Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 345281

Summary: Indent auto-wrapped lines
Product: [Modeling] TMF Reporter: Mary Komor <mkomor>
Component: XtextAssignee: Project Inbox <tmf.xtext-inbox>
Status: CLOSED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: chanskw, moritz.eysholdt, sebastian.zarnekow, sven.efftinge
Version: unspecifiedFlags: sven.efftinge: indigo+
sebastian.zarnekow: review+
Target Milestone: RC3   
Hardware: All   
OS: Linux   
Whiteboard:
Attachments:
Description Flags
Patch to support indentation of wrapped lines in the formatter
sven.efftinge: iplog+
Patch to update test suite to use indentation of wrapped lines in the formatter sven.efftinge: iplog+

Description Mary Komor CLA 2011-05-10 11:08:19 EDT
Build Identifier: 

The formatter can be configured to wrap lines, but the wrapped lines are flushed with the previous line which makes the code hard to read after formatting. The wrapped lines need to be indented. 

Essentially, FormattingConfigBasedStream.Line.flushLine() needs to take a boolean to indicate whether the line is being flushed because of a wrap. If true, then increment the indent for the LineEntry at the "lastBreakableEntryIndex". I can provide a patch.

Reproducible: Always
Comment 1 Mary Komor CLA 2011-05-10 18:33:54 EDT
If I provide the patch, can the fix be made available in v2.0?
Comment 2 Sebastian Zarnekow CLA 2011-05-11 00:46:23 EDT
That depends on the patch. It may not break existing APIs and we have to make sure that it does not change any behavior unintentionally. In order to be able to review it in time, a patch is welcome as soon as possible.

Disclaimer: This is not a promise that we'll have the time to review a patch before 2.0
Comment 3 Mary Komor CLA 2011-05-12 02:11:53 EDT
Created attachment 195459 [details]
Patch to support indentation of wrapped lines in the formatter

The attached patch contains the following: 
1. FormattingConfig -- added a new field (wrappedLineIndentation) to hold the value for the number of tabs (or equivalent) that wrapped lines should be indented
2. FormattingConfigBasedStream -- when a line is wrapped, increment the indent of the LineEntry that is at the lastBreakableEntryIndex. Query the FormattingConfig for the number of indent level to add.
Comment 4 Sebastian Zarnekow CLA 2011-05-16 09:15:09 EDT
Hi Mary,

