Rename REAMDE to README.md
[nit.git] / src / pretty.nit
index 8d7a45a..e4d848d 100644 (file)
@@ -79,7 +79,7 @@ class PrettyPrinterVisitor
                current_token = nmodule.location.file.first_token
                visit nmodule
                catch_up nmodule.location.file.last_token
-               tpl.add "\n"
+               if skip_empty then tpl.add "\n"
                return tpl.as(not null)
        end
 
@@ -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
 
@@ -172,7 +196,7 @@ class PrettyPrinterVisitor
                else
                        abort
                end
-               assert current_token.location <= token.location
+               if current_token.location > token.location then return
                while current_token != token do visit current_token
        end
 
@@ -183,7 +207,7 @@ class PrettyPrinterVisitor
                        visit current_token
                end
 
-               while current_token isa TEol do skip
+               while current_token isa TEol do visit(current_token)
        end
 
        # The template under construction.
@@ -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
@@ -223,6 +248,14 @@ class PrettyPrinterVisitor
                if current_length == 0 and last_line_is_blank then return
                previous_length = current_length
                current_length = 0
+               if skip_empty then wait_addn += 1
+       end
+
+       # Perform `addn` even if not `skip_empty`.
+       fun forcen do
+               if current_length == 0 and last_line_is_blank then return
+               previous_length = current_length
+               current_length = 0
                wait_addn += 1
        end
 
@@ -243,6 +276,18 @@ class PrettyPrinterVisitor
                        consume "."
                end
        end
+
+       # Do we break string literals that are too long?
+       var break_strings = false is public writable
+
+       # Do we force `do` to be on the same line as the method signature?
+       var inline_do = false is public writable
+
+       # 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
@@ -252,12 +297,15 @@ 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 ","
-                                       v.addn
-                                       v.addt
+                                       v.forcen
+                                       v.indent += 1
                                        v.addt
+                                       v.indent -= 1
                                else
                                        v.add ", "
                                end
@@ -308,6 +356,17 @@ redef class Token
        redef fun was_inline do return true
 end
 
+redef class TEol
+       redef fun accept_pretty_printer(v) do
+               if v.skip_empty then
+                       super
+               else
+                       v.add text
+                       v.current_token = next_token
+               end
+       end
+end
+
 redef class Prod
        redef fun accept_pretty_printer(v) do v.visit first_token
 
@@ -344,7 +403,7 @@ redef class Prod
        end
 
        redef fun was_inline do
-               return first_token.location.line_start == last_token.location.line_end
+               return start_token.location.line_start == last_token.location.line_end
        end
 end
 
@@ -355,13 +414,13 @@ redef class TComment
                if is_adoc then
                        v.addt
                        super
-                       v.addn
+                       v.forcen
                        return
                end
 
                if is_licence then
                        super
-                       v.addn
+                       v.forcen
                        if is_last_in_group then v.addn
                        return
                end
@@ -370,7 +429,7 @@ redef class TComment
                        v.addn
                        v.addt
                        super
-                       v.addn
+                       v.forcen
                        v.addn
                        return
                end
@@ -379,13 +438,14 @@ redef class TComment
                        if next_token isa TComment and is_first_in_group then v.addn
                        v.addt
                        super
-                       v.addn
+                       v.forcen
                        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
+               if not v.skip_empty then v.forcen
        end
 
        # Is `self` part of an `ADoc`?
@@ -434,7 +494,6 @@ 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
@@ -443,21 +502,27 @@ redef class AAnnotations
                                        v.add ", "
                                end
                        end
-                       v.finish_line
-               else if n_items.length > 1 then
-                       v.addn
+                       if not was_inline then
+                               v.finish_line
+                               if v.current_token isa TKwend then v.skip
+                       end
+               else
+                       v.forcen
                        v.indent += 1
-
                        for n_item in n_items do
                                v.addt
                                v.visit n_item
                                v.finish_line
-                               v.addn
+                               if n_item != n_items.last then
+                                       if was_inline then
+                                               v.forcen
+                                       else
+                                               v.addn
+                                       end
+                               end
                        end
-
                        v.indent -= 1
                end
-               if not was_inline and v.current_token isa TKwend then v.skip
        end
 
        redef fun is_inlinable do
@@ -469,16 +534,12 @@ end
 
 redef class AAnnotation
        redef fun accept_pretty_printer(v) do
-               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
+               if n_visibility != null and not n_visibility isa APublicVisibility then
+                       v.visit n_visibility
+                       v.adds
                end
+               v.visit n_atid
+               v.visit_args n_args
        end
 end
 
@@ -494,7 +555,7 @@ redef class AModule
                v.visit n_moduledecl
 
                if not n_imports.is_empty then
-                       v.addn
+                       if v.skip_empty then v.addn
 
                        for n_import in n_imports do
                                v.catch_up n_import
@@ -516,7 +577,7 @@ redef class AModule
                end
 
                if not n_classdefs.is_empty then
