Merge: Nitdoc: some cleaning and fixes.
authorJean Privat <jean@pryen.org>
Fri, 5 Sep 2014 10:34:42 +0000 (06:34 -0400)
committerJean Privat <jean@pryen.org>
Fri, 5 Sep 2014 10:34:42 +0000 (06:34 -0400)
Some small fixes for nitdoc before the introduction of new features.

No concrete impact on visual for now.

Pull-Request: #718
Reviewed-by: Jean Privat <jean@pryen.org>

91 files changed:
.gitignore
benchmarks/.gitignore
benchmarks/bench_common.sh
benchmarks/bench_engines.sh
src/nitpretty.nit [new file with mode: 0644]
tests/README [deleted file]
tests/README.md [new file with mode: 0644]
tests/README_alternatives.md [new file with mode: 0644]
tests/niti.skip
tests/nitpretty.args [new file with mode: 0644]
tests/sav/nitpretty.res [new file with mode: 0644]
tests/sav/nitpretty_args1.res [new file with mode: 0644]
tests/sav/nitpretty_args10.res [new file with mode: 0644]
tests/sav/nitpretty_args11.res [new file with mode: 0644]
tests/sav/nitpretty_args12.res [new file with mode: 0644]
tests/sav/nitpretty_args13.res [new file with mode: 0644]
tests/sav/nitpretty_args14.res [new file with mode: 0644]
tests/sav/nitpretty_args15.res [new file with mode: 0644]
tests/sav/nitpretty_args16.res [new file with mode: 0644]
tests/sav/nitpretty_args17.res [new file with mode: 0644]
tests/sav/nitpretty_args18.res [new file with mode: 0644]
tests/sav/nitpretty_args19.res [new file with mode: 0644]
tests/sav/nitpretty_args2.res [new file with mode: 0644]
tests/sav/nitpretty_args20.res [new file with mode: 0644]
tests/sav/nitpretty_args21.res [new file with mode: 0644]
tests/sav/nitpretty_args22.res [new file with mode: 0644]
tests/sav/nitpretty_args23.res [new file with mode: 0644]
tests/sav/nitpretty_args24.res [new file with mode: 0644]
tests/sav/nitpretty_args25.res [new file with mode: 0644]
tests/sav/nitpretty_args26.res [new file with mode: 0644]
tests/sav/nitpretty_args27.res [new file with mode: 0644]
tests/sav/nitpretty_args3.res [new file with mode: 0644]
tests/sav/nitpretty_args4.res [new file with mode: 0644]
tests/sav/nitpretty_args5.res [new file with mode: 0644]
tests/sav/nitpretty_args6.res [new file with mode: 0644]
tests/sav/nitpretty_args7.res [new file with mode: 0644]
tests/sav/nitpretty_args8.res [new file with mode: 0644]
tests/sav/nitpretty_args9.res [new file with mode: 0644]
tests/sav/zzz_test_args.res [new file with mode: 0644]
tests/sav/zzz_test_args_args1.res [new file with mode: 0644]
tests/sav/zzz_test_args_args2.res [new file with mode: 0644]
tests/sav/zzz_test_envvar.res [new file with mode: 0644]
tests/sav/zzz_test_in.res [new file with mode: 0644]
tests/sav/zzz_test_post_proc.res [new file with mode: 0644]
tests/sav/zzz_test_post_proc_args1.res [new file with mode: 0644]
tests/sav/zzz_test_write_args1.res [new file with mode: 0644]
tests/test_pretty/test_annot1.nit [new file with mode: 0644]
tests/test_pretty/test_attr1.nit [new file with mode: 0644]
tests/test_pretty/test_attr2.nit [new file with mode: 0644]
tests/test_pretty/test_call1.nit [new file with mode: 0644]
tests/test_pretty/test_call2.nit [new file with mode: 0644]
tests/test_pretty/test_class1.nit [new file with mode: 0644]
tests/test_pretty/test_class2.nit [new file with mode: 0644]
tests/test_pretty/test_class3.nit [new file with mode: 0644]
tests/test_pretty/test_comments1.nit [new file with mode: 0644]
tests/test_pretty/test_extern1.nit [new file with mode: 0644]
tests/test_pretty/test_if1.nit [new file with mode: 0644]
tests/test_pretty/test_if2.nit [new file with mode: 0644]
tests/test_pretty/test_if3.nit [new file with mode: 0644]
tests/test_pretty/test_indent1.nit [new file with mode: 0644]
tests/test_pretty/test_loop1.nit [new file with mode: 0644]
tests/test_pretty/test_loop2.nit [new file with mode: 0644]
tests/test_pretty/test_loop3.nit [new file with mode: 0644]
tests/test_pretty/test_mod1.nit [new file with mode: 0644]
tests/test_pretty/test_mod2.nit [new file with mode: 0644]
tests/test_pretty/test_mod3.nit [new file with mode: 0644]
tests/test_pretty/test_op1.nit [new file with mode: 0644]
tests/test_pretty/test_op2.nit [new file with mode: 0644]
tests/test_pretty/test_op3.nit [new file with mode: 0644]
tests/test_pretty/test_prims1.nit [new file with mode: 0644]
tests/test_pretty/test_prop1.nit [new file with mode: 0644]
tests/test_pretty/test_prop2.nit [new file with mode: 0644]
tests/test_pretty/test_prop3.nit [new file with mode: 0644]
tests/zzz_test_args.args [new file with mode: 0644]
tests/zzz_test_in.inputs [new file with mode: 0644]
tests/zzz_test_post_proc.args [new file with mode: 0644]
tests/zzz_test_write.args [new file with mode: 0644]
tests/zzz_tests/zzz_test_0k.nit
tests/zzz_tests/zzz_test_args.nit [new file with mode: 0644]
tests/zzz_tests/zzz_test_envvar.nit [new file with mode: 0644]
tests/zzz_tests/zzz_test_fail.nit
tests/zzz_tests/zzz_test_fixme.nit
tests/zzz_tests/zzz_test_fixme_changed.nit
tests/zzz_tests/zzz_test_fixme_remains.nit
tests/zzz_tests/zzz_test_in.nit [new file with mode: 0644]
tests/zzz_tests/zzz_test_nosav.nit
tests/zzz_tests/zzz_test_ok.nit
tests/zzz_tests/zzz_test_post_proc.nit [new file with mode: 0644]
tests/zzz_tests/zzz_test_soso.nit
tests/zzz_tests/zzz_test_todo.nit
tests/zzz_tests/zzz_test_write.nit [new file with mode: 0644]

index 8ed1a4e..65ac23a 100644 (file)
@@ -6,6 +6,7 @@ EIFGENs
 
 .nit_compile*
 .nitunit
+.nitpretty
 *.orig
 bin/nit*
 doc/stdlib
index 77d37a6..c85e49e 100644 (file)
@@ -1,4 +1,7 @@
 *.dat
 *.gnu
 *.bin
+*.png
+*.xml
+index.html
 nitg
index c600732..4ea5ffe 100644 (file)
@@ -37,9 +37,11 @@ function bench_command()
        echo "** [$title] $desc **"
        echo " $ $@"
 
+       failed=
+
        # Execute the commands $count times
        for i in `seq 1 "$count"`; do
-               /usr/bin/time -f "%U" -o "$timeout" -a "$@" > $outputopts 2>&1 || die "$1: failed"
+               /usr/bin/time -f "%U" -o "$timeout" -a "$@" > $outputopts 2>&1 || { failed=true; die "$1: failed"; }
                echo -n "$i. "
                tail -n 1 "$timeout"
        done
@@ -47,6 +49,13 @@ function bench_command()
        line=`compute_stats "$timeout"`
        echo "$line ($res)"
        echo $line >> "$res"
+
+       test -z "$xml" && return
+       echo >>"$xml" "<testcase classname='bench.`basename $res .dat`' name='$title' time='`echo $line | cut -f 1 -d " "`' timestamp='`date -Iseconds`'>"
+       if test -n "$failed"; then
+               echo >>"$xml" "<error message='Command failed'/>"
+       fi
+       echo >>"$xml" "</testcase>"
 }
 
 # Run a simble command witout storing the execution time
index abc65e3..385d033 100755 (executable)
@@ -26,8 +26,6 @@ source ./bench_plot.sh
 # Can be overrided with 'the option -n'
 count=2
 
-pep8analysis=../../pep8analysis
-
 ### HELPER FUNCTIONS ##
 
 function die()
@@ -56,19 +54,27 @@ function run_compiler()
                bench_command "bintrees" "bench_bintree_gen 16" "./bintrees.$title.bin" 16
        else
                run_command "$@" ../src/nitg.nit -o "nitg.$title.bin"
-               bench_command "nitg-g" "nitg --global --no-cc ../src/nitmetrics.nit" "./nitg.$title.bin" -v --global --no-cc ../src/nitmetrics.nit
+               bench_command "nitg-g" "nitg --global --no-cc ../src/nitls.nit" "./nitg.$title.bin" -v --global --no-cc ../src/nitls.nit
                bench_command "nitg-s" "nitg --separate ../src/nitg.nit" "./nitg.$title.bin" -v --no-cc --separate ../src/nitg.nit
                run_command "$@" ../src/nit.nit -o "nit.$title.bin"
-               bench_command "nit" "nit ../src/test_parser.nit ../src/rapid_type_analysis.nit" "./nit.$title.bin" -v ../src/test_parser.nit -- -n ../src/rapid_type_analysis.nit
+               bench_command "nit" "nit ../src/test_parser.nit ../src/nitls.nit" "./nit.$title.bin" -v ../src/test_parser.nit -- -n ../src/nitls.nit
+               run_command "$@" ../src/nitdoc.nit -o "nitdoc.$title.bin"
+               rm -r out 2> /dev/null
+               mkdir out 2> /dev/null
+               bench_command "nitdoc" "nitdoc ../src/nitls.nit" "./nitdoc.$title.bin" -v ../src/nitls.nit -d out
                run_command "$@" ../examples/shoot/src/shoot_logic.nit -o "shoot.$title.bin"
-               bench_command "shoot" "shoot_logic 30" "./shoot.$title.bin" 30
+               bench_command "shoot" "shoot_logic 15" "./shoot.$title.bin" 15
                run_command "$@" ../tests/bench_bintree_gen.nit -o "bintrees.$title.bin"
-               bench_command "bintrees" "bench_bintree_gen 18" "./bintrees.$title.bin" 18
-               if test -f "$pep8analysis/src/pep8analysis.nit"; then
-                       run_command "$@" "$pep8analysis/src/pep8analysis.nit" -I "$pep8analysis/lib" -o "pep8a.$title.bin"
-                       bench_command "pep8analisis" "bench_bintree_gen 18" "./pep8a.$title.bin" "$pep8analysis/tests/privat/"*.pep
-               fi
+               bench_command "bintrees" "bench_bintree_gen 17" "./bintrees.$title.bin" 17
+               #run_command "$@" "../contrib/pep8analysis/src/pep8analysis.nit" -o "pep8a.$title.bin"
+               #bench_command "pep8analisis" "bench_pep8analisis" "./pep8a.$title.bin" "../contrib/pep8analysis/tests/privat/"*.pep
+               run_command "$@" "../lib/ai/examples/queens.nit" -o "queens.$title.bin"
+               bench_command "queens" "bench_queens 13" "./queens.$title.bin" 13
+               run_command "$@" "../lib/ai/examples/puzzle.nit" -o "puzzle.$title.bin"
+               bench_command "puzzle" "puzzle 15-hard" "./puzzle.$title.bin" kleg.mondcafjhbi
        fi
+
+       rm -r *.bin .nit_compile out
 }
 
 ## HANDLE OPTIONS ##
@@ -97,6 +103,9 @@ while [ "$stop" = false ]; do
        esac
 done
 
+xml="bench_engines.xml"
+echo "<testsuites><testsuite>" > "$xml"
+
 NOTSKIPED="$*"
 
 if test -z "$NOTSKIPED"; then
@@ -107,8 +116,8 @@ fi
 
 ## COMPILE ENGINES
 
-# force to use the last nitg, not the bootstraped one
-test -f ./nitg || ../bin/nitg ../src/nitg.nit -v
+# get the bootstrapped nitg
+cp ../bin/nitg .
 
 ## EFFECTIVE BENCHS ##
 
@@ -163,8 +172,8 @@ function bench_nitg-g_options()
 
        plot "$name.gnu"
 }
-bench_nitg-g_options "slower" --hardening
-bench_nitg-g_options "nocheck" --no-check-covariance --no-check-attr-isset --no-check-assert --no-check-autocast --no-check-other
+bench_nitg-g_options "slower" --hardening --no-shortcut-range
+bench_nitg-g_options "nocheck" --no-check-null --no-check-autocast --no-check-attr-isset --no-check-covariance --no-check-assert
 
 function bench_nitg-s_options()
 {
@@ -190,9 +199,9 @@ function bench_nitg-s_options()
 
        plot "$name.gnu"
 }
-bench_nitg-s_options "slower" --hardening --no-inline-intern --no-union-attribute --no-shortcut-equal --no-shortcut-range "--no-gcc-directive likely" "--no-gcc-directive noreturn"
-bench_nitg-s_options "nocheck" --no-check-covariance --no-check-attr-isset --no-check-assert --no-check-autocast --no-check-other
-bench_nitg-s_options "faster" --inline-coloring-numbers --inline-some-methods --direct-call-monomorph "--inline-some-methods --direct-call-monomorph"
+bench_nitg-s_options "slower" --hardening --no-shortcut-equal --no-union-attribute --no-shortcut-range --no-inline-intern "--no-gcc-directive likely --no-gcc-directive noreturn"
+bench_nitg-s_options "nocheck" --no-check-null --no-check-autocast --no-check-attr-isset --no-check-covariance --no-check-assert
+bench_nitg-s_options "faster" --skip-dead-methods --inline-coloring-numbers --inline-some-methods --direct-call-monomorph "--inline-some-methods --direct-call-monomorph" ""
 
 function bench_nitg-e_options()
 {
@@ -218,20 +227,26 @@ function bench_nitg-e_options()
 
        plot "$name.gnu"
 }
-bench_nitg-e_options "slower" --hardening --no-inline-intern --no-union-attribute --no-shortcut-equal --no-shortcut-range
-bench_nitg-e_options "nocheck" --no-check-covariance --no-check-attr-isset --no-check-assert --no-check-autocast --no-check-other --no-check-erasure-cast
-bench_nitg-e_options "faster" --inline-coloring-numbers
+bench_nitg-e_options "slower" --hardening --no-shortcut-equal --no-union-attribute --no-shortcut-range --no-inline-intern
+bench_nitg-e_options "nocheck" --no-check-null --no-check-autocast --no-check-attr-isset --no-check-covariance --no-check-assert --no-check-erasure-cast
+bench_nitg-e_options "faster" --skip-dead-methods --inline-coloring-numbers --inline-some-methods --direct-call-monomorph --rta
 
 function bench_engines()
 {
        name="$FUNCNAME"
        skip_test "$name" && return
-       prepare_res "$name-nitg-g.dat" "nitg-g" "nitg with --global"
-       run_compiler "nitg-g" ./nitg --global
        prepare_res "$name-nitg-s.dat" "nitg-s" "nitg with --separate"
        run_compiler "nitg-s" ./nitg --separate
        prepare_res "$name-nitg-e.dat" "nitg-e" "nitg with --erasure"
        run_compiler "nitg-e" ./nitg --erasure
+       prepare_res "$name-nitg-sg.dat" "nitg-sg" "nitg with --separate --semi-global"
+       run_compiler "nitg-sg" ./nitg --separate --semi-global
+       prepare_res "$name-nitg-eg.dat" "nitg-eg" "nitg with --erasure --semi-global"
+       run_compiler "nitg-eg" ./nitg --erasure --semi-global
+       prepare_res "$name-nitg-egt.dat" "nitg-egt" "nitg with --erasure --semi-global --rta"
+       run_compiler "nitg-egt" ./nitg --erasure --semi-global --rta
+       prepare_res "$name-nitg-g.dat" "nitg-g" "nitg with --global"
+       run_compiler "nitg-g" ./nitg --global
        plot "$name.gnu"
 }
 bench_engines
@@ -240,10 +255,12 @@ function bench_nitg-e_gc()
 {
        name="$FUNCNAME"
        skip_test "$name" && return
-       prepare_res "$name-nitg-e-malloc.dat" "nitg-e-malloc" "nitg with --erasure and malloc"
-       NIT_GC_OPTION="malloc" run_compiler "nitg-e-malloc" ./nitg --erasure
        prepare_res "$name-nitg-e.dat" "nitg-e" "nitg with --erasure"
        run_compiler "nitg-e" ./nitg --erasure
+       prepare_res "$name-nitg-e-malloc.dat" "nitg-e-malloc" "nitg with --erasure and malloc"
+       NIT_GC_OPTION="malloc" run_compiler "nitg-e-malloc" ./nitg --erasure
+       prepare_res "$name-nitg-e-large.dat" "nitg-e-large" "nitg with --erasure and large"
+       NIT_GC_OPTION="large" run_compiler "nitg-e-large" ./nitg --erasure
        plot "$name.gnu"
 }
 bench_nitg-e_gc
@@ -318,6 +335,8 @@ if test -n "$html"; then
        echo >>"$html" "</body></html>"
 fi
 
+echo >>"$xml" "</testsuite></testsuites>"
+
 if test -n "$died"; then
        echo "Some commands failed"
        exit 1
