Rename REAMDE to README.md
[nit.git] / src / pretty.nit
index 2d08571..e4d848d 100644 (file)
@@ -99,7 +99,20 @@ class PrettyPrinterVisitor
                n.accept_pretty_printer self
        end
 
-       # Visit a list of `Anode`.
+       # Visit a list of arguments `ANode` with optional parentheses
+       fun visit_args(n: nullable ANodes[ANode]) do
+               if n == null or n.is_empty then return
+               if current_token isa TOpar then
+                       consume "("
+               else
+                       adds
+               end
+
+               visit_list n
+               if current_token isa TCpar then consume ")"
+       end
+
+       # Visit a list of `ANode`.
        fun visit_list(n: nullable ANodes[ANode]) do
                if n == null then return
                n.accept_pretty_printer self
@@ -108,10 +121,11 @@ class PrettyPrinterVisitor
        # 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 no_inline and n.location.line_start != n.location.line_end then return false
                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
+               if max_size > 0 and n.collect_length + current_length > max_size then return false
                # check block is inlinable
                return n.is_inlinable
        end
@@ -145,12 +159,22 @@ class PrettyPrinterVisitor
        # 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
+               while current_token != null and current_token != target do skip
+               if current_token == null then
+                       target.debug("Looked for, but not found :(")
+                       abort
+               end
+       end
+
+       # Consume comments and end of lines if any
+       fun consume_comments do
+               while current_token isa TEol or current_token isa TComment do visit current_token
        end
 
        # Visit `current_token`.
        fun consume(token: String) do
-               assert current_token.text == token
+               consume_comments
+               if current_token.text == token then else current_token.debug("Got `{current_token.text}`; expected `{token}`.")
                visit current_token
        end
 
@@ -196,7 +220,8 @@ class PrettyPrinterVisitor
        var tab_size = 8
 
        # Max line size.
-       var max_size = 80
+       # 0 (or negative) to disable.
+       var max_size = 80 is writable
 
        # Length of the current line.
        var current_length = 0
@@ -260,6 +285,9 @@ class PrettyPrinterVisitor
 
        # Do we force the deletion of empty lines?
        var skip_empty = false is public writable
+
+       # Disable automatic inlining.
+       var no_inline = false is writable
 end
 
 # Base framework redefs
@@ -269,6 +297,8 @@ redef class ANodes[E]
                for e in self do
                        var e_can_inline = v.can_inline(e)
 
+                       if v.current_token isa TComma then v.skip
+
                        if e != first then
                                if not e_can_inline then
                                        v.add ","
@@ -509,15 +539,7 @@ redef class AAnnotation
                        v.adds
                end
                v.visit n_atid
-               if not n_args.is_empty then
-                       if n_opar == null then
-                               v.adds
-                       else
-                               v.visit n_opar
-                       end
-                       v.visit_list n_args
-                       v.visit n_cpar
-               end
+               v.visit_args n_args
        end
 end
 
@@ -691,8 +713,8 @@ redef class AStdClassdef
                if can_inline then
                        v.adds
 
-                       if not n_superclasses.is_empty then
-                               for n_superclass in n_superclasses do
+                       if not n_propdefs.is_empty then
+                               for n_superclass in n_propdefs do
                                        v.visit n_superclass
                                        v.adds
                                end
@@ -702,18 +724,6 @@ redef class AStdClassdef
                        if v.skip_empty then 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
-                               if v.skip_empty then v.addn
-                       end
-
                        super
                        v.catch_up n_kwend
                        v.indent -= 1
@@ -727,8 +737,9 @@ redef class AStdClassdef
 
        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
+               # FIXME: repair pretty-printing one-liner classes
+               if n_propdefs.length > 0 then return false
+               #if n_propdefs.length == 1 and not n_propdefs.first isa ASuperPropdef then return false
                if not collect_comments.is_empty then return false
                return true
        end
@@ -785,14 +796,6 @@ redef class AType
        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
@@ -800,7 +803,7 @@ redef class APropdef
                v.visit n_doc
                v.addt
 
-               if not n_visibility isa APublicVisibility then
+               if not n_visibility isa nullable APublicVisibility then
                        v.visit n_visibility
                        v.adds
                end
@@ -1005,6 +1008,20 @@ redef class AMainMethPropdef
        end
 end
 
