From 0b74443d41d455475ceaa3a073a7f51f4c293b12 Mon Sep 17 00:00:00 2001 From: Thomas Kutz Date: Fri, 29 Sep 2017 13:40:36 +0200 Subject: [PATCH] [#483] Append trailing whitespaces and newlines after appending separator in for-loops Signed-off-by: Thomas Kutz --- .../trace/node/TemplateNodeTest.xtend | 29 +++++++ .../trace/node/TemplateNodeTest.java | 76 +++++++++++++++++++ .../generator/trace/node/TemplateNode.xtend | 14 +++- .../generator/trace/node/TemplateNode.java | 24 ++++-- 4 files changed, 134 insertions(+), 9 deletions(-) diff --git a/org.eclipse.xtext.tests/src/org/eclipse/xtext/generator/trace/node/TemplateNodeTest.xtend b/org.eclipse.xtext.tests/src/org/eclipse/xtext/generator/trace/node/TemplateNodeTest.xtend index 3b6f0c50c..8f1ef3426 100644 --- a/org.eclipse.xtext.tests/src/org/eclipse/xtext/generator/trace/node/TemplateNodeTest.xtend +++ b/org.eclipse.xtext.tests/src/org/eclipse/xtext/generator/trace/node/TemplateNodeTest.xtend @@ -77,6 +77,33 @@ class TemplateNodeTest { ''') } + @Test def void testSeparatorLoopWithWhitespace() { + val strings = #['a', 'b', 'c'] + assertEquals(''' + «FOR s : strings SEPARATOR ', '»«s» «s»«ENDFOR» + ''') + } + + @Test def void testSeparatorLoopWithWhitespace2() { + val strings = #['a', 'b', 'c'] + assertEquals(''' + «FOR s : strings SEPARATOR ','» + «s» «s» + «ENDFOR» + ''') + } + + @Test def void testSeparatorLoopWithWhitespace3() { + val strings = #['a', 'b', 'c'] + assertEquals(''' + «FOR s : strings SEPARATOR ','» + + «s» + + «ENDFOR» + ''') + } + @Test def void testIndentedIf() { val condition = true val string = 'foo' @@ -96,6 +123,8 @@ class TemplateNodeTest { ''') } + + @Test def void testIndentedTemplate() { val StringConcatenationClient template = ''' sometimes foo diff --git a/org.eclipse.xtext.tests/xtend-gen/org/eclipse/xtext/generator/trace/node/TemplateNodeTest.java b/org.eclipse.xtext.tests/xtend-gen/org/eclipse/xtext/generator/trace/node/TemplateNodeTest.java index 6d12ec3fb..1a0095e12 100644 --- a/org.eclipse.xtext.tests/xtend-gen/org/eclipse/xtext/generator/trace/node/TemplateNodeTest.java +++ b/org.eclipse.xtext.tests/xtend-gen/org/eclipse/xtext/generator/trace/node/TemplateNodeTest.java @@ -172,6 +172,82 @@ public class TemplateNodeTest { this.assertEquals(_client); } + @Test + public void testSeparatorLoopWithWhitespace() { + final List strings = Collections.unmodifiableList(CollectionLiterals.newArrayList("a", "b", "c")); + StringConcatenationClient _client = new StringConcatenationClient() { + @Override + protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) { + { + boolean _hasElements = false; + for(final String s : strings) { + if (!_hasElements) { + _hasElements = true; + } else { + _builder.appendImmediate(", ", ""); + } + _builder.append(s); + _builder.append(" "); + _builder.append(s); + } + } + _builder.newLineIfNotEmpty(); + } + }; + this.assertEquals(_client); + } + + @Test + public void testSeparatorLoopWithWhitespace2() { + final List strings = Collections.unmodifiableList(CollectionLiterals.newArrayList("a", "b", "c")); + StringConcatenationClient _client = new StringConcatenationClient() { + @Override + protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) { + { + boolean _hasElements = false; + for(final String s : strings) { + if (!_hasElements) { + _hasElements = true; + } else { + _builder.appendImmediate(",", ""); + } + _builder.append(s); + _builder.append(" "); + _builder.append(s); + _builder.newLineIfNotEmpty(); + } + } + } + }; + this.assertEquals(_client); + } + + @Test + public void testSeparatorLoopWithWhitespace3() { + final List strings = Collections.unmodifiableList(CollectionLiterals.newArrayList("a", "b", "c")); + StringConcatenationClient _client = new StringConcatenationClient() { + @Override + protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) { + { + boolean _hasElements = false; + for(final String s : strings) { + if (!_hasElements) { + _hasElements = true; + } else { + _builder.appendImmediate(",", ""); + } + _builder.newLine(); + _builder.append(s); + _builder.append(" "); + _builder.newLineIfNotEmpty(); + _builder.newLine(); + } + } + } + }; + this.assertEquals(_client); + } + @Test public void testIndentedIf() { final boolean condition = true; diff --git a/org.eclipse.xtext/src/org/eclipse/xtext/generator/trace/node/TemplateNode.xtend b/org.eclipse.xtext/src/org/eclipse/xtext/generator/trace/node/TemplateNode.xtend index 607e378aa..e92150464 100644 --- a/org.eclipse.xtext/src/org/eclipse/xtext/generator/trace/node/TemplateNode.xtend +++ b/org.eclipse.xtext/src/org/eclipse/xtext/generator/trace/node/TemplateNode.xtend @@ -12,6 +12,7 @@ import com.google.common.collect.Iterables import java.util.regex.Pattern import org.eclipse.xtend2.lib.StringConcatenationClient import org.eclipse.xtend2.lib.StringConcatenationClient.TargetStringConcatenation +import com.google.common.collect.Lists /** * A template node applies a {@link StringConcatenationClient} to compute its children. @@ -85,12 +86,17 @@ class TemplateNode extends CompositeGeneratorNode implements TargetStringConcate } override appendImmediate(Object object, String indentation) { + val removed = Lists.newArrayList for (var i = currentParent.children.size - 1; i >= 0; i--) { val node = currentParent.children.get(i) - if (node instanceof TextNode) { - if (!node.text.hasContent) { - currentParent.children.remove(i) - } + if (node instanceof TextNode && !(node as TextNode).text.hasContent) { + removed += currentParent.children.remove(i) + } else if (node instanceof NewLineNode) { + removed += currentParent.children.remove(i) + } else { + append(object, indentation) + removed.reverse.forEach[append(it, indentation)] + return } } append(object, indentation) diff --git a/org.eclipse.xtext/xtend-gen/org/eclipse/xtext/generator/trace/node/TemplateNode.java b/org.eclipse.xtext/xtend-gen/org/eclipse/xtext/generator/trace/node/TemplateNode.java index e4b6ae3a9..c1fd9cd8e 100644 --- a/org.eclipse.xtext/xtend-gen/org/eclipse/xtext/generator/trace/node/TemplateNode.java +++ b/org.eclipse.xtext/xtend-gen/org/eclipse/xtext/generator/trace/node/TemplateNode.java @@ -9,15 +9,19 @@ package org.eclipse.xtext.generator.trace.node; import com.google.common.base.Splitter; import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.function.Consumer; import java.util.regex.Pattern; import org.eclipse.xtend2.lib.StringConcatenationClient; import org.eclipse.xtext.generator.trace.node.CompositeGeneratorNode; import org.eclipse.xtext.generator.trace.node.GeneratorNodeExtensions; import org.eclipse.xtext.generator.trace.node.IGeneratorNode; import org.eclipse.xtext.generator.trace.node.IndentNode; +import org.eclipse.xtext.generator.trace.node.NewLineNode; import org.eclipse.xtext.generator.trace.node.TextNode; import org.eclipse.xtext.xbase.lib.CollectionLiterals; import org.eclipse.xtext.xbase.lib.Functions.Function1; @@ -126,14 +130,24 @@ public class TemplateNode extends CompositeGeneratorNode implements StringConcat @Override public void appendImmediate(final Object object, final String indentation) { + final ArrayList removed = Lists.newArrayList(); for (int i = (this.currentParent.getChildren().size() - 1); (i >= 0); i--) { { final IGeneratorNode node = this.currentParent.getChildren().get(i); - if ((node instanceof TextNode)) { - boolean _hasContent = TemplateNode.hasContent(((TextNode)node).getText()); - boolean _not = (!_hasContent); - if (_not) { - this.currentParent.getChildren().remove(i); + if (((node instanceof TextNode) && (!TemplateNode.hasContent(((TextNode) node).getText())))) { + IGeneratorNode _remove = this.currentParent.getChildren().remove(i); + removed.add(_remove); + } else { + if ((node instanceof NewLineNode)) { + IGeneratorNode _remove_1 = this.currentParent.getChildren().remove(i); + removed.add(_remove_1); + } else { + this.append(object, indentation); + final Consumer _function = (IGeneratorNode it) -> { + this.append(it, indentation); + }; + ListExtensions.reverse(removed).forEach(_function); + return; } } }