thanks for the patch. Would it be possible for you to provide some unit tests, too?
Comment 5 Mary Komor CLA 2011-05-17 01:32:44 EDT
Are there any existing unit tests for the formatter that I can add to?
Comment 6 Sebastian Zarnekow CLA 2011-05-17 01:35:32 EDT
You may want to have a look at org.eclipse.xtext.parsetree.formatter.FormatterTest
Comment 7 Mary Komor CLA 2011-05-17 18:28:21 EDT
(In reply to comment #6)
> You may want to have a look at
> org.eclipse.xtext.parsetree.formatter.FormatterTest

Are the test packages kept up to date? I checked them out from the GIT repository, but they fail to build.
Comment 8 Mary Komor CLA 2011-05-19 02:15:04 EDT
I have updated and tested using org.eclipse.xtext.parsetree.formatter. Should I provide a patch for the updated test cases?
Comment 9 Sebastian Zarnekow CLA 2011-05-19 02:32:02 EDT
(In reply to comment #8)
> I have updated and tested using org.eclipse.xtext.parsetree.formatter. Should I
> provide a patch for the updated test cases?

That would be great.
Comment 10 Mary Komor CLA 2011-05-19 19:46:17 EDT
Created attachment 196174 [details]
Patch to update test suite to use indentation of wrapped lines in the formatter

The attached patch has the following updates

1. org.eclipse.xtext.parsetree.formatter.FormatterTestConfig -- set indentation for wrapped lines to 1 tab (or equivalent) in the FormattingConfig

2. org.eclipse.xtext.parsetree.formatter.FormatterTest -- updated the following to include the indentation (tab) in the expected value:
    o testIndentationAndLineWrap
    o testLinewrapDatatypeRuleComments
    o testSuppressedLinewrap
Comment 11 Moritz Eysholdt CLA 2011-05-20 04:57:24 EDT
Hi Mary,

thx for your contribution. However, I don't quite understand how it improves the indentation-mechanism over what we already have:

Let's say there is a rule like:

---
Rule: 'foo' val+=ID 'bar';
---

and you configure

---
cfg.SetAutoLineWrap(20);
cfg.setIndentationStart().after(grammar.getFooKeyword); 
cfg.setIndentationEnd().after(grammar.getBarKeyword); 
---

then this indentation will only be applied if auto-linewrap kicks in.

e.g. 

"foo a b c d bar" will become "foo a b c d bar"

and 

"foo a b c d e f g h i j k l m n o p bar" will become

---
foo a b c d e f g h 
    i j k l m n o p 
    bar
---

Please refer to FormatterTest.testIndentationAndLineWrap() as an example.

doesn't this solve your use-case?

regards,
  Moritz
Comment 12 Mary Komor CLA 2011-05-25 01:11:14 EDT
(In reply to comment #11)
Hi Moritz,

I'm looking specifically for a way to indent lines that are wrapped because it has exceeded max line width (auto-linewrap) setting. From what I understand of FormattingConfig.setIndentation(AbstractElement, AbstractElement), it indents all new/wrapped lines between the beginElement and endElement, regardless of whether the line was wrapped because of a setLineBreak on a keyword or because the line exceeded the max line width (auto-linewrap). Is my understanding correct? If so, then I'm looking for something that has more granular control. I want to specify additional indentation for lines that get wrapped because the max line width has been exceeded. 

So, using a variation of your example in comment #11,

---
Rule: 'foo' val+=ID 'c' val2+=ID 'bar';
---

and I configure

---
cfg.SetAutoLineWrap(20);
cfg.setLineWrap.after(grammar.getCKeyword);
cfg.setIndentation(grammar.getFooKeyword, grammar.getBarKeyword); 
---

then indentation will be applied when auto-linewrap kicks in as well as when the "c" keyword is encountered

e.g. 

"foo a b c d bar" will become 

---
foo a b c 
    d bar
---

and 

"foo a b c d e f g h i j k l m n o p bar" will become

---
foo a b c 
    d e f g h i j k     <-- line wrapped & indented because of setIndentation
    l m n o p bar       <-- line wrapped & indented because of 
                            auto-linewrap,  but the wrapped line is flushed
                            with previous (parent)line
---

What I want is

---
foo a b c 
    d e f g h i j k      <-- line wrapped & indented because of setIndentation
        l m n o p bar    <-- line wrapped & indented further because this line
                             was wrapped when auto-linewrap(max line width) 
                             was exceeded
---


Here's a Java example:

---
cfg.SetAutoLineWrap(40);
cfg.setLineWrap.after(grammar.getSemi);
cfg.setLineWrap.after(grammar.getLeftCurly);
cfg.setIndentation(grammar.getLeftCurly, grammar.getRightCurly); 
---

e.g. 

---
public void myMethod(String param1, String param2) {
    System.out.println("Prints line number one");
    System.out.println("Prints line number two");
}
---

will become

---
public void myMethod(String param1, 
String param2) {                        
    System.out.println("Prints line     
    number one");                       
    System.out.println("Prints line     
    number two");                       
}
---

but I want

---
public void myMethod(String param1, 
    String param2) {
    System.out.println("Prints line 
        number one");
    System.out.println("Prints line 
        number two");
}
---

I hope I made some sense... 

Regards,

Mary
Comment 13 Mary Komor CLA 2011-05-26 19:36:03 EDT
Just wondering where we are with this. Did my previous comment clarify things. I hope I did not end up confusing you even more. 

Mary
Comment 14 Sebastian Zarnekow CLA 2011-05-27 17:38:15 EDT
Hi Mary,

thanks for the clarification. We'll review your patch carefully but I cannot promise that it'll make it into the 2.0 release since we are already late in the end-game for Indigo.

Regards,
Sebastian
Comment 15 Sebastian Zarnekow CLA 2011-05-27 17:38:54 EDT
Preliminary scheduled for RC3 to make sure it'll be reviewed.
Comment 16 Sebastian Zarnekow CLA 2011-05-30 03:20:11 EDT
The patches look good to me. I'd apply them for RC3. What do others think?
Comment 17 Moritz Eysholdt CLA 2011-05-30 04:58:52 EDT
(In reply to comment #12)

> What I want is
> 
> ---
> foo a b c 
>     d e f g h i j k      <-- line wrapped & indented because of setIndentation
>         l m n o p bar    <-- line wrapped & indented further because this line
>                              was wrapped when auto-linewrap(max line width) 
>                              was exceeded
> ---


hi Mary,

you can get this formatting with this configuration:

---
cfg.SetAutoLineWrap(20);
cfg.setLineWrap.after(grammar.getCKeyword);
cfg.setIndentation(grammar.getCKeyword, grammar.getBarKeyword); 
cfg.setIndentation(grammar.getFooKeyword, grammar.getBarKeyword); 
---

why isn't that sufficient?

The same is true for your java example:

---
cfg.SetAutoLineWrap(40);
cfg.setLineWrap.after(grammar.getSemi);
cfg.setLineWrap.after(grammar.getLeftCurly);
cfg.setIndentation(grammar.getLeftCurly, grammar.getRightCurly); 
cfg.setIndentation(grammar.getLeftParenthesis, grammar.getRightParenthesis); 
---

all you need to do is define indentation between the parenthesis that surround the println's parameters. 

You are saying that one needs to distinguish between indentation applied to explicitly-wrapped lines and indentation applied to auto-wrapped lines. The use cases you've provided don't show why this should be necessary.
Comment 18 Moritz Eysholdt CLA 2011-05-30 05:00:57 EDT
(In reply to comment #17)
> ---
> cfg.SetAutoLineWrap(20);
> cfg.setLineWrap.after(grammar.getCKeyword);
> cfg.setIndentation(grammar.getCKeyword, grammar.getBarKeyword); 
> cfg.setIndentation(grammar.getFooKeyword, grammar.getBarKeyword); 
> ---

my bad, this is supposed to be 

---
cfg.SetAutoLineWrap(20);
cfg.setLineWrap.after(grammar.getCKeyword);
cfg.setIndentation(grammar.getDKeyword, grammar.getBarKeyword); 
cfg.setIndentation(grammar.getFooKeyword, grammar.getBarKeyword); 
---

it needs to be 'DKeyword', otherwise 'c' gets indented twice.
Comment 19 Mary Komor CLA 2011-05-30 16:07:05 EDT
Hi Moritz,

Thanks for your consideration. Yes, I can probably explicitly set indentation in all the appropriate places, but I would end up painstakingly setting the indentation for just about every rule in my grammar! I am asking for a more generic way to indent lines that are wrapped because the line has exceeded the max line width (i.e. "auto-wrapped"). For the simple examples that we have been using in this defect, it is easy to do and looks trivial. Once you take a real-world (i.e. complex) grammar file, it starts to get really tedious (assuming that it *is* possible) if you have to explicitly set the indentation for everything. Once the rule definition starts to get complex, it gets harder to easily set the indentation between two keywords. 

Mary
Comment 20 Moritz Eysholdt CLA 2011-05-31 13:01:21 EDT
(In reply to comment #19)
> (...) I am asking for a more
> generic way to indent lines that are wrapped because the line has exceeded the
> max line width (i.e. "auto-wrapped"). (...)

I agree that such scenarios do exist and that a generic way to specify indentation does simplify them. I've applied your patch, thx for it.

This is in time for RC3.
Comment 21 Moritz Eysholdt CLA 2011-05-31 13:01:50 EDT
pushed to master.
Comment 22 Mary Komor CLA 2011-06-02 16:27:54 EDT
(In reply to comment #21)
> pushed to master.

Awesome! Thanks!
Comment 23 Karsten Thoms CLA 2017-09-19 17:00:08 EDT
Closing all bugs that were set to RESOLVED before Neon.0
Comment 24 Karsten Thoms CLA 2017-09-19 17:11:34 EDT
Closing all bugs that were set to RESOLVED before Neon.0