+redef class ASuperPropdef
+       redef fun accept_pretty_printer(v) do
+               super
+               v.visit n_kwsuper
+               v.adds
+               v.visit n_type
+               visit_annotations(v, n_annotations)
+               v.finish_line
+               v.addn
+       end
+
+       redef fun is_inlinable do return true
+end
+
 redef class ASignature
        redef fun accept_pretty_printer(v) do
                if not n_params.is_empty then
@@ -1046,7 +1063,7 @@ redef class AExternCalls
                        v.adds
                        v.visit_list n_extern_calls
                else
-                       v.addn
+                       v.forcen
                        v.indent += 1
                        v.addt
                        v.indent -= 1
@@ -1146,7 +1163,7 @@ redef class TExternCodeSegment
                                v.add "`\{"
 
                                if not lines.first.trim.is_empty then
-                                       v.addn
+                                       v.forcen
                                        lines.first.l_trim
                                        v.indent += 1
                                        v.addt
@@ -1223,7 +1240,7 @@ redef class AIfExpr
                        v.adds
                else
                        v.visit n_expr
-                       v.addn
+                       v.forcen
                        v.addt
                end
 
@@ -1274,10 +1291,11 @@ redef class AIfExpr
                                end
                        end
 
-                       if has_else(v) then
-                               while not v.current_token isa TKwelse do
-                                       v.consume v.current_token.text
-                               end
+                       v.consume_comments
+
+                       # FIXME: for some unknown reasons, has_else can be true even if
+                       # there is no `else` keyword but a `end` instead.
+                       if has_else(v) and v.current_token isa TKwelse then
 
                                v.indent -= 1
                                v.addt
@@ -1564,7 +1582,7 @@ redef class ACallExpr
                v.visit_recv n_expr
 
                if not n_expr isa AImplicitSelfExpr and not can_inline then
-                       v.addn
+                       v.forcen
                        v.addt
                end
 
@@ -1577,14 +1595,7 @@ redef class ACallExpr
                                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 ")"
+                               v.visit_args n_args.n_exprs
                        end
                end
        end
@@ -1705,12 +1716,7 @@ redef class AInitExpr
                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
+               v.visit_args n_args.n_exprs
        end
 end
 
@@ -1725,7 +1731,7 @@ redef class ANewExpr
                        v.consume "."
 
                        if not can_inline then
-                               v.addn
+                               v.forcen
                                v.indent += 1
                                v.addt
                                v.indent -= 1
@@ -1734,11 +1740,7 @@ redef class ANewExpr
                        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
+               v.visit_args n_args.n_exprs
        end
 
        redef fun is_inlinable do return true
@@ -1847,7 +1849,7 @@ redef class AAssertExpr
                                else
                                        v.addt
                                        v.visit n_else
-                                       v.addn
+                                       v.forcen
                                        v.indent -= 1
                                        v.addt
                                        v.add "end"
@@ -1885,14 +1887,7 @@ redef class ASuperExpr
                                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 ")"
+                               v.visit_args n_args.n_exprs
                        end
                end
        end
@@ -1982,7 +1977,7 @@ private class ABinOpHelper
                        v.adds
                        v.visit bin_expr2
                else
-                       v.addn
+                       v.forcen
                        v.indent += 1
                        v.addt
                        v.indent -= 1
@@ -2020,66 +2015,7 @@ redef class ABinopExpr
 
        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 AStarstarExpr
-       redef fun bin_op do return "**"
-end
-
-redef class AStarshipExpr
-       redef fun bin_op do return "<=>"
+       redef fun bin_op do return operator
 end
 
 redef class AIsaExpr
@@ -2108,9 +2044,9 @@ end
 
 # Syntax
 
-redef class AUminusExpr
+redef class AUnaryopExpr
        redef fun accept_pretty_printer(v) do
-               v.consume "-"
+               v.visit n_op
                v.visit n_expr
        end
 end
@@ -2132,6 +2068,11 @@ redef class AArrayExpr
        redef fun accept_pretty_printer(v) do
                v.consume "["
                v.visit_list n_exprs
+               if n_type != null then
+                       v.consume ":"
+                       v.adds
+                       v.visit n_type
+               end
                v.consume "]"
        end
 end
@@ -2175,7 +2116,7 @@ redef class AStringFormExpr
                        while i < text.length do
                                v.add text[i].to_s
 
-                               if v.current_length >= v.max_size and i <= text.length - 3 then
+                               if v.max_size > 0 and v.current_length >= v.max_size and i <= text.length - 3 then
                                        v.add "\" +"
                                        if was_inline then
                                                v.forcen