-                       v.addn
+                       if v.skip_empty then v.addn
 
                        for n_classdef in n_classdefs do
                                v.catch_up n_classdef
@@ -561,7 +622,7 @@ redef class AModuledecl
                end
 
                v.finish_line
-               v.addn
+               if v.skip_empty then v.addn
        end
 end
 
@@ -582,7 +643,7 @@ redef class ANoImport
                v.adds
                v.visit n_kwend
                v.finish_line
-               v.addn
+               if v.skip_empty then v.addn
        end
 end
 
@@ -597,7 +658,7 @@ redef class AStdImport
                v.adds
                v.visit n_name
                v.finish_line
-               v.addn
+               if v.skip_empty then v.addn
        end
 end
 
@@ -609,9 +670,9 @@ redef class AClassdef
                        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
+                               if v.skip_empty and n_propdef != n_propdefs.first then v.addn
                                v.visit n_propdef
-                               if n_propdef != n_propdefs.last then v.addn
+                               if v.skip_empty and n_propdef != n_propdefs.last then v.addn
                        else
                                v.visit n_propdef
                        end
@@ -652,29 +713,17 @@ 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
                        end
                else
                        v.finish_line
-                       v.addn
+                       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
-                               v.addn
-                       end
-
                        super
                        v.catch_up n_kwend
                        v.indent -= 1
@@ -682,14 +731,15 @@ redef class AStdClassdef
 
                v.visit n_kwend
                v.finish_line
-               v.addn
+               if v.skip_empty then 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
+               # 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
@@ -746,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
@@ -761,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
@@ -772,6 +814,90 @@ redef class APropdef
                end
        end
 
+       # Factorize annotations visit for all APropdef.
+       #
+       # Return true if annotations were inlined.
+       fun visit_annotations(v: PrettyPrinterVisitor, n_annotations: nullable AAnnotations): Bool do
+               var res = v.can_inline(n_annotations)
+               if n_annotations != null then v.visit n_annotations
+               return res
+       end
+
+       # Factorize block visit for APropdefs.
+       #
+       # Were annotations printed inline? If so, we need to print the block differently.
+       fun visit_block(v: PrettyPrinterVisitor, n_block: nullable AExpr, annot_inline: Bool) do
+               # var can_inline = v.can_inline(n_block)
+               if n_block == null then return
+               if n_annotations != null and not annot_inline then
+                       v.forcen
+                       v.addt
+               end
+               if v.inline_do then
+                       while not v.current_token isa TKwdo do v.skip
+               end
+               var token = v.current_token
+               var do_inline = true
+               loop
+                       if token isa TEol then
+                               v.skip
+                               if not v.can_inline(n_block) then
+                                       v.forcen
+                                       v.addt
+                                       do_inline = false
+                               end
+                       end
+                       token = v.current_token
+                       if token isa TKwdo then break
+               end
+               if annot_inline and do_inline then v.adds
+               v.consume "do"
+
+               if v.can_inline(n_block) and do_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
+                       if was_inline then
+                               v.forcen
+                       else
+                               v.addn
+                       end
+                       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.forcen
+                       end
+
+                       v.indent -= 1
+                       v.addt
+                       if n_block isa ABlockExpr then
+                               v.visit n_block.n_kwend
+                       else
+                               v.add "end"
+                       end
+               end
+               v.finish_line
+       end
+
        redef fun start_token do
                if n_doc == null then return super
                return n_doc.last_token.next_token
@@ -798,7 +924,8 @@ redef class AAttrPropdef
                        v.visit n_expr
                end
 
-               if n_annotations != null then v.visit n_annotations
+               var annot_inline = visit_annotations(v, n_annotations)
+               visit_block(v, n_block, annot_inline)
                v.finish_line
                v.addn
        end
@@ -822,6 +949,7 @@ redef class ATypePropdef
                v.consume ":"
                v.adds
                v.visit n_type
+               visit_annotations(v, n_annotations)
                v.finish_line
                v.addn
        end
@@ -834,7 +962,6 @@ redef class AMethPropdef
                #  TODO: Handle extern annotations
 
                var before = v.indent
-               var can_inline = v.can_inline(self)
                super
                if n_kwinit != null then v.visit n_kwinit
                if n_kwmeth != null then v.visit n_kwmeth
@@ -847,72 +974,15 @@ redef class AMethPropdef
 
                v.visit n_signature
 
-               if n_annotations != null then
-                       v.visit n_annotations
-               else
-                       v.adds
-               end
+               var annot_inline = visit_annotations(v, n_annotations)
 
                if n_extern_calls != null or n_extern_code_block != null then
-                       if n_annotations != null then v.adds
+                       v.adds
                        if n_extern_calls != null then v.visit n_extern_calls
                        if n_extern_code_block != null then v.visit n_extern_code_block
                end
 