diff --git a/src/nitpretty.nit b/src/nitpretty.nit
new file mode 100644 (file)
index 0000000..d49f60d
--- /dev/null
@@ -0,0 +1,2459 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# `nitpretty` is a tool able to pretty print Nit files.
+#
+# Usage:
+#
+#      nitpretty source.nit
+#
+# Main options:
+#
+# * `-o res.nit` output result into `res.nit`
+# * `--diff` show diff between `source` and `res`
+# * `--meld` open diff with `meld`
+# * `--check` check the format of multiple source files
+# * `--check --meld` perform `--check` and open `meld` for each difference
+#
+# ## Specification
+#
+# The specification of the pretty printing is described here.
+#
+# * Default indentation level is one `'\t'` character and
+# is increased by one for each indentation level.
+# * Default line max-size is 80.
+#
+# ### Comments
+#
+# There is many categories of comments:
+#
+# `Licence comments` are attached to the top of the file
+# no blank line before, one after.
+#
+#     # This is a licence comment
+#
+#     # Documentation for module `foo`
+#     module foo
+#
+# `ADoc` are documentation comments attached to a `AModule`, `AClassdef`, `APropdef`.
+#
+# They are printed before the definition with a blank line before and no after
+# at the same indentation level than the definition.
+#
+#     # Documentation for module `foo`
+#     module foo
+#
+#     # Documentation for class `Bar`
+#     class Bar
+#          # Documentation for method `baz`
+#          fun baz do end
+#     end
+#
+# `Block comments` are comments composed of one or more line rattached to nothing.
+# They are displayed with one blank line before and after at current indent level.
+#
+#     <blank>
+#     # block
+#     # comment
+#     <blank>
+#
+# `Attached comments` are comments attached to a production.
+# They are printed as this.
+#
+#     fun foo do # attached comment
+#     end
+#
+# `nitpretty` automatically remove multiple blanks between comments:
+#
+#     # Licence
+#     # ...
+#     <blank>
+#     # Block comment
+#
+# ### Inlining
+#
+# Productions are automatically inlined when possible.
+#
+# Conditions:
+#
+# * the production must be syntactically inlinable
+# * the inlined production length is less than `PrettyPrinterVisitor::max-size`
+# * the production do not contains any comments
+#
+# ### Modules
+#
+# * There is a blank between the module declaration and its imports
+# * There is no blank between imports and only one after
+# * There is a blank between each extern block definition
+# * There is a blank between each class definition
+# * There is no blank line at the end of the module
+#
+#     # Documentation for module `foo`
+#     module foo
+#
+#     import a
+#     # import b
+#     import c
+#
+#     # Documentation for class `Bar`
+#     class Bar end
+#
+#     class Baz end # not a `ADoc` comment
+#
+#
+# ### Classes
+#
+# * There is no blank between the class definition and its super-classes declarations
+# * There is no blank between two inlined property definition
+# * There is a blank between each block definition
+# * There no blank line at the end of the class definition
+#
+#     # Documentation for class `Bar`
+#     class Bar end
+#
+#     class Baz
+#          super Bar
+#
+#          fun a is abstract
+#          private fun b do end
+#
+#          fun c do
+#               # ...
+#          end
+#     end
+#
+# Generic types have no espace after or before brackets and are separated by a comma and a space:
+#
+#     class A[E: Type1, F: Type1] do end
+#
+# ### Blocks
+#
+# * Inlined productions have no blank lines between them
+# * Block productions have a blank before and after
+#
+#     var a = 10
+#     var b = 0
+#
+#     if a > b then
+#          # is positive
+#          print "positive"
+#     end
+#
+#     print "end"
+#
+# ### Calls and Binary Ops
+#
+# Arguments are always printed separated with a comma and a space:
+#
+#     foo(a, b, c)
+#
+# Binary ops are always printed wrapped with spaces:
+#
+#     var c = 1 + 2
+#
+# Calls and binary ops can be splitted to fit the `max-size` constraint.
+# Breaking priority is given to arguments declaration after the comma.
+#
+#     return foo("aaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbb",
+#        "cccccccccccccccccccccccccc")
+#
+# Binary ops can also be broken to fit the `max-size` limit:
+#
+#     return "aaaaaaaaaaaaaaaaaaaaaaaaaa" + "bbbbbbbbbbbbbbbbbbbbbbbbbbb" +
+#        "cccccccccccccccccccccccccc"
+#
+module nitpretty
+
+import template
+import toolcontext
+import modelbuilder
+import astutil
+
+# The `PrettyPrinterVisitor` is used to visit a node and pretty print it.
+#
+# The main method here is `visit` that performs the pretty printing of a `ANode`.
+#
+# Because some tokens like `TComment` are not stored in the AST,
+# we visit the AST like traditionnal visitor and also maintain a
+# pointer to the `current_token` (actually the next one to be printed).
+#
+# Visited productions are in charges to move the token pointer using methods such as:
+#
+# * `consume`: print `current_token` and move to the next one
+# * `skip`: move to the next token without printing the current one
+# * `skip_to`: move to a specified token skipping all the tokens before
+# * `catch_up`: consume all the tokens between `current_token` and a specified token
+# * `finish_line`: consume all the tokens between `current_token` and the end of line
+class PrettyPrinterVisitor
+       # Pretty print `n`.
+       fun pretty(n: ANode): Template do
+               clear
+               n.parentize_tokens
+
+               if n isa Prod then
+                       current_token = n.first_token
+                       visit n
+               else if n isa Token then
+                       var p = n.parent
+
+                       while p != null and not p isa Prod do
+                               p = p.parent
+                       end
+
+                       current_token = p.first_token
+                       visit p
+               end
+
+               return tpl.as(not null)
+       end
+
+       # Pretty print the whole `nmodule` with comments before and after.
+       fun pretty_nmodule(nmodule: AModule): Template do
+               clear
+               nmodule.parentize_tokens
+               current_token = nmodule.location.file.first_token
+               visit nmodule
+               catch_up nmodule.location.file.last_token
+               tpl.add "\n"
+               return tpl.as(not null)
+       end
+
+       # Prepare `self` for a new visit.
+       private fun clear do
+               tpl = new Template
+               current_token = null
+               indent = 0
+               current_length = 0
+               previous_length = 0
+               wait_addn = 0
+       end
+
+       # Visit `n` if not null.
+       fun visit(n: nullable ANode) do
+               if n == null then return
+               n.accept_pretty_printer self
+       end
+
+       # Visit a list of `Anode`.
+       fun visit_list(n: nullable ANodes[ANode]) do
+               if n == null then return
+               n.accept_pretty_printer self
+       end
+
+       # Is the node inlinable and can fit on the line.
+       fun can_inline(n: nullable ANode): Bool do
+               if n == null then return true
+               if n.must_be_inline then return true
+               if n.must_be_block then return false
+               # check length
+               if n.collect_length + current_length > max_size then return false
+               # check block is inlinable
+               return n.is_inlinable
+       end
+
+       # Collect all `TComment` between `from` and `to`.
+       fun collect_comments(from: nullable ANode, to: nullable ANode): Array[TComment] do
+               var res = new Array[TComment]
+               if from isa Prod then from = from.first_token
+               if to isa Prod then to = to.first_token
+               if from == null or to == null then return res
+
+               while from != to do
+                       if from isa TComment then res.add from
+                       from = from.as(Token).next_token
+               end
+
+               return res
+       end
+
+       # Token under cursor.
+       #
+       # This is the next token to visit.
+       var current_token: nullable Token = null
+
+       # Skip the `current_token`.
+       fun skip do current_token = current_token.next_token
+
+       # Skip `current_token` until the end of line.
+       fun skip_line do current_token = current_token.last_real_token_in_line
+
+       # Skip `current_token` until `target` is reached.
+       fun skip_to(target: nullable Token) do
+               if target == null then return
+               while current_token != target do skip
+       end
+
+       # Visit `current_token`.
+       fun consume(token: String) do
+               assert current_token.text == token
+               visit current_token
+       end
+
+       # Is there token to visit between `current_token` and `target`?
+       fun need_catch_up(target: nullable Token): Bool do
+               if target == null then return false
+               return current_token != target
+       end
+
+       # Visit all tokens between `current_token` and `target`.
+       fun catch_up(target: nullable ANode) do
+               if target == null then return
+               if current_token == null then return
+               var token: Token
+               if target isa Token then
+                       token = target
+               else if target isa Prod then
+                       token = target.first_token.as(not null)
+               else
+                       abort
+               end
+               assert current_token.location <= token.location
+               while current_token != token do visit current_token
+       end
+
+       # Visit all tokens between `current_token` and the end of line.
+       fun finish_line do
+               if current_token isa TComment then
+                       adds
+                       visit current_token
+               end
+
+               while current_token isa TEol do skip
+       end
+
+       # The template under construction.
+       private var tpl: nullable Template = null
+
+       # Current indent level.
+       var indent = 0
+
+       # Size of a tabulation in spaces.
+       var tab_size = 8
+
+       # Max line size.
+       var max_size = 80
+
+       # Length of the current line.
+       var current_length = 0
+
+       # Length of the previous line.
+       var previous_length = 0
+
+       # Is the last line a blank line?
+       fun last_line_is_blank: Bool do return previous_length == 0
+
+       # Add `t` to current template.
+       fun add(t: String) do
+               if t.is_empty then return
+               while wait_addn > 0 do
+                       tpl.add "\n"
+                       wait_addn -= 1
+               end
+               tpl.add t
+               current_length += t.length
+       end
+
+       # Add a `'\n'`.
+       fun addn do
+               if current_length == 0 and last_line_is_blank then return
+               previous_length = current_length
+               current_length = 0
+               wait_addn += 1
+       end
+
+       # End of line chars are stored until another char is added.
+       # This avoid empty files with only a '`\n`'.
+       private var wait_addn = 0
+
+       # Add `'\t' * indent`.
+       fun addt do add "\t" * indent
+
+       # Add a space.
+       fun adds do add " "
+
+       fun visit_recv(n_expr: AExpr) do
+               if not n_expr isa AImplicitSelfExpr then
+                       visit n_expr
+                       consume "."
+               end
+       end
+end
+
+# Base framework redefs
+
+redef class ANodes[E]
+       private fun accept_pretty_printer(v: PrettyPrinterVisitor) do
+               for e in self do
+                       var e_can_inline = v.can_inline(e)
+
+                       if e != first then
+                               if not e_can_inline then
+                                       v.add ","
+                                       v.addn
+                                       v.addt
+                                       v.addt
+                               else
+                                       v.add ", "
+                               end
+                       end
+
+                       v.visit e
+               end
+       end
+end
+
+redef class ANode
+       # Start visit of `self` using a `PrettyPrinterVisitor`
+       private fun accept_pretty_printer(v: PrettyPrinterVisitor) is abstract
+
+       # Collect the length (in `Char`) of the node.
+       private fun collect_length: Int is abstract
+
+       # Is `self` printable in one line?
+       private fun is_inlinable: Bool do return true
+
+       # Force `self` to be rendered as a block.
+       private var force_block = false
+
+       # Does `self` have to be rendered as a block?
+       private fun must_be_block: Bool do return force_block
+
+       # Force `self` to be rendered as a line.
+       private var force_inline = false
+
+       # Does `self` have be rendered as a line?
+       private fun must_be_inline: Bool do
+               if parent != null and parent.must_be_inline then return true
+               return force_inline
+       end
+
+       # Does `self` was written in one line before transformation?
+       private fun was_inline: Bool is abstract
+end
+
+redef class Token
+       redef fun accept_pretty_printer(v) do
+               v.add text.trim
+               v.current_token = next_token
+       end
+
+       redef fun collect_length do return text.length
+       redef fun is_inlinable do return true
+       redef fun was_inline do return true
+end
+
+redef class Prod
+       redef fun accept_pretty_printer(v) do v.visit first_token
+
+       # The token where the production really start (skipping ADoc).
+       private fun start_token: nullable Token do return first_token
+
+       # Collect all `TComment` contained in the production
+       # (between `start_token` and `end_token`).
+       private fun collect_comments: Array[TComment] do
+               var res = new Array[TComment]
+               if start_token == null or last_token == null then return res
+               var token = start_token
+
+               while token != last_token do
+                       if token isa TComment then res.add token
+                       token = token.next_token
+               end
+
+               return res
+       end
+
+       redef fun collect_length do
+               var res = 0
+               if start_token == null or last_token == null then return res
+               var token = start_token
+
+               while token != last_token do
+                       res += token.text.length
+                       token = token.next_token
+               end
+
+               res += token.text.length
+               return res
+       end
+
+       redef fun was_inline do
+               return first_token.location.line_start == last_token.location.line_end
+       end
+end
+
+# Comments
+
+redef class TComment
+       redef fun accept_pretty_printer(v) do
+               if is_adoc then
+                       v.addt
+                       super
+                       v.addn
+                       return
+               end
+
+               if is_licence then
+                       super
+                       v.addn
+                       if is_last_in_group then v.addn
+                       return
+               end
+
+               if is_orphan then
+                       v.addn
+                       v.addt
+                       super
+                       v.addn
+                       v.addn
+                       return
+               end
+
+               if is_inline then
+                       if next_token isa TComment and is_first_in_group then v.addn
+                       v.addt
+                       super
+                       v.addn
+                       var prev_token = self.prev_token
+                       if prev_token isa TComment and prev_token.is_inline and is_last_in_group then v.addn
+                       return
+               end
+
+               super
+       end
+
+       # Is `self` part of an `ADoc`?
+       private fun is_adoc: Bool do return parent isa ADoc and parent.parent != null
+
+       # Is `self` part of a licence?
+       private fun is_licence: Bool do
+               var prev_token = self.prev_token
+
+               if prev_token == null then
+                       return true
+               else if prev_token isa TComment then
+                       return prev_token.is_licence
+               else
+                       return false
+               end
+       end
+
+       # Is `self` starts and ends its line?
+       private fun is_inline: Bool do
+               return self == first_real_token_in_line and self == last_real_token_in_line
+       end
+
+       # Is `self` an orphan line (blank before and after)?
+       private fun is_orphan: Bool do
+               return prev_token isa TEol and
+                  (prev_token.prev_token isa TEol or prev_token.prev_token isa TComment) and
+                  next_token isa TEol
+       end
+
+       # Is `self` the first comment of a group of comment?
+       private fun is_first_in_group: Bool do return not prev_token isa TComment
+
+       # Is `self` the last comment of a group of comments?
+       private fun is_last_in_group: Bool do return not next_token isa TComment
+end
+
+redef class ADoc
+       redef fun accept_pretty_printer(v) do for comment in n_comment do v.visit comment
+       redef fun is_inlinable do return n_comment.length <= 1
+end
+
+# Annotations
+
+redef class AAnnotations
+       redef fun accept_pretty_printer(v) do
+               v.adds
+               v.consume "is"
+
+               if v.can_inline(self) then
+                       v.adds
+                       for n_item in n_items do
+                               v.visit n_item
+                               if n_item != n_items.last then
+                                       v.add ", "
+                               end
+                       end
+                       v.finish_line
+               else if n_items.length > 1 then
+                       v.addn
+                       v.indent += 1
+
+                       for n_item in n_items do
+                               v.addt
+                               v.visit n_item
+                               v.finish_line
+                               v.addn
+                       end
+
+                       v.indent -= 1
+               end
+               if not was_inline and v.current_token isa TKwend then v.skip
+       end
+
+       redef fun is_inlinable do
+               if not super then return false
+               for annot in n_items do if not annot.is_inlinable then return false
+               return true
+       end
+end
+
+redef class AAnnotation
+       redef fun accept_pretty_printer(v) do
+               v.visit n_atid
+               if not n_args.is_empty then
+                       v.visit n_opar
+                       v.visit_list n_args
+                       v.visit n_cpar
+               end
+       end
+end
+
+redef class ATypeAtArg
+       redef fun accept_pretty_printer(v) do v.visit n_type
+end
+
+redef class AExprAtArg
+       redef fun accept_pretty_printer(v) do v.visit n_expr
+end
+
+# Modules
+
+redef class AModule
+       redef fun accept_pretty_printer(v) do
+               v.catch_up start_token
+               v.visit n_moduledecl
+
+               if not n_imports.is_empty then
+                       v.addn
+
+                       for n_import in n_imports do
+                               v.catch_up n_import
+                               v.visit n_import
+                       end
+               end
+
+               if not n_extern_code_blocks.is_empty then
+                       v.addn
+
+                       for n_extern_block in n_extern_code_blocks do
+                               v.catch_up n_extern_block
+                               v.visit n_extern_block
+                               v.addn
+                               if n_extern_block != n_extern_code_blocks.last then v.addn
+                       end
+
+                       if not n_classdefs.is_empty then v.addn
+               end
+
+               if not n_classdefs.is_empty then
+                       v.addn
+
+                       for n_classdef in n_classdefs do
+                               v.catch_up n_classdef
+                               v.visit n_classdef
+                               if n_classdef != n_classdefs.last then v.addn
+                       end
+               end
+
+               assert v.indent == 0
+       end
+
+       # Skip doc if any.
+       redef fun start_token do
+               if n_moduledecl != null then return n_moduledecl.first_token
+               if not n_imports.is_empty then return n_imports.first.first_token
+               if not n_classdefs.is_empty then return n_classdefs.first.first_token
+               return first_token
+       end
+
+       redef fun is_inlinable do return false
+end
+
+redef class AModuledecl
+       redef fun accept_pretty_printer(v) do
+               v.visit n_doc
+               v.visit n_kwmodule
+               v.adds
+               v.visit n_name
+
+               if n_annotations != null then
+                       var annot_inline = v.can_inline(n_annotations)
+                       v.visit n_annotations
+
+                       if not annot_inline then
+                               if v.current_token isa TKwend then
+                                       v.consume "end"
+                                       v.finish_line
+                               else
+                                       v.add "end"
+                               end
+                       end
+               end
+
+               v.finish_line
+               v.addn
+       end
+end
+
+redef class AModuleName
+       redef fun accept_pretty_printer(v) do
+               for path in n_path do
+                       v.visit path
+                       v.add "::"
+               end
+
+               v.visit n_id
+       end
+end
+
+redef class ANoImport
+       redef fun accept_pretty_printer(v) do
+               v.visit n_kwimport
+               v.adds
+               v.visit n_kwend
+               v.finish_line
+               v.addn
+       end
+end
+
+redef class AStdImport
+       redef fun accept_pretty_printer(v) do
+               if not n_visibility isa APublicVisibility then
+                       v.visit n_visibility
+                       v.adds
+               end
+
+               v.visit n_kwimport
+               v.adds
+               v.visit n_name
+               v.finish_line
+               v.addn
+       end
+end
+
+# Classes
+
+redef class AClassdef
+       redef fun accept_pretty_printer(v) do
+               for n_propdef in n_propdefs do
+                       v.catch_up n_propdef
+
+                       if n_propdef.n_doc != null or not v.can_inline(n_propdef) then
+                               if n_propdef != n_propdefs.first then v.addn
+                               v.visit n_propdef
+                               if n_propdef != n_propdefs.last then v.addn
+                       else
+                               v.visit n_propdef
+                       end
+               end
+       end
+end
+
+redef class AStdClassdef
+       redef fun accept_pretty_printer(v) do
+               v.visit n_doc
+               var can_inline = v.can_inline(self)
+
+               if not n_visibility isa APublicVisibility then
+                       v.visit n_visibility
+                       v.adds
+               end
+
+               if n_kwredef != null then
+                       v.visit n_kwredef
+                       v.adds
+               end
+
+               v.visit n_classkind
+               v.adds
+               v.visit n_id
+
+               if not n_formaldefs.is_empty then
+                       v.consume "["
+                       v.visit_list n_formaldefs
+                       v.consume "]"
+               end
+
+               if n_extern_code_block != null then
+                       v.adds
+                       v.visit n_extern_code_block
+               end
+
+               if can_inline then
+                       v.adds
+
+                       if not n_superclasses.is_empty then
+                               for n_superclass in n_superclasses do
+                                       v.visit n_superclass
+                                       v.adds
+                               end
+                       end
+               else
+                       v.finish_line
+                       v.addn
+                       v.indent += 1
+
+                       for n_superclass in n_superclasses do
+                               v.catch_up n_superclass
+                               v.addt
+                               v.visit n_superclass
+                               v.finish_line
+                               v.addn
+                       end
+
+                       if not n_superclasses.is_empty and not n_propdefs.is_empty then
+                               v.addn
+                       end
+
+                       super
+                       v.catch_up n_kwend
+                       v.indent -= 1
+               end
+
+               v.visit n_kwend
+               v.finish_line
+               v.addn
+               assert v.indent == 0
+       end
+
+       redef fun is_inlinable do
+               if not super then return false
+               if not n_propdefs.is_empty then return false
+               if n_superclasses.length > 1 then return false
+               if not collect_comments.is_empty then return false
+               return true
+       end
+
+       redef fun start_token do
+               if not n_visibility isa APublicVisibility then return n_visibility.first_token
+               if n_kwredef != null then return n_kwredef
+               return n_classkind.first_token
+       end
+end
+
+redef class AAbstractClasskind
+       redef fun accept_pretty_printer(v) do
+               v.visit n_kwabstract
+               v.adds
+               v.visit n_kwclass
+       end
+end
+
+redef class AExternClasskind
+       redef fun accept_pretty_printer(v) do
+               v.visit n_kwextern
+               v.adds
+               v.visit n_kwclass
+       end
+end
+
+redef class AFormaldef
+       redef fun accept_pretty_printer(v) do
+               v.visit n_id
+
+               if n_type != null then
+                       v.consume ":"
+                       v.adds
+                       v.visit n_type
+               end
+       end
+end
+
+redef class AType
+       redef fun accept_pretty_printer(v) do
+               if n_kwnullable != null then
+                       v.visit n_kwnullable
+                       v.adds
+               end
+
+               v.visit n_id
+
+               if not n_types.is_empty then
+                       v.consume "["
+                       v.visit_list n_types
+                       v.consume "]"
+               end
+       end
+end
+
+redef class ASuperclass
+       redef fun accept_pretty_printer(v) do
+               v.visit n_kwsuper
+               v.adds
+               v.visit n_type
+       end
+end
+
+# Properties
+
+redef class APropdef
+       redef fun accept_pretty_printer(v) do
+               v.visit n_doc
+               v.addt
+
+               if not n_visibility isa APublicVisibility then
+                       v.visit n_visibility
+                       v.adds
+               end
+
+               if n_kwredef != null then
+                       v.visit n_kwredef
+                       v.adds
+               end
+       end
+
+       redef fun start_token do
+               if n_doc == null then return super
+               return n_doc.last_token.next_token
+       end
+end
+
+redef class AAttrPropdef
+       redef fun accept_pretty_printer(v) do
+               super
+               v.visit n_kwvar
+               v.adds
+               if n_id != null then v.visit n_id
+               if n_id2 != null then v.visit n_id2
+
+               if n_type != null then
+                       v.consume ":"
+                       v.adds
+                       v.visit n_type
+               end
+
+               if n_readable != null then
+                       v.adds
+                       v.visit n_readable
+               end
+
+               if n_writable != null then
+                       v.adds
+                       v.visit n_writable
+               end
+
+               if n_expr != null then
+                       v.adds
+                       v.consume "="
+                       v.adds
+                       v.visit n_expr
+               end
+
+               if n_annotations != null then v.visit n_annotations
+               v.finish_line
+               v.addn
+       end
+
+       redef fun first_token do
+               if n_doc != null then return n_doc.first_token
+               if not n_visibility isa APublicVisibility then return n_visibility.first_token
+               if n_kwredef != null then return n_kwredef
+               return n_kwvar
+       end
+
+       redef fun is_inlinable do return true
+end
+
+redef class ATypePropdef
+       redef fun accept_pretty_printer(v) do
+               super
+               v.visit n_kwtype
+               v.adds
+               v.visit n_id
+               v.consume ":"
+               v.adds
+               v.visit n_type
+               v.finish_line
+               v.addn
+       end
+
+       redef fun is_inlinable do return true
+end
+
+redef class AMethPropdef
+       redef fun accept_pretty_printer(v) do
+               super
+               if n_kwinit != null then v.visit n_kwinit
+               if n_kwmeth != null then v.visit n_kwmeth
+               if n_kwnew != null then v.visit n_kwnew
+
+               if not n_methid == null then
+                       v.adds
+                       v.visit n_methid
+               end
+
+               v.visit n_signature
+
+               if n_annotations != null then
+                       v.visit n_annotations
+               else
+                       v.adds
+               end
+       end
+
+       # Can be inlined if:
+       # * block is empty or can be inlined
+       # * contains no comments
+       redef fun is_inlinable do
+               if not super then return false
+               if n_annotations != null and not n_annotations.is_inlinable then return false
+               if n_block != null and not n_block.is_inlinable then return false
+               if not collect_comments.is_empty then return false
+               return true
+       end
+end
+
+redef class AMainMethPropdef
+       redef fun accept_pretty_printer(v) do
+               v.visit n_block
+               v.addn
+       end
+end
+
+redef class ADeferredMethPropdef
+       redef fun accept_pretty_printer(v) do
+               super
+               if n_annotations == null then
+                       while not v.current_token isa TKwis do v.skip
+                       v.consume "is"
+                       v.adds
+                       while not v.current_token isa TKwabstract do v.skip
+                       v.consume "abstract"
+               end
+               v.finish_line
+               v.addn
+       end
+end
+
+redef class AExternPropdef
+       redef fun accept_pretty_printer(v) do
+               super
+               while v.current_token isa TEol do v.skip
+
+               if v.current_token isa TKwis then
+                       v.consume "is"
+                       v.adds
+               end
+
+               if v.current_token isa TKwextern then
+                       v.consume "extern"
+                       v.adds
+               end
+
+               if n_extern != null then v.visit n_extern
+               if n_extern_calls != null then v.visit n_extern_calls
+               if n_extern_code_block != null then v.visit n_extern_code_block
+               v.finish_line
+               v.addn
+       end
+
+       redef fun is_inlinable do
+               if not super then return false
+               if n_block != null and not n_block.is_inlinable then return false
+               if n_extern_calls != null and not n_extern_calls.is_inlinable then return false
+               if n_extern_code_block != null and not n_extern_code_block.is_inlinable then return false
+               return true
+       end
+
+       redef fun must_be_inline do
+               if super then return true
+               return n_extern != null
+       end
+end
+
+redef class AInternMethPropdef
+       redef fun accept_pretty_printer(v) do
+               super
+               v.consume "is"
+               v.adds
+               v.consume "intern"
+               v.finish_line
+               v.addn
+       end
+end
+
+redef class AConcreteMethPropdef
+       redef fun accept_pretty_printer(v) do
+               var before = v.indent
+               var can_inline = v.can_inline(self)
+               super
+               var n_block = self.n_block
+
+               if n_block != null then
+                       while not v.current_token isa TKwdo do v.skip
+                       if n_annotations != null then
+                               if v.can_inline(n_annotations) then
+                                       v.adds
+                               else
+                                       v.addt
+                               end
+                       end
+                       v.consume "do"
+
+                       if can_inline then
+                               v.adds
+
+                               if n_block isa ABlockExpr then
+                                       if n_block.n_expr.is_empty then
+                                               v.visit n_block.n_kwend
+                                       else
+                                               v.visit n_block.n_expr.first
+                                               v.current_token = n_block.n_kwend
+                                               v.skip
+                                       end
+                               else
+                                       v.visit n_block
+                                       if v.current_token isa TKwend then v.skip
+                               end
+                       else
+                               v.finish_line
+                               v.addn
+                               v.indent += 1
+
+                               if n_block isa ABlockExpr then
+                                       n_block.force_block = true
+                                       v.visit n_block
+                                       v.catch_up n_block.n_kwend
+                               else
+                                       v.addt
+                                       v.visit n_block
+                                       v.addn
+                               end
+
+                               v.indent -= 1
+                               v.addt
+                               if n_block isa ABlockExpr then
+                                       v.visit n_block.n_kwend
+                               else
+                                       v.add "end"
+                               end
+                       end
+               end
+
+               v.finish_line
+               v.addn
+               assert v.indent == before
+       end
+end
+
+redef class ASignature
+       redef fun accept_pretty_printer(v) do
+               if not n_params.is_empty then
+                       v.consume "("
+                       v.visit_list n_params
+                       v.consume ")"
+               end
+
+               if n_type != null then
+                       v.consume ":"
+                       v.adds
+                       v.visit n_type
+               end
+       end
+end
+
+redef class AParam
+       redef fun accept_pretty_printer(v) do
+               v.visit n_id
+
+               if n_type != null then
+                       v.consume ":"
+                       v.adds
+                       v.visit n_type
+               end
+
+               if n_dotdotdot != null then v.visit n_dotdotdot
+       end
+end
+
+# Extern
+
+redef class AExternCalls
+       redef fun accept_pretty_printer(v) do
+               var can_inline = v.can_inline(self)
+               v.visit n_kwimport
+
+               if can_inline then
+                       v.adds
+                       v.visit_list n_extern_calls
+               else
+                       v.addn
+                       v.addt
+                       v.addt
+                       v.visit_list n_extern_calls
+               end
+
+               v.adds
+       end
+end
+
+redef class AFullPropExternCall
+       redef fun accept_pretty_printer(v) do
+               v.visit n_type
+               v.visit n_dot
+               v.visit n_methid
+       end
+end
+
+redef class ALocalPropExternCall
+       redef fun accept_pretty_printer(v) do v.visit n_methid
+end
+
+redef class AInitPropExternCall
+       redef fun accept_pretty_printer(v) do v.visit n_type
+end
+
+redef class ACastAsExternCall
+       redef fun accept_pretty_printer(v) do
+               v.visit n_from_type
+               v.visit n_dot
+               v.visit n_kwas
+               v.consume "("
+               v.visit n_to_type
+               v.consume ")"
+       end
+end
+
+redef class AAsNullableExternCall
+       redef fun accept_pretty_printer(v) do
+               v.visit n_type
+               v.consume "."
+               v.visit n_kwas
+               v.adds
+               v.visit n_kwnullable
+       end
+end
+
+redef class AAsNotNullableExternCall
+       redef fun accept_pretty_printer(v) do
+               v.visit n_type
+               v.consume "."
+               v.visit n_kwas
+               v.adds
+               v.visit n_kwnot
+               v.adds
+               v.visit n_kwnullable
+       end
+end
+
+redef class AExternCodeBlock
+       redef fun accept_pretty_printer(v) do
+               if n_in_language != null then
+                       v.visit n_in_language
+                       v.adds
+               end
+
+               v.visit n_extern_code_segment
+       end
+
+       redef fun is_inlinable do
+               if not super then return false
+               return n_extern_code_segment.is_inlinable
+       end
+end
+
+redef class AInLanguage
+       redef fun accept_pretty_printer(v) do
+               v.visit n_kwin
+               v.adds
+               v.visit n_string
+       end
+end
+
+redef class TExternCodeSegment
+       redef fun accept_pretty_printer(v) do
+               var can_inline = v.can_inline(self)
+
+               if can_inline then
+                       super
+               else
+                       var text = text.substring(2, text.length - 4)
+                       var lines = text.r_trim.split("\n")
+
+                       if text.is_empty then
+                               v.add "`\{`\}"
+                       else
+                               v.add "`\{"
+
+                               if not lines.first.trim.is_empty then
+                                       v.addn
+                                       lines.first.l_trim
+                                       v.indent += 1
+                                       v.addt
+                                       v.indent -= 1
+                               end
+
+                               for line in lines do
+                                       v.add line.r_trim
+                                       v.addn
+                               end
+
+                               v.addt
+                               v.add "`\}"
+                       end
+
+                       v.current_token = next_token
+               end
+       end
+
+       redef fun is_inlinable do
+               if not super then return false
+               return location.line_start == location.line_end
+       end
+end
+
+# Blocks
+
+redef class ABlockExpr
+       redef fun accept_pretty_printer(v) do
+               var before = v.indent
+               var can_inline = v.can_inline(self)
+
+               if can_inline and not n_expr.is_empty then
+                       v.visit n_expr.first
+                       v.finish_line
+               else
+                       for nexpr in n_expr do
+                               var expr_inline = v.can_inline(nexpr)
+                               if not expr_inline and nexpr != n_expr.first then v.addn
+                               v.catch_up nexpr
+                               v.addt
+                               v.visit nexpr
+                               v.finish_line
+                               v.addn
+                               if not expr_inline and nexpr != n_expr.last then v.addn
+                       end
+               end
+
+               assert v.indent == before
+       end
+
+       redef fun is_inlinable do
+               if not super then return false
+               if not collect_comments.is_empty then return false
+
+               if not n_expr.is_empty then
+                       if n_expr.length > 1 then return false
+                       if not n_expr.first.is_inlinable then return false
+               end
+
+               return true
+       end
+end
+
+redef class AIfExpr
+       redef fun accept_pretty_printer(v) do
+               var before = v.indent
+               var can_inline = v.can_inline(self)
+               v.visit n_kwif
+               v.adds
+
+               if v.can_inline(n_expr) then
+                       v.visit n_expr
+                       v.adds
+               else
+                       v.visit n_expr
+                       v.addn
+                       v.addt
+               end
+
+               # skip comments before `then` token
+               while not v.current_token isa TKwthen do v.skip
+               v.consume "then"
+               var n_else = self.n_else
+
+               if can_inline then
+                       v.adds
+                       if n_then != null then v.visit n_then
+
+                       if has_else(v) then
+                               n_else.force_inline = true
+                               v.adds
+                               v.consume "else"
+                               v.adds
+                               v.visit n_else
+                       else if n_then == null then
+                               v.add "end"
+                       end
+
+                       v.skip_to last_token.last_real_token_in_line
+               else
+                       v.finish_line
+                       v.addn
+                       v.indent += 1
+
+                       if n_then != null then
+                               if n_then isa ABlockExpr then
+                                       n_then.force_block = true
+                                       v.visit n_then
+                               else
+                                       v.addt
+                                       v.visit n_then
+                                       v.addn
+                               end
+                       end
+
+                       if has_else(v) then
+                               while not v.current_token isa TKwelse do
+                                       v.consume v.current_token.text
+                               end
+
+                               v.indent -= 1
+                               v.addt
+                               v.consume "else"
+
+                               if n_else isa AIfExpr then
+                                       n_else.force_block = true
+                                       v.adds
+                                       v.visit n_else
+                               else
+                                       v.finish_line
+                                       v.addn
+                                       v.indent += 1
+
+                                       if n_else isa ABlockExpr then
+                                               n_else.force_block = true
+                                               v.visit n_else
+                                       else
+                                               v.addt
+                                               v.visit n_else
+                                               v.addn
+                                       end
+
+                                       if last_token isa TKwend then
+                                               v.catch_up last_token
+                                               v.indent -= 1
+                                               v.addt
+                                               v.consume "end"
+                                       else
+                                               v.indent -= 1
+                                               v.addt
+                                               v.add "end"
+                                       end
+                               end
+                       else
+                               if last_token.location >= v.current_token.location then v.catch_up last_token
+                               v.indent -= 1
+                               v.addt
+                               v.add "end"
+                               if v.current_token isa TKwend then v.skip
+                       end
+               end
+
+               assert v.indent == before
+       end
+
+       redef fun is_inlinable do
+               if not super then return false
+               if n_then != null and not n_then.is_inlinable then return false
+               var n_else = self.n_else
+               if (n_else isa ABlockExpr and not n_else.n_expr.is_empty) or
+                  (not n_else isa ABlockExpr and n_else != null) then
+                       return false
+               end
+               if not collect_comments.is_empty then return false
+               return true
+       end
+
+       # Does this `if` statement contains a `else` part?
+       private fun has_else(v: PrettyPrinterVisitor): Bool do
+               var n_else = n_else
+               if n_else == null then return false
+               var n_kwelse = collect_kwelse
+               if n_kwelse == null then return false
+
+               if n_else isa ABlockExpr then
+                       var comments: Array[TComment]
+
+                       if n_then == null then
+                               comments = v.collect_comments(n_expr.last_token, n_else.last_token)
+                       else
+                               comments = v.collect_comments(n_then.last_token, n_else.last_token)
+                       end
+
+                       if not comments.is_empty then return true
+                       return not n_else.n_expr.is_empty
+               end
+
+               return true
+       end
+
+       # Lookup for `else` token in `self`.
+       private fun collect_kwelse: nullable TKwelse do
+               var token = first_token
+
+               while token != last_token do
+                       if token isa TKwelse then return token
+                       token = token.next_token
+               end
+
+               return null
+       end
+end
+
+# Used to factorize work on loops.
+private class ALoopHelper
+       super AExpr
+
+       fun loop_block: nullable ANode is abstract
+       fun loop_label: nullable ANode is abstract
+
+       fun visit_loop_block(v: PrettyPrinterVisitor) do
+               var n_block = loop_block
+               v.finish_line
+               v.addn
+               v.indent += 1
+
+               if n_block isa ABlockExpr then
+                       n_block.force_block = true
+                       v.visit n_block
+                       v.catch_up n_block.n_kwend
+                       v.indent -= 1
+                       v.addt
+                       v.visit n_block.n_kwend
+               else
+                       v.addt
+                       v.visit n_block
+                       v.addn
+                       v.indent -= 1
+                       v.addt
+                       v.add "end"
+               end
+
+               if loop_label != null then
+                       v.adds
+                       v.visit loop_label
+               end
+       end
+
+       fun visit_loop_inline(v: PrettyPrinterVisitor) do
+               var n_block = loop_block
+               v.adds
+
+               if n_block isa ABlockExpr then
+                       if n_block.n_expr.is_empty then
+                               v.visit n_block.n_kwend
+                       else
+                               v.visit n_block.n_expr.first
+                               v.current_token = n_block.n_kwend
+                               v.skip
+                       end
+               else
+                       v.visit n_block
+                       if v.current_token isa TKwend then v.skip
+               end
+
+               if loop_label != null then
+                       v.adds
+                       v.visit loop_label
+               end
+       end
+
+       redef fun is_inlinable do
+               var n_block = loop_block
+               if not super then return false
+               if n_block isa ABlockExpr and not n_block.is_inlinable then return false
+               if not collect_comments.is_empty then return false
+               return true
+       end
+end
+
+redef class ALoopExpr
+       super ALoopHelper
+
+       redef fun loop_block do return n_block
+       redef fun loop_label do return n_label
+
+       redef fun accept_pretty_printer(v) do
+               var can_inline = v.can_inline(self)
+               v.visit n_kwloop
+               if can_inline then visit_loop_inline v else visit_loop_block v
+       end
+end
+
+redef class AWhileExpr
+       super ALoopHelper
+
+       redef fun loop_block do return n_block
+       redef fun loop_label do return n_label
+
+       redef fun accept_pretty_printer(v) do
+               var can_inline = v.can_inline(self)
+               v.visit n_kwwhile
+               v.adds
+               v.visit n_expr
+               v.adds
+               v.visit n_kwdo
+               if can_inline then visit_loop_inline v else visit_loop_block v
+       end
+end
+
+redef class ADoExpr
+       super ALoopHelper
+
+       redef fun loop_block do return n_block
+       redef fun loop_label do return n_label
+
+       redef fun accept_pretty_printer(v) do
+               var can_inline = v.can_inline(self)
+               v.visit n_kwdo
+               if can_inline then visit_loop_inline v else visit_loop_block v
+       end
+end
+
+redef class AForExpr
+       super ALoopHelper
+
+       redef fun loop_block do return n_block
+       redef fun loop_label do return n_label
+
+       redef fun accept_pretty_printer(v) do
+               var can_inline = v.can_inline(self)
+               v.visit n_kwfor
+               v.adds
+
+               for n_id in n_ids do
+                       v.visit n_id
+                       if n_id != n_ids.last then v.add ", "
+               end
+
+               v.adds
+               v.consume "in"
+               v.adds
+               v.visit n_expr
+               v.adds
+               v.visit n_kwdo
+               if can_inline then visit_loop_inline v else visit_loop_block v
+       end
+end
+
+redef class ABreakExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit n_kwbreak
+
+               if n_expr != null then
+                       v.adds
+                       v.visit n_expr
+               end
+
+               if n_label != null then
+                       v.adds
+                       v.visit n_label
+               end
+       end
+
+       redef fun is_inlinable do return true
+end
+
+redef class AContinueExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit n_kwcontinue
+
+               if n_expr != null then
+                       v.adds
+                       v.visit n_expr
+               end
+
+               if n_label != null then
+                       v.adds
+                       v.visit n_label
+               end
+       end
+
+       redef fun is_inlinable do return true
+end
+
+# Calls
+
+redef class ASendExpr
+       redef fun is_inlinable do return true
+end
+
+redef class ACallExpr
+       redef fun accept_pretty_printer(v) do
+               var can_inline = v.can_inline(self)
+               v.visit_recv n_expr
+
+               if not n_expr isa AImplicitSelfExpr and not can_inline then
+                       v.addn
+                       v.addt
+                       v.addt
+               end
+
+               v.visit n_id
+
+               if not n_args.n_exprs.is_empty then
+                       if is_stmt and n_args.n_exprs.length == 1 then
+                               v.adds
+                               if v.current_token isa TOpar then v.skip
+                               v.visit n_args.n_exprs.first
+                               if v.current_token isa TCpar then v.skip
+                       else
+                               if v.current_token isa TOpar then
+                                       v.consume "("
+                               else
+                                       v.adds
+                               end
+
+                               v.visit_list n_args.n_exprs
+                               if v.current_token isa TCpar then v.consume ")"
+                       end
+               end
+       end
+
+       # Is the call alone on its line?
+       fun is_stmt: Bool do return parent isa ABlockExpr
+end
+
+redef class ACallAssignExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit_recv n_expr
+               v.visit n_id
+
+               if not n_args.n_exprs.is_empty then
+                       v.consume "("
+                       v.visit_list n_args.n_exprs
+                       v.consume ")"
+               end
+
+               v.adds
+               v.consume "="
+               v.adds
+               v.visit n_value
+       end
+end
+
+redef class ACallReassignExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit_recv n_expr
+               v.visit n_id
+
+               if not n_args.n_exprs.is_empty then
+                       v.consume "("
+                       v.visit_list n_args.n_exprs
+                       v.consume ")"
+               end
+
+               v.adds
+               v.visit n_assign_op
+               v.adds
+               v.visit n_value
+       end
+end
+
+redef class ABraExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit n_expr
+
+               if not n_args.n_exprs.is_empty then
+                       v.consume "["
+                       v.visit_list n_args.n_exprs
+                       v.consume "]"
+               end
+       end
+end
+
+redef class ABraAssignExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit n_expr
+
+               if not n_args.n_exprs.is_empty then
+                       v.consume "["
+                       v.visit_list n_args.n_exprs
+                       v.consume "]"
+               end
+
+               v.adds
+               v.visit n_assign
+               v.adds
+               v.visit n_value
+       end
+end
+
+redef class ABraReassignExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit n_expr
+
+               if not n_args.n_exprs.is_empty then
+                       v.consume "["
+                       v.visit_list n_args.n_exprs
+                       v.consume "]"
+               end
+
+               v.adds
+               v.visit n_assign_op
+               v.adds
+               v.visit n_value
+       end
+end
+
+redef class AAssignMethid
+       redef fun accept_pretty_printer(v) do
+               v.visit n_id
+               v.visit n_assign
+       end
+end
+
+redef class ABraMethid
+       redef fun accept_pretty_printer(v) do
+               v.visit n_obra
+               v.visit n_cbra
+       end
+end
+
+redef class ABraassignMethid
+       redef fun accept_pretty_printer(v) do
+               v.visit n_obra
+               v.visit n_cbra
+               v.visit n_assign
+       end
+end
+
+redef class AInitExpr
+       redef fun accept_pretty_printer(v) do
+               if not n_expr isa AImplicitSelfExpr then
+                       v.visit n_expr
+                       v.consume "."
+               end
+
+               v.visit n_kwinit
+
+               if not n_args.n_exprs.is_empty then
+                       v.consume "("
+                       v.visit_list n_args.n_exprs
+                       v.consume ")"
+               end
+       end
+end
+
+redef class ANewExpr
+       redef fun accept_pretty_printer(v) do
+               var can_inline = v.can_inline(self)
+               v.visit n_kwnew
+               v.adds
+               v.visit n_type
+
+               if n_id != null then
+                       v.consume "."
+
+                       if not can_inline then
+                               v.addn
+                               v.addt
+                               v.addt
+                       end
+
+                       v.visit n_id
+               end
+
+               if not n_args.n_exprs.is_empty then
+                       v.consume "("
+                       v.visit_list n_args.n_exprs
+                       v.consume ")"
+               end
+       end
+
+       redef fun is_inlinable do return true
+end
+
+# Attributes
+
+redef class AAttrExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit_recv n_expr
+               v.visit n_id
+       end
+
+       redef fun is_inlinable do return true
+end
+
+redef class AAttrAssignExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit_recv n_expr
+               v.visit n_id
+               v.adds
+               v.visit n_assign
+               v.adds
+               v.visit n_value
+       end
+end
+
+redef class AAttrReassignExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit_recv n_expr
+               v.visit n_id
+               v.adds
+               v.visit n_assign_op
+               v.adds
+               v.visit n_value
+       end
+end
+
+redef class AAble
+       redef fun accept_pretty_printer(v) do
+               if n_kwredef != null then
+                       v.visit n_kwredef
+                       v.adds
+               end
+
+               if not n_visibility isa APublicVisibility then
+                       v.visit n_visibility
+                       v.adds
+               end
+       end
+end
+
+redef class AReadAble
+       redef fun accept_pretty_printer(v) do
+               super
+               v.visit n_kwreadable
+       end
+end
+
+redef class AWriteAble
+       redef fun accept_pretty_printer(v) do
+               super
+               v.visit n_kwwritable
+       end
+end
+
+# Exprs
+
+redef class AVardeclExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit n_kwvar
+               v.adds
+               v.visit n_id
+
+               if n_type != null then
+                       v.consume ":"
+                       v.adds
+                       v.visit n_type
+               end
+
+               if n_expr != null then
+                       v.adds
+                       v.consume "="
+                       v.adds
+                       v.visit n_expr
+               end
+       end
+
+       redef fun is_inlinable do return true
+end
+
+redef class AVarAssignExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit n_id
+               v.adds
+               v.visit n_assign
+               v.adds
+               v.visit n_value
+       end
+end
+
+redef class AAssertExpr
+       redef fun accept_pretty_printer(v) do
+               var can_inline = v.can_inline(self)
+               v.visit n_kwassert
+
+               if n_id != null then
+                       v.adds
+                       v.visit n_id
+                       v.consume ":"
+               end
+
+               v.adds
+               v.visit n_expr
+               var n_else = self.n_else
+
+               if n_else != null then
+                       v.adds
+                       v.consume "else"
+
+                       if can_inline then
+                               v.adds
+                               v.visit n_else
+                       else
+                               v.addn
+
+                               if n_else isa ABlockExpr then
+                                       v.indent += 1
+                                       n_else.force_block = true
+                                       v.visit n_else
+                                       v.indent -= 1
+                                       v.addt
+                                       v.visit n_else.n_kwend
+                               else
+                                       v.indent += 1
+                                       v.addt
+                                       v.visit n_else
+                                       v.addn
+                                       v.indent -= 1
+                                       v.addt
+                                       v.add "end"
+                               end
+                       end
+               end
+       end
+
+       redef fun is_inlinable do
+               if not super then return false
+               if n_else != null and not n_else.is_inlinable then return false
+               return true
+       end
+end
+
+redef class AReturnExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit n_kwreturn
+
+               if n_expr != null then
+                       v.adds
+                       v.visit n_expr
+               end
+       end
+end
+
+redef class ASuperExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit n_kwsuper
+
+               if not n_args.n_exprs.is_empty then
+                       if is_stmt and n_args.n_exprs.length == 1 then
+                               v.adds
+                               if v.current_token isa TOpar then v.skip
+                               v.visit n_args.n_exprs.first
+                               if v.current_token isa TCpar then v.skip
+                       else
+                               if v.current_token isa TOpar then
+                                       v.consume "("
+                               else
+                                       v.adds
+                               end
+
+                               v.visit_list n_args.n_exprs
+                               if v.current_token isa TCpar then v.consume ")"
+                       end
+               end
+       end
+
+       # Is the call alone on its line?
+       fun is_stmt: Bool do return self.first_token.is_starting_line
+
+       redef fun is_inlinable do return true
+end
+
+redef class AOnceExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit n_kwonce
+               v.adds
+               v.visit n_expr
+       end
+
+       redef fun is_inlinable do return true
+end
+
+redef class AAbortExpr
+       redef fun accept_pretty_printer(v) do v.visit n_kwabort
+       redef fun is_inlinable do return true
+end
+
+redef class ANotExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit n_kwnot
+               v.adds
+               v.visit n_expr
+       end
+end
+
+redef class AAsCastExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit n_expr
+               v.consume "."
+               v.visit n_kwas
+               v.visit n_opar
+               v.visit n_type
+               v.visit n_cpar
+       end
+end
+
+redef class AAsNotnullExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit n_expr
+               v.consume "."
+               v.visit n_kwas
+               v.visit n_opar
+               v.visit n_kwnot
+               v.adds
+               v.visit n_kwnull
+               v.visit n_cpar
+       end
+end
+
+# Binops
+
+# Used to factorize work on Or, And, Implies and Binop expressions.
+private class ABinOpHelper
+       super AExpr
+
+       fun bin_expr1: AExpr is abstract
+       fun bin_expr2: AExpr is abstract
+
+       # Operator string
+       fun bin_op: String is abstract
+
+       redef fun accept_pretty_printer(v) do
+               var can_inline = v.can_inline(self)
+
+               if not can_inline then
+                       if (self isa ABinopExpr and bin_expr1 isa ABinopExpr) or
+                          (self isa AAndExpr and (bin_expr1 isa AAndExpr or bin_expr1 isa AOrExpr)) or
+                          (self isa AOrExpr and (bin_expr1 isa AAndExpr or bin_expr1 isa AOrExpr))
+                       then
+                               bin_expr1.force_block = true
+                       end
+               end
+
+               v.visit bin_expr1
+               v.adds
+               v.consume bin_op
+
+               if can_inline then
+                       v.adds
+                       v.visit bin_expr2
+               else
+                       v.addn
+                       v.addt
+                       v.addt
+                       v.visit bin_expr2
+               end
+       end
+end
+
+redef class AAndExpr
+       super ABinOpHelper
+
+       redef fun bin_expr1 do return n_expr
+       redef fun bin_expr2 do return n_expr2
+       redef fun bin_op do return "and"
+end
+
+redef class AOrExpr
+       super ABinOpHelper
+
+       redef fun bin_expr1 do return n_expr
+       redef fun bin_expr2 do return n_expr2
+       redef fun bin_op do return "or"
+end
+
+redef class AImpliesExpr
+       super ABinOpHelper
+
+       redef fun bin_expr1 do return n_expr
+       redef fun bin_expr2 do return n_expr2
+       redef fun bin_op do return "implies"
+end
+
+redef class ABinopExpr
+       super ABinOpHelper
+
+       redef fun bin_expr1 do return n_expr
+       redef fun bin_expr2 do return n_expr2
+end
+
+redef class AEqExpr
+       redef fun bin_op do return "=="
+end
+
+redef class AGeExpr
+       redef fun bin_op do return ">="
+end
+
+redef class AGgExpr
+       redef fun bin_op do return ">>"
+end
+
+redef class AGtExpr
+       redef fun bin_op do return ">"
+end
+
+redef class ALeExpr
+       redef fun bin_op do return "<="
+end
+
+redef class ALlExpr
+       redef fun bin_op do return "<<"
+end
+
+redef class ALtExpr
+       redef fun bin_op do return "<"
+end
+
+redef class AMinusExpr
+       redef fun bin_op do return "-"
+end
+
+redef class ANeExpr
+       redef fun bin_op do return "!="
+end
+
+redef class APercentExpr
+       redef fun bin_op do return "%"
+end
+
+redef class APlusExpr
+       redef fun bin_op do return "+"
+end
+
+redef class ASlashExpr
+       redef fun bin_op do return "/"
+end
+
+redef class AStarExpr
+       redef fun bin_op do return "*"
+end
+
+redef class AStarshipExpr
+       redef fun bin_op do return "<=>"
+end
+
+redef class AIsaExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit n_expr
+               v.adds
+               v.consume "isa"
+               v.adds
+               v.visit n_type
+       end
+end
+
+redef class AOrElseExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit n_expr
+               v.adds
+               v.consume "or"
+               v.adds
+               v.consume "else"
+               v.adds
+               v.visit n_expr2
+       end
+
+       redef fun is_inlinable do return true
+end
+
+# Syntax
+
+redef class AUminusExpr
+       redef fun accept_pretty_printer(v) do
+               v.consume "-"
+               v.visit n_expr
+       end
+end
+
+redef class ANullExpr
+       redef fun accept_pretty_printer(v) do v.visit n_kwnull
+       redef fun is_inlinable do return true
+end
+
+redef class AParExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit n_opar
+               v.visit n_expr
+               v.visit n_cpar
+       end
+end
+
+redef class AArrayExpr
+       redef fun accept_pretty_printer(v) do
+               v.consume "["
+               v.visit_list n_exprs.n_exprs
+               v.consume "]"
+       end
+end
+
+redef class ACrangeExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit n_obra
+               v.visit n_expr
+               v.consume ".."
+               v.visit n_expr2
+               v.visit n_cbra
+       end
+end
+
+redef class AOrangeExpr
+       redef fun accept_pretty_printer(v) do
+               v.visit n_obra
+               v.visit n_expr
+               v.consume ".."
+               v.visit n_expr2
+               v.visit n_cbra
+       end
+end
+
+# Strings
+
+redef class AStringFormExpr
+       redef fun accept_pretty_printer(v) do
+               var can_inline = v.can_inline(self)
+
+               if can_inline then
+                       v.visit n_string
+               else
+                       var text = n_string.text
+                       var i = 0
+
+                       while i < text.length do
+                               v.add text[i].to_s
+
+                               if v.current_length >= v.max_size and i <= text.length - 3 then
+                                       v.add "\" +"
+                                       v.addn
+                                       v.indent += 1
+                                       v.addt
+                                       v.indent -= 1
+                                       v.add "\""
+                               end
+
+                               i += 1
+                       end
+
+                       v.current_token = n_string.next_token
+               end
+       end
+end
+
+redef class ASuperstringExpr
+       redef fun accept_pretty_printer(v) do
+               var force_inline = self.force_inline
+               for n_expr in n_exprs do v.visit n_expr
+       end
+
+       redef fun must_be_inline do
+               if super then return true
+
+               if not n_exprs.is_empty then
+                       var first = n_exprs.first
+                       return first isa AStringFormExpr and first.n_string.text.has_prefix("\"\"\"")
+               end
+
+               return false
+       end
+end
+
+redef class ToolContext
+       var opt_dir = new OptionString("Working directory (default is '.nitpretty')", "--dir")
+
+       var opt_output = new OptionString("Output name (default is pretty.nit)", "-o",
+          "--output")
+
+       var opt_diff = new OptionBool("Show diff between source and output", "--diff")
+
+       var opt_meld = new OptionBool("Show diff between source and output using meld",
+          "--meld")
+
+       var opt_check = new OptionBool("Check format of Nit source files", "--check")
+end
+
+# Return result from diff between `file1` and `file2`.
+private fun diff(file1, file2: String): String do
+       var p = new IProcess("diff", "-u", file1, file2)
+       var res = p.read_all
+       p.wait
+       p.close
+       return res
+end
+
+# process options
+var toolcontext = new ToolContext
+
+toolcontext.option_context.
+   add_option(toolcontext.opt_dir, toolcontext.opt_output, toolcontext.opt_diff,
+   toolcontext.opt_meld, toolcontext.opt_check)
+
+toolcontext.tooldescription = "Usage: nitpretty [OPTION]... <file.nit>\n" +
+       "Pretty print Nit code from Nit source files."
+
+toolcontext.process_options args
+var arguments = toolcontext.option_context.rest
+# build model
+var model = new Model
+var mbuilder = new ModelBuilder(model, toolcontext)
+var mmodules = mbuilder.parse(arguments)
+mbuilder.run_phases
+
+if mmodules.is_empty then
+       print "Error: no module to pretty print"
+       return
+end
+
+if not toolcontext.opt_check.value and mmodules.length > 1 then
+       print "Error: only --check option allow multiple modules"
+       return
+end
+
+var dir = toolcontext.opt_dir.value or else ".nitpretty"
+if not dir.file_exists then dir.mkdir
+var v = new PrettyPrinterVisitor
+
+for mmodule in mmodules do
+       if not mbuilder.mmodule2nmodule.has_key(mmodule) then
+               print " Error: no source file for module {mmodule}"
+               return
+       end
+
+       var nmodule = mbuilder.mmodule2nmodule[mmodule]
+       var file = "{dir}/{mmodule.name}.nit"
+       var tpl = v.pretty_nmodule(nmodule)
+       tpl.write_to_file file
+
+       if toolcontext.opt_check.value then
+               var res = diff(nmodule.location.file.filename, file)
+
+               if not res.is_empty then
+                       print "Wrong formating for module {nmodule.location.file.filename}"
+                       toolcontext.info(res, 1)
+
+                       if toolcontext.opt_meld.value then
+                               sys.system "meld {nmodule.location.file.filename} {file}"
+                       end
+               else
+                       toolcontext.info("[OK] {nmodule.location.file.filename}", 1)
+               end
+       else
+               # write to file
+               var out = toolcontext.opt_output.value
+               if out != null then sys.system "cp {file} {out}"
+
+               # open in meld
+               if toolcontext.opt_meld.value then
+                       sys.system "meld {arguments.first} {file}"
+                       return
+               end
+
+               # show diff
+               if toolcontext.opt_diff.value then
+                       var res = diff(arguments.first, file)
+                       if not res.is_empty then print res
+                       return
+               end
+
+               # show pretty
+               if not toolcontext.opt_quiet.value then tpl.write_to sys.stdout
+       end
+end
diff --git a/tests/README b/tests/README
deleted file mode 100644 (file)
index 7042a5c..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-This directory contains small NIT programs divided in some categories:
-* 'base' are minimal and fundamental tests
-* 'bench' are memory and time tests
-* 'error' are invalid programs
-* 'example' are examples 
-* 'test' are others tests
-* 'shootout' are benchmarks from http://shootout.alioth.debian.org/
-
-The .gitignore contains specific artefacts produced by some tests.
-However, it is better to produce these artifacts in the `out` directory instead,
-because `out` is cleaned before runing tests (so that old artefacts do not
-interfere with new executions of tests)
diff --git a/tests/README.md b/tests/README.md
new file mode 100644 (file)
index 0000000..c1b4cff
--- /dev/null
@@ -0,0 +1,320 @@
+# Regression test for the Nit project
+
+## Content of the directory
+
+This directory contains small Nit programs and useful scripts to test the non regression of the nit tools.
+
+### Useful scripts
+
+* `tests.sh` is the main test script used to run some specific tests.
+* `testall.sh` runs some tests on all engines.
+  (No more excuse to forget to check your new tests with an obscure engine).
+* `testfull.sh` runs all tests on a single engine.
+  (go and grab a coffee)
+* `search_test.sh` lists tests given a testname, a basename, or a `.res` file.
+  Useful when `foo failed` but you do not know where the program `foo` is.
+* `search_tests_git.sh` lists tests that seem modified between 2 git revisions.
+  Useful before committing something.
+* `listfull.sh` lists tests that are run by `testfull.sh`.
+  It is used by other scripts but can be used by human to see what is tested.
+
+  Currently, all files in `tests/`, `lib/` and `examples/` are executed, some of `contrib/` and the main programs of `src/`.
+  To update the list of tested files, just edit this script.
+
+### Small Nit programs
+
+They are divided in categories:
+
+* `base` are minimal and fundamental tests.
+  They are small and test the fundamental language specifications.
+* `bench` are memory and time tests
+* `error` are invalid programs
+  They test the error message and the good behavior of the tool.
+  Nowadays, alternatives (see below) are more used to test erroneous programs.
+* `example` are examples
+  Nowadays, examples are developed in the `examples/` root directory.
+* `test` are others tests that usually depend on standard or other libraries.
+  Nowadays, nitunit are a better place for them.
+* `shootout` are benchmarks from http://shootout.alioth.debian.org/
+
+### Other stuff
+
+The .gitignore contains specific artefacts produced by some tests.
+However, it is better to produce these artifacts in the `out` directory instead,
+because `out` is cleaned before running tests (so that old artefacts do not
+interfere with new executions of tests)
+
+The `sav/` directory contains reference result files for tests (see below)
+
+The `alt/` and `out/` directory are transient directories used during the tests.
+
+The `zzz_tests/` directory contains tests to test the test system.
+Execute `./tests.ss zzz_tests/*.nit` if you want.
+
+## Running tests
+
+~~~
+./tests.sh filepath.nit...
+./tests.sh base_attr*.nit
+~~~
+
+Will execute the program filepath for all its alternative (see below) and all its arguments (see below) for the default engine (see below).
+
+The output is something like
+~~~
+=> test_args: . [ok] out/test_args.res sav/test_args.res
+~~~
+
+where in order, there is
+
+* The test description (`test_args` in the example).
+  It is the basename of the file + information about alternatives and arguments.
+* The build status: `.`, `!`, or `nocc`, or `_`.
+  They respectively mean "compilation OK", "compilation error", "compilation skipped", "compilation OK but execution skipped".
+* The test status (see below) where `out/*.res` is the produced result file, and `sav/*.res` is the reference result file.
+
+
+## Test statuses
+
+### Ok
+
+`[ok] out/zzz_test_ok.res sav/zzz_test_ok.res`
+
+The produced result file correspond to the reference result file (according to `diff`).
+It is a success.
+
+### 0k, is empty
+
+`[0k] out/zzz_test_0k.res is empty`
+
+The produced result file is empty and no reference result file is present.
+It is a success.
+
+If you introduced a new library, it is likely that you get this.
+It basically means that the module compile and does noting, and its fine.
+
+### Fail
+
+`[======= fail out/zzz_test_fail.res sav/zzz_test_fail.res =======]`
+
+The produced result file do not correspond to the reference result file.
+It is a failure.
+
+Did something break? or does the reference result file need to be updated?
+
+### No sav
+
+`[=== no sav ===] out/zzz_test_nosav.res is not empty`
+
+The produced result file is not empty but no reference result file is present.
+It is a failure.
+
+Did something break? or does the reference result file need to be created?
+If you introduced a new program, it is likely that you get this.
+It basically means the program compiles and produces something.
+Please create a new reference result file for it.
+
+### Soso
+
+`[======= soso out/zzz_test_soso.res sav//zzz_test_soso.res =======]`
+
+The produced result file do not correspond to the reference result file.
+But the difference in only in errors or warnings.
+It is a failure.
+
+Usually, some lines in error messages changed.
+So just update the reference result file.
+
+### Fixme
+
+`[fixme] out/zzz_test_fixme.res sav//fixme/zzz_test_fixme.res`
+
+The produced result file correspond to a *fixme* reference result file.
+It is an expected error. So not a regression.
+
+Reference result files in `sav/**/fixme/` are considered expected errors.
+The distinction with standard reference result files is only for final statistics.
+
+### Ok, but fixme remains
+
+`[*ok*] out/zzz_test_fixme_remains.res sav//zzz_test_fixme_remains.res - but sav//fixme/zzz_test_fixme_remains.res remains!`
+
+There is a fixme reference result file and a standard reference result file. But the produced result file correspond to the standard one.
+Usually it means that a bug was fixed. But is considered a regression until the *fixme* reference result file is removed.
+It is a failure.
+
+### Changed fixme
+
+`[======= changed out/zzz_test_fixme_changed.res sav//fixme/zzz_test_fixme_changed.res ======]`
+
+The produced result file do not correspond to the *fixme* reference result file.
+It is a failure, and analogous to the standard `fail`.
+
+### Todo, not yet implemented
+
+`[todo] out/zzz_test_todo.res -> not yet implemented`
+
+The produced result file contains the magic string "NOT YET IMPLEMENTED".
+Those are considered the same as expected errors (like a fixme)
+It is a success.
+
+Some engines, libraries or program just print this to simplify the management of tests.
+
+### Skipped
+
+`[skip]`
+
+The test is skipped.
+It is a success.
+
+The `$engine.skip` files (where `$engine` is an engine name, see below) describe tests that are skipped completely on a given engine.
+Usually it used with then engine `niti` because tests are too long.
+
+The `cc.skip` file describes tests that are analysed but no executable is generated.
+Usually it is because expected CC errors or missing C libraries.
+
+The `exec.skip` file describes tests that compiled but not executed.
+Usually it is because the programs are interactive or run some kind of server.
+
+These `*.skip` files contain a list of patterns that will be used against test names.
+A single substring can thus be used to skip a full family of tests.
+
+## Update reference result files
+
+To update the reference result files, just create/remove/update files in the `sav/` directory.
+
+HINT: for easy management, just copy-paste parts of the test status to build your command.
+Example `cp <copy-paste out/zzz_test_fail.res sav/zzz_test_fail.res>` to update a file.
+
+
+If a reference result file contains only `UNDEFINED`, then the produced result file is always considered successful.
+It is used to store system-dependant *fixme* reference result files.
+Once the problem is solved, the status will become `Ok but fixme remains`
+
+
+Note: `UNDEFINED` still gives a success even if the tests is uncompilable.
+So do not use it for standard reference result files.
+Use the various skipping or controls to try to produce reproducible results.
+
+
+## Engines
+
+Engines are selected with the option `--engine`.
+
+~~~
+./tests.sh --engine nitg-e base_class_name.nit
+~~~
+
+Current engines are:
+
+* `nitg-s`, for `nitg --separate` (this is the default)
+* `nitg-e`, for `nitg --erasure`
+* `nitg-sg`, for `nitg --separate --semi-global`
+* `nitg-g`, for `nitg --global`
+* `niti`, for `nit`, the interpreter
+* `nitvm`, for `nitvm` (not automatically executed by `testall.sh`)
+* `emscripten`, for `nitg --semi-global -m emscripten` (not automatically executed by `testall.sh`)
+
+Engines control:
+
+* How tests are run: compiled or interpreted? which binary? what options?
+* Where to find the reference result files.
+  The sav/ directory contains subdirectories per engine that are used to store specific reference result files.
+  Specific reference result files override the generic ones.
+
+
+## Alternatives
+
+See `README_alternatives.md`
+
+
+## Controlling the execution of program tests
+
+
+### Arguments
+
+Argument files `*.args` are used to run program tests with specific command line arguments.
+
+* `foo.args` are used for the test file basenamed `foo`.
+* `foo_*alt*.args` are used for specific alternatives if they exists.
+
+Each line of an argument file produces an additional distinct test, with its own testname and reference result files.
+
+
+The first test, with a short arrow `=>`, is the test executed without any arguments.
+Other tests are arguments tests and have a longer arrow `==>`.
+If the first test does not produce an executapel, arguments tests are not run.
+
+Example:
+
+~~~
+$ tail zzz_test_args.args zzz_tests/zzz_test_args.nit
+$ ./tests.sh zzz_tests/zzz_test_args.nit
+$ tail out/zzz_test_args*.res
+~~~
+
+
+### Input
+
+By default, stdin is read from `/dev/null.`
+Specific tests may need prepared inputs.
+
+The `*.inputs` files are used to provide inputs during the execution of program tests.
+
+* `foo.inputs` are used for the test file basenamed `foo`
+* `foo_*alt*_args*.args` are used for specific alternatives and/or arguments if they exists.
+
+Example:
+
+~~~
+$ tail zzz_test_in.inputs zzz_tests/zzz_test_in.nit
+$ ./tests.sh zzz_tests/zzz_test_in.nit
+$ cat out/zzz_test_in.res
+~~~
+
+
+### Output and generated files
+
+The stdout and stderr are redirected to the produced result file.
+
+Sometimes, files are also produced by the programs.
+In order to check those files, a special path by testname is watched.
+Its name is `out/foo.write` where `foo` is the complete testname (with alts and args).
+
+The shell variable `$WRITE` can be used in `*.args` file in order to give the correct path to the program.
+
+If it exists, the content of the `$WRITE` file is appended at the end of the produced result file.
+If `$WRITE` is created as a directory, then the names of files in this directory is appended.
+
+Example:
+
+~~~
+$ tail zzz_test_write.args zzz_tests/zzz_test_write.nit
+$ ./tests.sh zzz_tests/zzz_test_write.nit
+$ cat out/zzz_test_write.out
+~~~
+
+
+### Post-processing
+
+Some simple post-processing can be executed after each tests associated to a line in a `.args` file.
+
+In `*.args` files, semicolons can be used to introduce and separate additional shell commands.
+
+~~~
+$ tail zzz_test_post_proc.args zzz_tests/zzz_test_post_proc.nit
+$ ./tests.sh zzz_tests/zzz_test_post_proc.nit
+$ cat out/zzz_test_post_proc.res
+~~~
+
+
+### Environment variable
+
+The environment variable `NIT_TESTING` is set to `true` during the execution of program tests.
+Some libraries of programs can use it to produce specific reproducible results ; or just to exit their executions.
+
+~~~
+$ cat zzz_tests/zzz_test_envvar.nit
+$ ./tests.sh zzz_tests/zzz_test_envvar.nit
+$ cat out/zzz_test_post_proc.res
+~~~
diff --git a/tests/README_alternatives.md b/tests/README_alternatives.md
new file mode 100644 (file)
index 0000000..eee0fd0
--- /dev/null
@@ -0,0 +1,200 @@
+# Produces alternatives of text files
+
+alterner.pl is a simple tool that use alternation directives in a text file to produce variations (alternatives) of this text file.
+
+alterner.pl was primarily developed to help the generation of regression tests for [SableCC][1] but now it aims to be a more generic and versatile tool.
+
+  [1]: http://sablecc.org
+
+Principles of alterner.pl
+-------------------------
+
+alterner works line by line and produces alternatives files where some lines are altered.
+
+An line containing an alternation directive looks like
+
+    standard text //alt1 alternative text
+
+where `//alt1` is the alternation directive (note there is no space between the `//` and the `alt` nor between the `alt` and the number).
+
+Note: an alternation directive can also be terminated by a `//`.
+Eg.
+
+    standard text //alt1// alternative text
+
+The first principle is that the alternation is produced by swapping the right part of the directive with its left part.
+
+The basic idea behind alterner.pl is that if `//` marks the start of a comment for your input language then:
+
+* if the file is used unmodified, the useful part of the line will be `standard text`;
+* if the alternative version is used, the useful part of the line will be `alternative text`.
+
+Neither the left or the right part is mandatory.
+Therefore, directives are often used to make some lines appear or disappear in the alternatives:
+
+    this will disappear in the alternative //alt1
+    //alt1 this will appear in the alternative
+
+
+The second principle is that there could be many alternatives generated for a single base file.
+Each alternation directive is numbered (`//alt1`, `//alt2`, `//alt3`, etc.) and, for a given alternative, all the associated directives are applied together.
+
+Example:
+
+    //alt1 this will appear in alternative 1
+    this will disappear in alternative 2 //alt2
+    this is in base and in alternative 2 //alt1 but this is in alternative 1
+
+The last principle is that more than one directive can appear on a single line.
+The first principle still apply: for a given alternative version, the left and right parts of the associated directives are swapped.
+The trick is that the directives of other alternatives do not interfere.
+
+Example:
+
+    base version //alt1 version of alternative 1 //alt2 version of alternative 2
+
+
+Lists and ranges
+----------------
+
+A single directive can be associated to more than one alternative version.
+Directives for multiple alternatives are declared with a list (separated with a comma) or with a range (indicated with a dash).
+
+Example:
+
+    base version //alt1,3 version of alternative 1 and 3
+    base version //alt2-4 version of alternatives 2, 3 and 4
+
+Lists and ranges can be used together and multiple alternatives can appears on a single line.
+
+    base //alt1,3-4 version for 1, 3, and 4 //alt2,5 version for 2 and 5
+
+
+Combinations
+------------
+
+Each directive belong to a given group: either to the anonymous group (by default) or to a numbered group.
+The number of the group is noted before the `alt`.
+
+Example:
+
+       base version //1alt1 first alternative of the first group
+       base version //2alt1 first alternative of the second group
+       base version //2alt2 second alternative of the second group
+
+alterner.pl also produces alternative files by combining the groups.
+With two groups, is means that at least three alternative files are created: one with the first group, one with the second group, and one with both.
+
+If there is more than one alternative by group, even more alternative files are created.
+With the previous example, 5 alternative files are created:
+
+* one with 1alt1 activated
+* one with 2alt1 activated
+* one with 2alt2 activated
+* one with 1alt1 and 2alt1 activated
+* one with 1alt1 and 2alt2 activated
+
+Be careful with groups since the number of alternative file generated increase rapidly.
+For instance, with 4 groups of 4 alternatives each, 624 alternative files are generated.
+
+Usage of alterner.pl
+--------------------
+
+    alterner.pl [options] input-file.ext
+
+Produce alternatives of `input-file.ext` according to the alternation directives present in the file.
+By default, alternatives are named `input-file.altX.ext` (where `X` is a number) and are generated in a `alt/` sub-directory.
+If groups are used, the `altX` is replaced by `YaltX` (where `Y` is the number of the group) and the combination of multiple groups produce multiple `YaltX` (separated with dots).
+If the directory does not exist, it is created.
+The path of `input-file.ext` is not considered: only the base name of the file and its extension are used to name the alternatives.
+
+alterner.pl also outputs the path of each generated alternative (a path by line).
+This list can be used to know what are the generated alternatives.
+
+
+Options
+-------
+
+* `-d` directory
+
+  Generate the alternatives in the specified directory.
+  By default, the directory is `alt/`.
+  Use `.` for the current directory.
+
+* `--start` pattern
+
+  Alternation directives start with the specified pattern.
+  This option is used to indicate what starts comments in the language.
+  By default, the start pattern is `//`.
+  For example, `--start '#'` means that the alternatives are `#alt1`, `#alt2`, etc.
+
+  Note: an alternation directive can also be terminated by the start pattern.
+  For example, `--start '#'` means that the alternatives can also be `#alt1#`, `#alt2#`, etc.
+
+* `--end` pattern
+
+  Lines with alternation directives end with the specified pattern.
+  This option is used to indicate what end comments in the language when multiline comments are used.
+  By default, the end pattern is the empty string.
+  For example, start with `/*` and end with `*/` for using alternatives in a C file.
+
+  The principle of the end pattern is that:
+
+  1. alternation directives are ignored if the end pattern is not present at the end of the line;
+  2. the end pattern is not swapped when a directive is applied (it means the end pattern stay at the end of the line).
+
+* `--altsep` separator
+
+  Separator used in the name of the generated file betwen the basename of the original file and the alternative mark.
+  By default, it is `.`.
+
+Examples
+--------
+
+Example with default options
+
+    $ cat example.txt
+    foo //alt1 bar
+    foo //alt1 bar //alt2 baz
+
+    $ alterner.pl example.txt
+    alt/example.alt1.txt
+    alt/example.alt2.txt
+
+    $ echo alt/example.alt1.txt
+    bar //alt1 foo
+    bar //alt2 baz //alt1 foo
+
+    $ echo alt/example.alt2.txt
+    foo //alt1 bar
+    baz //alt2 foo //alt1 bar
+
+
+Example with directives in C comments.
+
+    $ cat input-file.c
+    base /*alt1 first /*alt2 second */
+
+    $ alterner.pl --start '/*' --end '*/' input-file.c
+    alt/input-file.alt1.c
+    alt/input-file.alt2.c
+
+    $ cat alt/input-file.alt1.c
+    first /*alt2 second /*alt1 base */
+
+    $ cat alt/input-file.alt2.c
+    second /*alt2 base /*alt1 first */
+
+
+Example with groups.
+
+    $ cat example.txt
+    first //alt1 second //alt2 third
+    first //2alt1 second
+
+    $ alterner.pl exaple.txt
+    example.alt1.txt
+    example.alt2.txt
+    example.2alt1.txt
+    example.alt1.2alt1.txt
+    example.alt2.2alt1.txt
index 22d7416..c052cff 100644 (file)
@@ -17,5 +17,5 @@ pep8analysis
 nitcc_parser_gen
 emscripten
 nitserial_args