-               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
-               v.finish_line
-               end
-
+               visit_block(v, n_block, annot_inline)
                v.addn
                assert v.indent == before
        end
@@ -934,8 +1004,22 @@ end
 redef class AMainMethPropdef
        redef fun accept_pretty_printer(v) do
                v.visit n_block
+               if v.skip_empty then v.addn
+       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
@@ -979,9 +1063,10 @@ redef class AExternCalls
                        v.adds
                        v.visit_list n_extern_calls
                else
-                       v.addn
-                       v.addt
+                       v.forcen
+                       v.indent += 1
                        v.addt
+                       v.indent -= 1
                        v.visit_list n_extern_calls
                end
 
@@ -1078,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
@@ -1087,7 +1172,7 @@ redef class TExternCodeSegment
 
                                for line in lines do
                                        v.add line.r_trim
-                                       v.addn
+                                       v.forcen
                                end
 
                                v.addt
@@ -1155,7 +1240,7 @@ redef class AIfExpr
                        v.adds
                else
                        v.visit n_expr
-                       v.addn
+                       v.forcen
                        v.addt
                end
 
@@ -1177,11 +1262,18 @@ redef class AIfExpr
                        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
+                       if was_inline then
+                               v.forcen
+                       else if not v.skip_empty and n_then != null and
+                               n_then.was_inline and
+                               n_then.location.line_end == location.line_start then
+                               v.forcen # Xymus fucking syntax
+                       else
+                               v.addn
+                       end
                        v.indent += 1
 
                        if n_then != null then
@@ -1191,14 +1283,19 @@ redef class AIfExpr
                                else
                                        v.addt
                                        v.visit n_then
-                                       v.addn
+                                       if n_then.was_inline then
+                                               v.forcen
+                                       else
+                                               v.addn
+                                       end
                                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
@@ -1210,7 +1307,11 @@ redef class AIfExpr
                                        v.visit n_else
                                else
                                        v.finish_line
-                                       v.addn
+                                       if was_inline then
+                                               v.forcen
+                                       else
+                                               v.addn
+                                       end
                                        v.indent += 1
 
                                        if n_else isa ABlockExpr then
@@ -1219,7 +1320,11 @@ redef class AIfExpr
                                        else
                                                v.addt
                                                v.visit n_else
-                                               v.addn
+                                               if n_else.was_inline then
+                                                       v.forcen
+                                               else
+                                                       v.addn
+                                               end
                                        end
 
                                        if last_token isa TKwend then
@@ -1477,8 +1582,7 @@ redef class ACallExpr
                v.visit_recv n_expr
 
                if not n_expr isa AImplicitSelfExpr and not can_inline then
-                       v.addn
-                       v.addt
+                       v.forcen
                        v.addt
                end
 
@@ -1491,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
@@ -1619,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
 
@@ -1639,19 +1731,16 @@ redef class ANewExpr
                        v.consume "."
 
                        if not can_inline then
-                               v.addn
-                               v.addt
+                               v.forcen
+                               v.indent += 1
                                v.addt
+                               v.indent -= 1
                        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
+               v.visit_args n_args.n_exprs
        end
 
        redef fun is_inlinable do return true
@@ -1749,19 +1838,18 @@ redef class AAssertExpr
                                v.visit n_else
                        else
                                v.addn
+                               v.indent += 1
 
                                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.forcen
                                        v.indent -= 1
                                        v.addt
                                        v.add "end"
@@ -1799,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
@@ -1896,9 +1977,10 @@ private class ABinOpHelper
                        v.adds
                        v.visit bin_expr2
                else
-                       v.addn
-                       v.addt
+                       v.forcen
+                       v.indent += 1
                        v.addt
+                       v.indent -= 1
                        v.visit bin_expr2
                end
        end
@@ -1933,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
@@ -2021,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
@@ -2045,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
@@ -2073,9 +2101,13 @@ end
 
 redef class AStringFormExpr
        redef fun accept_pretty_printer(v) do
-               var can_inline = v.can_inline(self)
-
-               if can_inline then
+               if not v.break_strings then
+                       # n_string.force_inline = true
+                       v.visit n_string
+                       return
+               end
+               if v.can_inline(self) then
+                       n_string.force_inline = true
                        v.visit n_string
                else
                        var text = n_string.text
@@ -2084,9 +2116,13 @@ 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 "\" +"
-                                       v.addn
+                                       if was_inline then
+                                               v.forcen
+                                       else
+                                               v.addn
+                                       end
                                        v.indent += 1
                                        v.addt
                                        v.indent -= 1
@@ -2103,7 +2139,12 @@ end
 
 redef class ASuperstringExpr
        redef fun accept_pretty_printer(v) do
-               for n_expr in n_exprs do v.visit n_expr
+               for n_expr in n_exprs do
+                       if not v.break_strings then
+                               n_expr.force_inline = true
+                       end
+                       v.visit n_expr
+               end
        end
 
        redef fun must_be_inline do