-nitunit_args2
-nitunit_args3
+nitunit_args
+nitpretty_args
diff --git a/tests/nitpretty.args b/tests/nitpretty.args
new file mode 100644 (file)
index 0000000..61b0157
--- /dev/null
@@ -0,0 +1,27 @@
+test_pretty/test_mod1.nit
+test_pretty/test_mod2.nit
+test_pretty/test_mod3.nit
+test_pretty/test_class1.nit
+test_pretty/test_class2.nit
+test_pretty/test_class3.nit
+test_pretty/test_prop1.nit
+test_pretty/test_prop2.nit
+test_pretty/test_prop3.nit
+test_pretty/test_loop1.nit
+test_pretty/test_loop2.nit
+test_pretty/test_loop3.nit
+test_pretty/test_call1.nit
+test_pretty/test_call2.nit
+test_pretty/test_if1.nit
+test_pretty/test_if2.nit
+test_pretty/test_if3.nit
+test_pretty/test_op1.nit
+test_pretty/test_op2.nit
+test_pretty/test_op3.nit
+test_pretty/test_extern1.nit
+test_pretty/test_attr1.nit
+test_pretty/test_attr2.nit
+test_pretty/test_comments1.nit
+test_pretty/test_indent1.nit
+test_pretty/test_prims1.nit
+test_pretty/test_annot1.nit
diff --git a/tests/sav/nitpretty.res b/tests/sav/nitpretty.res
new file mode 100644 (file)
index 0000000..0b02ffb
--- /dev/null
@@ -0,0 +1,3 @@
+Usage: nitpretty [OPTION]... <file.nit>
+Pretty print Nit code from Nit source files.
+Use --help for help
diff --git a/tests/sav/nitpretty_args1.res b/tests/sav/nitpretty_args1.res
new file mode 100644 (file)
index 0000000..f9f0615
--- /dev/null
@@ -0,0 +1,15 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# An empty module
diff --git a/tests/sav/nitpretty_args10.res b/tests/sav/nitpretty_args10.res
new file mode 100644 (file)
index 0000000..3868546
--- /dev/null
@@ -0,0 +1,33 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var a = 1
+var b = 2
+
+while a != b do # comment 1
+       # comment 2
+       var tmp = a
+       a = b
+       b = tmp
+       # comment 3
+end
+
+# comment 4
+while a != b do a = b # comment 5
+
+while a != b do
+       # comment 6
+end # comment 7
+
+# end
diff --git a/tests/sav/nitpretty_args11.res b/tests/sav/nitpretty_args11.res
new file mode 100644 (file)
index 0000000..57d2648
--- /dev/null
@@ -0,0 +1,42 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var a = 0
+var b = 2
+
+do # comment 1
+       # comment 2
+       var tmp = a
+       a = b
+       b = tmp
+       # comment 3
+end
+
+# comment 4
+do a = b # comment 5
+
+do
+       # comment 6
+end
+
+if a > b then loop print a # test
+if a > b then loop print a
+if a > b then loop print a
+
+if a > b then
+       loop
+               # comment 7
+               print a
+       end
+end
diff --git a/tests/sav/nitpretty_args12.res b/tests/sav/nitpretty_args12.res
new file mode 100644 (file)
index 0000000..0135aa1
--- /dev/null
@@ -0,0 +1,27 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var a = 0
+
+for i in [1, 2, 3] do # comment 1
+       # comment 2
+       a += i
+end
+
+# comment 4
+for i in [1..3] do a += i # comment 5
+
+for i in [1..3[ do
+       # comment 6
+end
diff --git a/tests/sav/nitpretty_args13.res b/tests/sav/nitpretty_args13.res
new file mode 100644 (file)
index 0000000..eaf7f56
--- /dev/null
@@ -0,0 +1,34 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class A
+       fun foo do end
+       fun bar(a: Int): Int do return 1
+       fun baz(a, b: Int) do end
+       fun gaz(a: Int, b: Float...) do end
+end
+
+fun top1 do end
+
+fun top2(a: Int) do end
+
+# comment 1
+var a = new A # comment 2
+a.foo # comment 3
+a.bar 1 # comment 4
+a.baz(1, 2) # comment 5
+top1 # comment 6
+top2 10 # comment 7
+print 10 # comment 8
+var b = a.bar(1)
diff --git a/tests/sav/nitpretty_args14.res b/tests/sav/nitpretty_args14.res
new file mode 100644 (file)
index 0000000..e2f4e9a
--- /dev/null
@@ -0,0 +1,37 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class A
+       var attr: Int
+       fun foo1=(i: Int) do end
+       fun foo2=(i, j: Int) do end
+       fun [](a: Int): Int is abstract
+       fun []=(a, b: Int) do end
+end
+
+class B
+       fun [](a, b: Int): Int is abstract
+       fun []=(a, b, c: Int) do end
+end
+
+# comment 1
+var a = new A(10) # comment 2
+a.foo1 = 10 # comment 3
+a.foo2(1) = 10 # comment 4
+print a[1] # comment 5
+a[1] = 2 # comment 6
+a[2] += 3 # comment 7
+var b = new B
+print b[1, 2]
+b[1, 2] = 10
diff --git a/tests/sav/nitpretty_args15.res b/tests/sav/nitpretty_args15.res
new file mode 100644 (file)
index 0000000..d2a5ee1
--- /dev/null
@@ -0,0 +1,49 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var a = 1
+var b = 2
+if a == b then a = b
+
+if a != b then
+       a = b
+       a = b
+end
+
+if a > b then
+       b = a
+       a = b
+else
+       a = b
+       a = b
+end
+
+if a < b then
+       a = b
+       a = b
+else if a == b then
+       b = a
+       a = b
+end
+
+if a < b then
+       a = b
+       a = b
+else if a == b then
+       b = b
+       a = b
+else
+       a = b
+       a = b
+end
diff --git a/tests/sav/nitpretty_args16.res b/tests/sav/nitpretty_args16.res
new file mode 100644 (file)
index 0000000..46efbce
--- /dev/null
@@ -0,0 +1,81 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# comment
+
+var a = 1 # comment
+# comment
+var b = 2 # comment
+# comment
+if a == b then a = b # comment
+
+# comment
+if a != b then # comment
+       # comment
+       a = b # comment
+       # comment
+       a = b # comment
+       # comment
+end # comment
+
+# comment
+if a > b then # comment
+       # comment
+       b = a # comment
+       # comment
+       a = b # comment
+       # comment
+else # comment
+       # comment
+       a = b # comment
+       # comment
+       a = b # comment
+       # comment
+end # comment
+
+# comment
+if a < b then # comment
+       # comment
+       a = b # comment
+       # comment
+       a = b # comment
+       # comment
+else if a == b then # comment
+       # comment
+       b = a # comment
+       # comment
+       a = b # comment
+       # comment
+end # comment
+
+# comment
+if a < b then # comment
+       # comment
+       a = b # comment
+       # comment
+       a = b # comment
+       # comment
+else if a == b then # comment
+       # comment
+       b = b # comment
+       # comment
+       a = b # comment
+       # comment
+else # comment
+       # comment
+       a = b # comment
+       # comment
+       a = b # comment
+       # comment
+end # comment
diff --git a/tests/sav/nitpretty_args17.res b/tests/sav/nitpretty_args17.res
new file mode 100644 (file)
index 0000000..e5aec78
--- /dev/null
@@ -0,0 +1,55 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var a = 1
+var b = 2
+
+# 0
+if a == b then # 1
+       # 2
+else # 3
+       # 4
+end # 5
+
+if a == b then print a # printing a
+
+if a == b then
+       print a # printing a
+end
+
+if a == b then print a # end
+if a == b then a = b
+if a == b then end
+if a == b then end
+if a != b then a = b
+
+if a > b then
+       a = b
+else
+       a = b
+end
+
+if a < b then
+       a = b
+else if a == b then
+       a = b
+end
+
+if a < b then
+       a = b
+else if a == b then
+       a = b
+else
+       a = b
+end
diff --git a/tests/sav/nitpretty_args18.res b/tests/sav/nitpretty_args18.res
new file mode 100644 (file)
index 0000000..7b25cdb
--- /dev/null
@@ -0,0 +1,20 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var a: nullable Int = 1
+var b: nullable Int = a.as(Int)
+var c: nullable Int = a.as(not null)
+assert c isa Int
+assert test1: c isa Int
+assert test2: c isa Int else abort
diff --git a/tests/sav/nitpretty_args19.res b/tests/sav/nitpretty_args19.res
new file mode 100644 (file)
index 0000000..f53462a
--- /dev/null
@@ -0,0 +1,28 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var a = 1
+var b = 2
+assert a == 2
+assert not a < 2 # comment 1
+assert a > 2 and b >= 2
+assert b != 2 or a <= 2
+assert b != null # comment 2
+# comment 3
+print a + b
+print a - b # comment 4
+print a * b
+print a / b
+print a % b
+print -a # comment 5
diff --git a/tests/sav/nitpretty_args2.res b/tests/sav/nitpretty_args2.res
new file mode 100644 (file)
index 0000000..7afcc94
--- /dev/null
@@ -0,0 +1,23 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Testing only imports
+
+# Module comment
+module test_mod2 # second comment
+
+import standard::kernel
+#import standard::string
+import template # no need for string
+# import standard
diff --git a/tests/sav/nitpretty_args20.res b/tests/sav/nitpretty_args20.res
new file mode 100644 (file)
index 0000000..9d59193
--- /dev/null
@@ -0,0 +1,25 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var a = 1
+var b = 2
+assert not a < 2 and (a == b or a > b) # comment 1
+assert not a < 2 and (a == b or ((a > b) or a <= b))
+assert (a > 2 and b >= 2)
+assert (b >= 2)
+# comment 3
+var c = a + (b - a)
+var d = (a - b) + c # comment 4
+var e = (-a) # comment 5
+var f = -(a - c)
diff --git a/tests/sav/nitpretty_args21.res b/tests/sav/nitpretty_args21.res
new file mode 100644 (file)
index 0000000..9b58418
--- /dev/null
@@ -0,0 +1,87 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import end
+intrude import standard::kernel
+private import standard::string
+
+`{`}
+
+`{
+#ifdef truc
+       #undef truc
+#endif
+`}
+
+in "C headers" `{
+       #include <errno.h>
+`}
+
+fun err: Int is extern `{ return 1; `}
+
+fun errno: Int is extern `{
+       return errno;
+`}
+
+fun errnoooooooooooooooooooooooooooooooooooooooooooooooooooooooooo: Int is extern `{
+        return errno;
+`}
+
+private class A
+       var my_attr = 1234
+
+       fun baz(msg: String) import String.length, String.to_cstring, my_attr, my_attr= `{
+               char *c_msg;
+               int msg_len;
+
+               /* String_to_cstring isa a allback to msg.to_cstring */
+               c_msg = String_to_cstring( msg );
+
+               /* String_length is a callback to msg.length */
+               msg_len = String_length( msg );
+
+               printf( "received msg: %s, of length = %d\n", c_msg, msg_len );
+
+               /* A_my_attr is a callback to the getter of self.my_attr */
+               printf( "old attr %d\n", A_my_attr(recv) );
+
+               if(chose)
+                       truc;
+               else
+                       chose;
+
+               /* A_my_attr is a callback to the setter of self.my_attr= */
+               A_my_attr__assign( recv, msg_len );
+       `}
+end
+
+extern class TimeT `{time_t`}
+       new `{ return time(NULL); `}
+       new from_i(i: Int) `{ return i; `}
+       fun update `{ time(&recv); `}
+
+       fun ctime: String import NativeString.to_s_with_copy `{
+               return NativeString_to_s_with_copy( ctime(&recv) );
+       `}
+
+       # Difference in secondes from start (self if the end time)
+       fun difftime(start: TimeT): Float `{ return difftime(recv, start); `}
+
+       private fun intern_poll(in_fds: Array[Int], out_fds: Array[Int]): nullable Int is extern import
+               Array[Int].length, Array[Int].[], Int.as(nullable Int) `{`}
+end
+
+fun address_is_null: Bool is extern "address_is_null"
+
+fun free `{ free(recv); `}
diff --git a/tests/sav/nitpretty_args22.res b/tests/sav/nitpretty_args22.res
new file mode 100644 (file)
index 0000000..b04cd1d
--- /dev/null
@@ -0,0 +1,29 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class A
+       var a: Int # comment
+       private var b: nullable Int # happy
+       protected var c = 10 # ending
+       var d: Int = 10
+
+       # Test test...
+       var e: Int writable
+
+       var f: Int protected writable
+
+       # Adoc
+       var k: Int protected writable = 10
+       # more comments
+end # end
diff --git a/tests/sav/nitpretty_args23.res b/tests/sav/nitpretty_args23.res
new file mode 100644 (file)
index 0000000..5b727f7
--- /dev/null
@@ -0,0 +1,24 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Foo
+       var _a: Int
+       private var _b: nullable Int
+       protected var _c = 10
+       var _d: Int = 10
+end
+
+var foo = new Foo(1, 2)
+print foo._a
+foo._a = 10
diff --git a/tests/sav/nitpretty_args24.res b/tests/sav/nitpretty_args24.res
new file mode 100644 (file)
index 0000000..79ab858
--- /dev/null
@@ -0,0 +1,71 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# toplevel comment
+
+# block
+# block
+# block
+
+# Adoc1
+class A # ending comments
+       super Object
+       # super Int
+       super String
+
+       # super Truc
+
+       # inclass comments
+       # comm
+       #    ented
+       #      blocks
+
+       # Adoc2
+       fun foo do
+
+               # comment
+
+               var truc
+
+               # comment
+               # comment
+
+               # comment
+
+               var chose
+               # comment
+       end
+
+       # comm
+       #    ented
+       #      blocks
+
+       fun bar do end
+       fun baz do end
+       # comment before end
+end # ending comments
+
+# comm
+#    ented
+#      blocks
+
+abstract class B # comment
+end
+
+abstract class C end
+
+abstract class B # comment 2
+end
+
+abstract class C end
diff --git a/tests/sav/nitpretty_args25.res b/tests/sav/nitpretty_args25.res
new file mode 100644 (file)
index 0000000..6638706
--- /dev/null
@@ -0,0 +1,123 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Foo
+       fun bar: Bool do return true
+
+       fun foo(other: Foo): Foo do
+               if other.bar then
+                       return other
+               else
+                       return self
+               end
+       end
+
+       fun baz: Int do
+               var nb = 0
+
+               while nb < 10 do
+                       print nb
+                       nb += 1
+               end # 1
+
+               return nb
+       end
+
+       fun gaz: Int do
+               if bar then # 3
+                       return 1
+               else
+                       return -1 # 4
+               end
+       end
+end
+
+class Test[E]
+       var heap: ArrayHeap[E]
+       init to(comparator: Comparator[E]) do heap = new ArrayHeap[E](comparator)
+
+       init from(comparator: Comparator[E], items: Collection[E]) do
+               heap = new ArrayHeap[E].from(comparator, items.to_a)
+       end
+
+       fun count(k: E): Int do
+               if heap.has(k) then
+                       return 1
+               else
+                       return 0
+               end
+       end
+
+       fun node_at_idx(i: Int, k: E) do
+               while heap != null do
+                       if heap.is_empty or i == k then # FIXME prefilter because the compiler is not smart enought yet
+                               break
+                       end
+               end
+       end
+
+       fun save_those_nodes(nodes: Collection[Object]) do for node in nodes do count(node)
+end
+
+fun foo do
+       if last_slash > 0 then
+               return substring(last_slash + 1, length)
+       else
+               return null
+       end
+end
+
+print "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam tincidun" +
+       "t sapien et velit fringilla varius at non eros. Nunc ut ultricies metus, sit a" +
+       "met lacinia felis. Donec in facilisis neque, non laoreet nibh. Etiam nec purus" +
+       " eu orci congue iaculis eu quis lorem. Ut et blandit erat. Cras fermentum pell" +
+       "entesque ante, ut dapibus ipsum placerat sit amet. Vivamus pharetra, sem vitae" +
+       " consequat venenatis, diam risus placerat est, sed hendrerit purus justo vitae" +
+       " lectus. In id quam mattis, rutrum augue eu, vehicula ipsum. Nulla nec egestas" +
+       " turpis, nec ullamcorper odio. Pellentesque vitae arcu justo. Aliquam sed phar" +
+       "etra lacus."
+
+var lorem = "lorem"
+var ipsum = "ipsum" # for fun
+
+print "We also need to handle super strings: {lorem} {ipsum} dolor sit amet, con" +
+       "sectetur adipiscing elit. Aliquam tincidunt sapien et velit fringilla varius a" +
+       "t non eros. Nunc ut ultricies metus, sit amet lacinia felis. Donec in facilisi" +
+       "s neque, non laoreet nibh. Etiam nec purus eu orci congue iaculis eu quis {lorem}" +
+       ". Ut et blandit erat. Cras fermentum pellentesque ante, ut dapibus {ipsum} pla" +
+       "cerat sit amet. Vivamus pharetra, sem vitae consequat venenatis, diam risus pl" +
+       "acerat est, sed hendrerit purus justo vitae lectus. In id quam mattis, rutrum " +
+       "augue eu, vehicula ipsum. Nulla nec egestas turpis, nec ullamcorper odio. Pell" +
+       "entesque vitae arcu justo. Aliquam sed pharetra lacus." # ending
+
+var title = "title"
+var links = new Array[String] # why not?
+
+var body = """
+<!DOCTYPE html>
+<head>
+       <meta charset="utf-8">
+       <meta http-equiv="X-UA-Compatible" content="IE=edge">
+       <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
+       <title>{{{title}}}</title>
+</head>
+<body>
+       <div class="container">
+               <h1>{{{title}}}</h1>
+               <ul>
+                       <li>{{{links.join("</li>\n\t\t\t<li>")}}}</li>
+               </ul>
+       </div>
+</body>
+</html>"""
diff --git a/tests/sav/nitpretty_args26.res b/tests/sav/nitpretty_args26.res
new file mode 100644 (file)
index 0000000..5bafc26
--- /dev/null
@@ -0,0 +1,43 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# prims
+
+var a = true
+var b = false
+var c = 10
+var d = -10
+var e = 1.12
+var f = -1.12
+var n = 'a'
+var o = null
+var p = 0x12345678
+
+# strings
+
+var g = "test"
+var h1 = "Hello {g}"
+var h2 = "Hello \"{g}\" Hello"
+var h3 = "Hello {g}"
+var m = """
+bla
+       bla
+
+bla"""
+
+# arrays
+
+var j = [1, 2, 3]
+var k = [1..2[
+var l = [1..2]
diff --git a/tests/sav/nitpretty_args27.res b/tests/sav/nitpretty_args27.res
new file mode 100644 (file)
index 0000000..0406b29
--- /dev/null
@@ -0,0 +1,45 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module test_annot1 is platform("android")
+
+class A
+       fun foo is a, b
+       fun bar is a, b do print "1"
+
+       fun baz is
+               a
+               bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+       do
+               print "2"
+       end
+end
+
+class B
+       fun foo is a, b
+       fun bar is a, b do print "1"
+
+       fun baz is a, b do
+               bar
+               print "2"
+       end
+
+       fun gaz is
+               a
+               bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+       do
+               bar
+               print "2"
+       end
+end
diff --git a/tests/sav/nitpretty_args3.res b/tests/sav/nitpretty_args3.res
new file mode 100644 (file)
index 0000000..e9c7176
--- /dev/null
@@ -0,0 +1,22 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# A simple module
+module test_mod3
+
+# before
+print "Hello World" # comment
+# after
+
+# end
diff --git a/tests/sav/nitpretty_args4.res b/tests/sav/nitpretty_args4.res
new file mode 100644 (file)
index 0000000..9b7d917
--- /dev/null
@@ -0,0 +1,23 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# comment 1
+interface A end
+
+abstract class B # comment 2
+end
+
+class C end # comment 3
+
+enum D end # comment 4
diff --git a/tests/sav/nitpretty_args5.res b/tests/sav/nitpretty_args5.res
new file mode 100644 (file)
index 0000000..89bf16c
--- /dev/null
@@ -0,0 +1,23 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module test_class2
+
+# comment
+class A end
+
+class B[T] # comment
+end
+
+private class C[U, V: B[A]] end # comment
diff --git a/tests/sav/nitpretty_args6.res b/tests/sav/nitpretty_args6.res
new file mode 100644 (file)
index 0000000..4e6b922
--- /dev/null
@@ -0,0 +1,33 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# comment
+class A end
+
+class B[T] # comment
+       # comment
+       super A # comment
+       super C[A, B[A]]
+       # comment
+end
+
+class C[U, V: B[A]] end # comment
+
+class D super A end # comment
+
+class E
+       super A # comment
+end
+
+# end
diff --git a/tests/sav/nitpretty_args7.res b/tests/sav/nitpretty_args7.res
new file mode 100644 (file)
index 0000000..e404557
--- /dev/null
@@ -0,0 +1,45 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# comment 1
+class A
+       type FOO: Discrete
+       private var foo: FOO # comment
+
+       # comment 2
+       var bar: Int = 10
+end
+
+class B
+       super A
+
+       redef type FOO: Int
+
+       # comment 3
+       redef fun foo do return bar # comment
+
+       redef fun bar do
+               return 10 # comment 4
+       end
+
+       fun baz do return # comment 5
+       protected fun baz2 do end
+
+       fun other: String do
+               return "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+                       "aaaaaaaaaaaaaaaaaaaaaaaaaa"
+       end
+end
+
+# end
diff --git a/tests/sav/nitpretty_args8.res b/tests/sav/nitpretty_args8.res
new file mode 100644 (file)
index 0000000..be68683
--- /dev/null
@@ -0,0 +1,29 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class A
+       fun foo(a, b: Int): Bool do return true # 1
+       fun foo2(a, b: Int): Bool do return true # 2
+       fun foo3(a, b: Int): Bool do return true
+
+       fun foo4(a, b: Int): Bool do
+               var res = true # 3
+               return res # 4
+       end
+
+       fun foo5 do end # 5
+       # fun foo6 do end
+end
+
+# end
diff --git a/tests/sav/nitpretty_args9.res b/tests/sav/nitpretty_args9.res
new file mode 100644 (file)
index 0000000..bd21dbb
--- /dev/null
@@ -0,0 +1,37 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class A
+       fun foo(aaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb: Int): Bool do
+               return true
+       end # comment
+
+       fun foo2(a, b: Int): Bool do return true # comment
+
+       fun foo3(a, b: Int): Bool do # comment
+               return true # comment
+       end # comment
+
+       fun foo4(a, b: Int): Bool do # comment
+               var res = true # comment
+               return res # comment
+       end # comment
+
+       fun foo5 do end # comment
+
+       fun foo6(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
+               aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: Int) do
+               print 1
+       end
+end # comment
diff --git a/tests/sav/zzz_test_args.res b/tests/sav/zzz_test_args.res
new file mode 100644 (file)
index 0000000..77ac542
--- /dev/null
@@ -0,0 +1,2 @@
+0
+
diff --git a/tests/sav/zzz_test_args_args1.res b/tests/sav/zzz_test_args_args1.res
new file mode 100644 (file)
index 0000000..7acffac
--- /dev/null
@@ -0,0 +1,2 @@
+1
+hello
diff --git a/tests/sav/zzz_test_args_args2.res b/tests/sav/zzz_test_args_args2.res
new file mode 100644 (file)
index 0000000..3b5896e
--- /dev/null
@@ -0,0 +1,2 @@
+2
+hello world
diff --git a/tests/sav/zzz_test_envvar.res b/tests/sav/zzz_test_envvar.res
new file mode 100644 (file)
index 0000000..27ba77d
--- /dev/null
@@ -0,0 +1 @@
+true
diff --git a/tests/sav/zzz_test_in.res b/tests/sav/zzz_test_in.res
new file mode 100644 (file)
index 0000000..59f3187
--- /dev/null
@@ -0,0 +1,4 @@
+INPUT:
+foo
+bar
+
diff --git a/tests/sav/zzz_test_post_proc.res b/tests/sav/zzz_test_post_proc.res
new file mode 100644 (file)
index 0000000..ce01362
--- /dev/null
@@ -0,0 +1 @@
+hello
diff --git a/tests/sav/zzz_test_post_proc_args1.res b/tests/sav/zzz_test_post_proc_args1.res
new file mode 100644 (file)
index 0000000..94954ab
--- /dev/null
@@ -0,0 +1,2 @@
+hello
+world
diff --git a/tests/sav/zzz_test_write_args1.res b/tests/sav/zzz_test_write_args1.res
new file mode 100644 (file)
index 0000000..ce01362
--- /dev/null
@@ -0,0 +1 @@
+hello
diff --git a/tests/test_pretty/test_annot1.nit b/tests/test_pretty/test_annot1.nit
new file mode 100644 (file)
index 0000000..381cc4f
--- /dev/null
@@ -0,0 +1,52 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module test_annot1 is platform("android")
+
+class A
+       fun foo is a, b
+       fun bar is a, b do print "1"
+       fun baz is a, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb do print "2"
+end
+
+class B
+       fun foo is
+               a
+               b
+       end
+
+       fun bar is
+               a
+               b
+       do
+               print "1"
+       end
+
+       fun baz is
+               a
+               b
+       do
+               bar
+               print "2"
+       end
+
+       fun gaz is
+               a
+               bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+       do
+               bar
+               print "2"
+       end
+
+end
diff --git a/tests/test_pretty/test_attr1.nit b/tests/test_pretty/test_attr1.nit
new file mode 100644 (file)
index 0000000..e14cef2
--- /dev/null
@@ -0,0 +1,35 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class A
+       var a: Int # comment
+       private var b: nullable Int # happy
+       protected var c = 10 # ending
+       var d: Int = 10
+
+
+
+
+
+       # Test test...
+       var e: Int writable
+       var f: Int protected writable
+       # Adoc
+var k: Int protected writable = 10
+
+
+
+# more comments
+                       end # end
+
diff --git a/tests/test_pretty/test_attr2.nit b/tests/test_pretty/test_attr2.nit
new file mode 100644 (file)
index 0000000..5b727f7
--- /dev/null
@@ -0,0 +1,24 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Foo
+       var _a: Int
+       private var _b: nullable Int
+       protected var _c = 10
+       var _d: Int = 10
+end
+
+var foo = new Foo(1, 2)
+print foo._a
+foo._a = 10
diff --git a/tests/test_pretty/test_call1.nit b/tests/test_pretty/test_call1.nit
new file mode 100644 (file)
index 0000000..805b214
--- /dev/null
@@ -0,0 +1,36 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class A
+       fun foo do end
+       fun bar(a: Int): Int do return 1
+       fun baz(a, b: Int) do end
+       fun gaz(a: Int, b: Float...) do end
+end
+
+fun top1 do end
+fun top2(a: Int) do end
+
+# comment 1
+var a = new A # comment 2
+a.foo # comment 3
+a.bar(1) # comment 4
+a.baz(1, 2) # comment 5
+top1 # comment 6
+top2(10) # comment 7
+
+print 10 # comment 8
+
+var b = a.bar(1)
+
diff --git a/tests/test_pretty/test_call2.nit b/tests/test_pretty/test_call2.nit
new file mode 100644 (file)
index 0000000..789abdd
--- /dev/null
@@ -0,0 +1,39 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class A
+       var attr: Int
+       fun foo1=(i: Int) do end
+       fun foo2=(i, j: Int) do end
+       fun [](a: Int): Int is abstract
+       fun []=(a, b: Int) do end
+end
+
+class B
+       fun [](a, b: Int): Int is abstract
+       fun []=(a, b, c: Int) do end
+end
+
+# comment 1
+var a = new A(10) # comment 2
+
+a.foo1 = 10 # comment 3
+a.foo2(1) = 10 # comment 4
+print a[1] # comment 5
+a[1] = 2 # comment 6
+a[2] += 3 # comment 7
+
+var b = new B
+print b[1, 2]
+b[1, 2] = 10
diff --git a/tests/test_pretty/test_class1.nit b/tests/test_pretty/test_class1.nit
new file mode 100644 (file)
index 0000000..fc3f239
--- /dev/null
@@ -0,0 +1,25 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# comment 1
+interface A end
+
+abstract class B # comment 2
+end
+
+class C
+end # comment 3
+
+enum D end # comment 4
+
diff --git a/tests/test_pretty/test_class2.nit b/tests/test_pretty/test_class2.nit
new file mode 100644 (file)
index 0000000..2a61cf1
--- /dev/null
@@ -0,0 +1,25 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module test_class2
+
+
+# comment
+class A end
+
+class B[T] # comment
+end
+
+private class C[U, V: B[A]] end # comment
+
diff --git a/tests/test_pretty/test_class3.nit b/tests/test_pretty/test_class3.nit
new file mode 100644 (file)
index 0000000..20ea6d3
--- /dev/null
@@ -0,0 +1,44 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# comment
+class A
+end
+
+class B[T] # comment
+# comment
+super A # comment
+
+
+       super C[A, B[A]]
+# comment
+end
+
+class C[U, V: B[A]] end # comment
+
+class D
+       super A
+
+
+end # comment
+
+class E
+
+
+
+                       super A # comment
+end
+
+               # end
+
diff --git a/tests/test_pretty/test_comments1.nit b/tests/test_pretty/test_comments1.nit
new file mode 100644 (file)
index 0000000..d891d45
--- /dev/null
@@ -0,0 +1,101 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+# toplevel comment
+
+
+
+
+
+
+# block
+# block
+# block
+
+
+
+
+
+# Adoc1
+class A                                                # ending comments
+
+       super Object
+       # super Int
+
+       
+       super String
+       # super Truc
+
+
+
+# inclass comments
+       # comm
+       #    ented
+       #      blocks
+
+
+
+       # Adoc2
+       fun foo do
+               
+               # comment
+
+
+
+               var truc
+
+               # comment
+               # comment
+
+               
+               
+               # comment
+               
+               
+               var chose
+
+               # comment
+       end
+
+# comm
+#    ented
+#      blocks
+
+
+       fun bar do end
+       
+       
+fun baz do end
+# comment before end
+
+end # ending comments
+
+# comm
+#    ented
+#      blocks
+
+abstract class B # comment
+end
+
+abstract class C
+end
+
+abstract class B # comment 2
+
+end
+
+abstract class C
+
+end
diff --git a/tests/test_pretty/test_extern1.nit b/tests/test_pretty/test_extern1.nit
new file mode 100644 (file)
index 0000000..d2fc373
--- /dev/null
@@ -0,0 +1,86 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import end
+intrude import standard::kernel
+private import standard::string
+
+`{`}
+
+`{
+#ifdef truc
+       #undef truc
+#endif
+`}
+
+in "C headers" `{
+       #include <errno.h>
+`}
+
+fun err: Int is extern `{ return 1; `}
+
+fun errno: Int is extern `{
+       return errno;
+`}
+
+fun errnoooooooooooooooooooooooooooooooooooooooooooooooooooooooooo: Int is extern `{ return errno; `}
+
+private class A
+    var my_attr = 1234
+
+    fun baz( msg : String ) import String.length, String.to_cstring, my_attr, my_attr= `{
+               char *c_msg;
+               int msg_len;
+
+               /* String_to_cstring isa a allback to msg.to_cstring */ 
+               c_msg = String_to_cstring( msg );
+
+               /* String_length is a callback to msg.length */
+               msg_len = String_length( msg );
+
+               printf( "received msg: %s, of length = %d\n", c_msg, msg_len );
+
+               /* A_my_attr is a callback to the getter of self.my_attr */
+               printf( "old attr %d\n", A_my_attr(recv) );
+
+               if(chose)
+                       truc;
+               else
+                       chose;
+
+               /* A_my_attr is a callback to the setter of self.my_attr= */
+               A_my_attr__assign( recv, msg_len );
+    `}
+end
+
+extern class TimeT `{time_t`}
+       new `{ return time(NULL); `}
+       new from_i(i: Int) `{ return i; `}
+
+       fun update `{ time(&recv); `}
+
+       fun ctime: String import NativeString.to_s_with_copy `{
+               return NativeString_to_s_with_copy( ctime(&recv) );
+       `}
+
+       # Difference in secondes from start (self if the end time)
+       fun difftime(start: TimeT): Float `{ return difftime(recv, start); `}
+
+       private fun intern_poll(in_fds: Array[Int], out_fds: Array[Int]) : nullable Int is extern import Array[Int].length, Array[Int].[], Int.as(nullable Int) `{`}
+end
+
+fun address_is_null: Bool is extern "address_is_null"
+
+fun free `{ free(recv); `}
+
diff --git a/tests/test_pretty/test_if1.nit b/tests/test_pretty/test_if1.nit
new file mode 100644 (file)
index 0000000..60bf5ef
--- /dev/null
@@ -0,0 +1,50 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var a = 1
+var b = 2
+
+if a == b then a = b
+
+if a != b then
+       a = b
+       a = b
+end
+
+if a > b then
+       b = a
+       a = b
+else
+       a = b
+       a = b
+end
+
+if a < b then
+       a = b
+       a = b
+else if a == b then
+       b = a
+       a = b
+end
+
+if a < b then
+       a = b
+       a = b
+else if a == b then
+       b = b
+       a = b
+else
+       a = b
+       a = b
+end
diff --git a/tests/test_pretty/test_if2.nit b/tests/test_pretty/test_if2.nit
new file mode 100644 (file)
index 0000000..45c3d72
--- /dev/null
@@ -0,0 +1,81 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# comment
+var a = 1# comment
+# comment
+var b = 2# comment
+
+# comment
+if a == b then a = b# comment
+
+# comment
+if a != b then# comment
+# comment
+       a = b# comment
+# comment
+       a = b# comment
+# comment
+end# comment
+
+# comment
+if a > b then# comment
+# comment
+       b = a# comment
+# comment
+       a = b# comment
+# comment
+else# comment
+# comment
+       a = b# comment
+# comment
+       a = b# comment
+# comment
+end# comment
+
+# comment
+if a < b then# comment
+# comment
+       a = b# comment
+# comment
+       a = b# comment
+# comment
+else if a == b then# comment
+# comment
+       b = a# comment
+# comment
+       a = b# comment
+# comment
+end# comment
+
+# comment
+if a < b then# comment
+# comment
+       a = b# comment
+# comment
+       a = b# comment
+# comment
+else if a == b then# comment
+# comment
+       b = b# comment
+# comment
+       a = b# comment
+# comment
+else# comment
+# comment
+       a = b# comment
+# comment
+       a = b# comment
+# comment
+end# comment
diff --git a/tests/test_pretty/test_if3.nit b/tests/test_pretty/test_if3.nit
new file mode 100644 (file)
index 0000000..8aa3fb2
--- /dev/null
@@ -0,0 +1,67 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var a = 1
+var b = 2
+
+# 0
+if a == b then # 1
+       # 2
+else # 3
+       # 4
+end # 5
+
+if a == b then print a # printing a
+
+if a == b then
+       print a # printing a
+end
+
+if a == b then
+       print a
+end # end
+
+if a == b then a = b
+
+if a == b then
+
+else
+
+end
+
+if a==b then end
+
+if a != b then
+       a = b
+end
+
+if a > b then
+       a = b
+else
+       a = b
+end
+
+if a < b then
+       a = b
+else if a == b then
+       a = b
+end
+
+if a < b then
+       a = b
+else if a == b then
+       a = b
+else
+       a = b
+end
diff --git a/tests/test_pretty/test_indent1.nit b/tests/test_pretty/test_indent1.nit
new file mode 100644 (file)
index 0000000..3812d9d
--- /dev/null
@@ -0,0 +1,106 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Foo
+       fun bar: Bool do return true
+
+       fun foo(other: Foo): Foo
+       do
+               if other.bar then return other else
+                       return self
+               end
+       end
+
+       fun baz: Int do
+               var nb = 0
+               while nb < 10 do
+                       print nb
+                       nb += 1
+end # 1
+               return nb
+       end
+
+       fun gaz: Int
+       do
+           if bar # 2
+           then # 3
+               return 1
+           else
+               return -1 # 4
+           end
+       end
+end
+
+class Test[E]
+       var heap: ArrayHeap[E]
+
+       init to(comparator: Comparator[E]) do
+               heap = new ArrayHeap[E](comparator)
+       end
+
+       init from(comparator: Comparator[E], items: Collection[E]) do
+               heap = new ArrayHeap[E].from(comparator, items.to_a)
+       end
+
+       fun count(k: E): Int do if heap.has(k) then return 1 else return 0
+
+       fun node_at_idx(i: Int, k: E) do
+               while heap != null do
+                       if heap.is_empty or i == k then # FIXME prefilter because the compiler is not smart enought yet
+                               break
+                       end
+               end
+       end
+
+       fun save_those_nodes(nodes: Collection[Object]) do
+               for node in nodes do count(node)
+       end
+end
+
+fun foo do
+       if last_slash > 0 then
+               return substring( last_slash+1, length )
+       else
+               return null
+       end
+end
+
+print "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam tincidunt sapien et velit fringilla varius at non eros. Nunc ut ultricies metus, sit amet lacinia felis. Donec in facilisis neque, non laoreet nibh. Etiam nec purus eu orci congue iaculis eu quis lorem. Ut et blandit erat. Cras fermentum pellentesque ante, ut dapibus ipsum placerat sit amet. Vivamus pharetra, sem vitae consequat venenatis, diam risus placerat est, sed hendrerit purus justo vitae lectus. In id quam mattis, rutrum augue eu, vehicula ipsum. Nulla nec egestas turpis, nec ullamcorper odio. Pellentesque vitae arcu justo. Aliquam sed pharetra lacus."
+
+var lorem = "lorem" 
+var ipsum = "ipsum" # for fun
+
+print "We also need to handle super strings: {lorem} {ipsum} dolor sit amet, consectetur adipiscing elit. Aliquam tincidunt sapien et velit fringilla varius at non eros. Nunc ut ultricies metus, sit amet lacinia felis. Donec in facilisis neque, non laoreet nibh. Etiam nec purus eu orci congue iaculis eu quis {lorem}. Ut et blandit erat. Cras fermentum pellentesque ante, ut dapibus {ipsum} placerat sit amet. Vivamus pharetra, sem vitae consequat venenatis, diam risus placerat est, sed hendrerit purus justo vitae lectus. In id quam mattis, rutrum augue eu, vehicula ipsum. Nulla nec egestas turpis, nec ullamcorper odio. Pellentesque vitae arcu justo. Aliquam sed pharetra lacus." # ending
+
+var title = "title"
+var links = new Array[String] # why not?
+
+var body = """
+<!DOCTYPE html>
+<head>
+       <meta charset="utf-8">
+       <meta http-equiv="X-UA-Compatible" content="IE=edge">
+       <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
+       <title>{{{title}}}</title>
+</head>
+<body>
+       <div class="container">
+               <h1>{{{title}}}</h1>
+               <ul>
+                       <li>{{{links.join("</li>\n\t\t\t<li>")}}}</li>
+               </ul>
+       </div>
+</body>
+</html>"""
+
diff --git a/tests/test_pretty/test_loop1.nit b/tests/test_pretty/test_loop1.nit
new file mode 100644 (file)
index 0000000..1ccf518
--- /dev/null
@@ -0,0 +1,36 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var a = 1
+var b = 2
+
+while a != b do # comment 1
+       # comment 2
+       var tmp = a
+       a = b
+       b = tmp
+       # comment 3
+end
+
+# comment 4
+while a != b do
+       a = b
+end # comment 5
+
+while a != b do
+       # comment 6
+end # comment 7
+
+# end
+
diff --git a/tests/test_pretty/test_loop2.nit b/tests/test_pretty/test_loop2.nit
new file mode 100644 (file)
index 0000000..546fc90
--- /dev/null
@@ -0,0 +1,53 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var a = 0
+var b = 2
+
+do # comment 1
+       # comment 2
+       var tmp = a
+       a = b
+       b = tmp
+       # comment 3
+end
+
+# comment 4
+do
+       a = b
+end # comment 5
+
+do
+       # comment 6
+end
+
+if a > b then loop print a # test
+
+if a > b then
+       loop print a
+end
+
+if a > b then
+       loop
+               print a
+       end
+end
+
+if a > b then
+       loop
+               # comment 7
+               print a
+       end
+end
+
diff --git a/tests/test_pretty/test_loop3.nit b/tests/test_pretty/test_loop3.nit
new file mode 100644 (file)
index 0000000..94e85fb
--- /dev/null
@@ -0,0 +1,29 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var a = 0
+
+for i in [1, 2, 3] do# comment 1
+       # comment 2
+       a += i
+end
+
+# comment 4
+for i in [1..3] do
+       a += i
+end # comment 5
+
+for i in [1..3[ do
+       # comment 6
+end
diff --git a/tests/test_pretty/test_mod1.nit b/tests/test_pretty/test_mod1.nit
new file mode 100644 (file)
index 0000000..f55be8f
--- /dev/null
@@ -0,0 +1,18 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+
+# An empty module
+
diff --git a/tests/test_pretty/test_mod2.nit b/tests/test_pretty/test_mod2.nit
new file mode 100644 (file)
index 0000000..c8adb76
--- /dev/null
@@ -0,0 +1,24 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Testing only imports
+
+# Module comment
+module test_mod2 # second comment
+
+   import standard::kernel
+#import standard::string
+
+       import template # no need for string
+# import standard
diff --git a/tests/test_pretty/test_mod3.nit b/tests/test_pretty/test_mod3.nit
new file mode 100644 (file)
index 0000000..2fa4856
--- /dev/null
@@ -0,0 +1,25 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# A simple module
+module test_mod3
+
+                               # before
+               print      "Hello World"      # comment
+               # after
+
+               # end
+
+
+
diff --git a/tests/test_pretty/test_op1.nit b/tests/test_pretty/test_op1.nit
new file mode 100644 (file)
index 0000000..4fec81e
--- /dev/null
@@ -0,0 +1,21 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var a: nullable Int = 1
+var b: nullable Int = a.as(Int)
+var c: nullable Int = a.as(not null)
+
+assert c isa Int
+assert test1: c isa Int
+assert test2: c isa Int else abort
diff --git a/tests/test_pretty/test_op2.nit b/tests/test_pretty/test_op2.nit
new file mode 100644 (file)
index 0000000..3562617
--- /dev/null
@@ -0,0 +1,31 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var a = 1
+var b = 2
+
+assert a == 2
+assert not a < 2 # comment 1
+assert a > 2 and b >= 2
+assert b != 2 or a <= 2
+assert b != null # comment 2
+
+# comment 3
+print a + b
+print a - b # comment 4
+print a * b
+print a / b
+print a % b
+
+print -a # comment 5
diff --git a/tests/test_pretty/test_op3.nit b/tests/test_pretty/test_op3.nit
new file mode 100644 (file)
index 0000000..641f01c
--- /dev/null
@@ -0,0 +1,27 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var a = 1
+var b = 2
+
+assert not a < 2 and (a == b or a > b)# comment 1
+assert not a < 2 and (a == b or ((a > b) or a <= b))
+assert (a > 2 and b >= 2)
+assert (b >= 2)
+
+# comment 3
+var c = a + (b - a)
+var d = (a - b) + c # comment 4
+var e = (-a) # comment 5
+var f = -(a - c)
diff --git a/tests/test_pretty/test_prims1.nit b/tests/test_pretty/test_prims1.nit
new file mode 100644 (file)
index 0000000..721a3e1
--- /dev/null
@@ -0,0 +1,48 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# prims
+
+var a = true
+var b = false
+
+var c          =        10
+       var d = -10
+var e = 1.12
+
+var f = -1.12
+var n = 'a'
+var o = null
+var p = 0x12345678
+
+# strings
+
+var g = "test"
+var h1 = "Hello {g}"
+var h2 = "Hello \"{g}\" Hello"
+var h3 = "Hello {g}"
+       var m = """
+bla
+       bla
+
+bla"""
+
+       # arrays
+
+var j = [1,2,3]
+var k=[ 1 .. 2 [
+var l  = [1..2]
+
+
+
diff --git a/tests/test_pretty/test_prop1.nit b/tests/test_pretty/test_prop1.nit
new file mode 100644 (file)
index 0000000..0b46c27
--- /dev/null
@@ -0,0 +1,41 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# comment 1
+class A
+type FOO: Discrete
+       private var foo: FOO # comment
+# comment 2
+       var bar: Int = 10
+end
+
+class B
+       super A
+
+       redef type FOO: Int
+# comment 3
+       redef fun foo do return bar # comment
+       redef fun bar
+       do
+               return 10 # comment 4
+       end
+       fun baz do
+               return
+       end # comment 5
+       protected fun baz2 do end
+       fun other: String do return "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+end
+
+# end
+
diff --git a/tests/test_pretty/test_prop2.nit b/tests/test_pretty/test_prop2.nit
new file mode 100644 (file)
index 0000000..caae0a8
--- /dev/null
@@ -0,0 +1,34 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class A
+       fun foo(a, b: Int): Bool do return true # 1
+
+       fun foo2(a, b: Int): Bool do return true end # 2
+
+       fun foo3(a, b: Int): Bool do
+               return true
+       end
+
+       fun foo4(a, b: Int): Bool do
+               var res = true # 3
+               return res # 4
+       end
+
+       fun foo5 do end # 5
+       # fun foo6 do end
+end
+
+# end
+
diff --git a/tests/test_pretty/test_prop3.nit b/tests/test_pretty/test_prop3.nit
new file mode 100644 (file)
index 0000000..60408c5
--- /dev/null
@@ -0,0 +1,35 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class A
+       fun foo(aaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb: Int): Bool do return true # comment
+
+       fun foo2(a, b: Int): Bool do return true end # comment
+
+       fun foo3(a, b: Int): Bool do # comment
+               return true # comment
+       end # comment
+
+       fun foo4(a, b: Int): Bool do # comment
+               var res = true # comment
+               return res # comment
+       end # comment
+
+       fun foo5 do end # comment
+
+       fun foo6(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: Int) do
+               print 1
+       end
+
+end # comment
diff --git a/tests/zzz_test_args.args b/tests/zzz_test_args.args
new file mode 100644 (file)
index 0000000..1709fa9
--- /dev/null
@@ -0,0 +1,2 @@
+hello
+hello world
diff --git a/tests/zzz_test_in.inputs b/tests/zzz_test_in.inputs
new file mode 100644 (file)
index 0000000..3bd1f0e
--- /dev/null
@@ -0,0 +1,2 @@
+foo
+bar
diff --git a/tests/zzz_test_post_proc.args b/tests/zzz_test_post_proc.args
new file mode 100644 (file)
index 0000000..eccc3a1
--- /dev/null
@@ -0,0 +1 @@
+; echo "world"
diff --git a/tests/zzz_test_write.args b/tests/zzz_test_write.args
new file mode 100644 (file)
index 0000000..a62688b
--- /dev/null
@@ -0,0 +1 @@
+$WRITE
index 8de86e9..61d8347 100644 (file)
@@ -1 +1,15 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 import kernel
diff --git a/tests/zzz_tests/zzz_test_args.nit b/tests/zzz_tests/zzz_test_args.nit
new file mode 100644 (file)
index 0000000..0d5a331
--- /dev/null
@@ -0,0 +1,16 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+print args.length
+print args.join(" ")
diff --git a/tests/zzz_tests/zzz_test_envvar.nit b/tests/zzz_tests/zzz_test_envvar.nit
new file mode 100644 (file)
index 0000000..d5fd881
--- /dev/null
@@ -0,0 +1,15 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+print "NIT_TESTING".environ
index c76b503..8dd3703 100644 (file)
@@ -1,2 +1,16 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 import kernel
 1.output
index c76b503..8dd3703 100644 (file)
@@ -1,2 +1,16 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 import kernel
 1.output
index c76b503..8dd3703 100644 (file)
@@ -1,2 +1,16 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 import kernel
 1.output
index c76b503..8dd3703 100644 (file)
@@ -1,2 +1,16 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 import kernel
 1.output
diff --git a/tests/zzz_tests/zzz_test_in.nit b/tests/zzz_tests/zzz_test_in.nit
new file mode 100644 (file)
index 0000000..704e87e
--- /dev/null
@@ -0,0 +1,16 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+print "INPUT:"
+print stdin.read_all
index c76b503..8dd3703 100644 (file)
@@ -1,2 +1,16 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 import kernel
 1.output
index c76b503..8dd3703 100644 (file)
@@ -1,2 +1,16 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 import kernel
 1.output
diff --git a/tests/zzz_tests/zzz_test_post_proc.nit b/tests/zzz_tests/zzz_test_post_proc.nit
new file mode 100644 (file)
index 0000000..01b343d
--- /dev/null
@@ -0,0 +1,15 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+print "hello"
index 6106e56..93273b1 100644 (file)
@@ -1,3 +1,17 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 import string
 0.output
 "Error: bla bla".output
index d1c18f5..4e41242 100644 (file)
@@ -1,2 +1,16 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 import string
 "NOT YET IMPLEMENTED".output
diff --git a/tests/zzz_tests/zzz_test_write.nit b/tests/zzz_tests/zzz_test_write.nit
new file mode 100644 (file)
index 0000000..66082c4
--- /dev/null
@@ -0,0 +1,16 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+if args.length == 0 then return
+"hello\n".write_to_file args.first