From 6bbad4f14219993811310efebbb828321953217d Mon Sep 17 00:00:00 2001 From: Moritz Eysholdt Date: Sun, 25 Sep 2016 21:24:01 +0200 Subject: [PATCH] fixed #14: [formatter2] honor FormatterRequest.allowIdentityEdits Signed-off-by: Moritz Eysholdt --- .../internal/FormatterReplacementsTest.xtend | 53 ++++++++ .../internal/FormatterReplacementsTest.java | 115 ++++++++++++++++++ .../internal/TextReplacerContext.java | 15 ++- 3 files changed, 180 insertions(+), 3 deletions(-) create mode 100644 org.eclipse.xtext.tests/src/org/eclipse/xtext/formatting2/internal/FormatterReplacementsTest.xtend create mode 100644 org.eclipse.xtext.tests/xtend-gen/org/eclipse/xtext/formatting2/internal/FormatterReplacementsTest.java diff --git a/org.eclipse.xtext.tests/src/org/eclipse/xtext/formatting2/internal/FormatterReplacementsTest.xtend b/org.eclipse.xtext.tests/src/org/eclipse/xtext/formatting2/internal/FormatterReplacementsTest.xtend new file mode 100644 index 000000000..8f7efbcc2 --- /dev/null +++ b/org.eclipse.xtext.tests/src/org/eclipse/xtext/formatting2/internal/FormatterReplacementsTest.xtend @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.xtext.formatting2.internal + +import com.google.inject.Inject +import com.google.inject.Provider +import org.eclipse.xtext.formatting2.FormatterRequest +import org.eclipse.xtext.formatting2.internal.formattertestlanguage.IDList +import org.eclipse.xtext.formatting2.internal.services.FormatterTestLanguageGrammarAccess +import org.eclipse.xtext.formatting2.internal.tests.FormatterTestLanguageInjectorProvider +import org.eclipse.xtext.formatting2.regionaccess.TextRegionAccessBuilder +import org.eclipse.xtext.resource.XtextResource +import org.eclipse.xtext.testing.InjectWith +import org.eclipse.xtext.testing.XtextRunner +import org.eclipse.xtext.testing.util.ParseHelper +import org.junit.Assert +import org.junit.Test +import org.junit.runner.RunWith + +/** + * @author Moritz Eysholdt - Initial contribution and API + */ +@RunWith(XtextRunner) +@InjectWith(FormatterTestLanguageInjectorProvider) +class FormatterReplacementsTest { + + @Inject Provider requestProvider + @Inject TextRegionAccessBuilder regionBuilder + @Inject ParseHelper parseHelper + @Inject extension FormatterTestLanguageGrammarAccess + + @Test def testIdentityEditsAreFiltered() { + val GenericFormatter formatter = [ IDList model, extension regions, extension document | + model.regionFor.ruleCallsTo(IDRule).forEach[prepend[autowrap; oneSpace]] + ] + val parsed = parseHelper.parse("idlist aaa bbb") + val request = requestProvider.get() + request.allowIdentityEdits = false + request.textRegionAccess = regionBuilder.forNodeModel(parsed.eResource as XtextResource).create + + val replacements = formatter.format(request) + val actual = replacements.map['''"«text»" -> "«replacementText»"«"\n"»'''].join + val expected = ''' + " " -> " " + ''' + Assert.assertEquals(expected, actual) + } +} diff --git a/org.eclipse.xtext.tests/xtend-gen/org/eclipse/xtext/formatting2/internal/FormatterReplacementsTest.java b/org.eclipse.xtext.tests/xtend-gen/org/eclipse/xtext/formatting2/internal/FormatterReplacementsTest.java new file mode 100644 index 000000000..aa0d8de2b --- /dev/null +++ b/org.eclipse.xtext.tests/xtend-gen/org/eclipse/xtext/formatting2/internal/FormatterReplacementsTest.java @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.xtext.formatting2.internal; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import java.util.List; +import java.util.function.Consumer; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.xtend2.lib.StringConcatenation; +import org.eclipse.xtext.TerminalRule; +import org.eclipse.xtext.formatting2.FormatterRequest; +import org.eclipse.xtext.formatting2.IFormattableDocument; +import org.eclipse.xtext.formatting2.IHiddenRegionFormatter; +import org.eclipse.xtext.formatting2.internal.GenericFormatter; +import org.eclipse.xtext.formatting2.internal.formattertestlanguage.IDList; +import org.eclipse.xtext.formatting2.internal.services.FormatterTestLanguageGrammarAccess; +import org.eclipse.xtext.formatting2.internal.tests.FormatterTestLanguageInjectorProvider; +import org.eclipse.xtext.formatting2.regionaccess.ISemanticRegion; +import org.eclipse.xtext.formatting2.regionaccess.ISemanticRegionsFinder; +import org.eclipse.xtext.formatting2.regionaccess.ITextRegionAccess; +import org.eclipse.xtext.formatting2.regionaccess.ITextRegionExtensions; +import org.eclipse.xtext.formatting2.regionaccess.ITextReplacement; +import org.eclipse.xtext.formatting2.regionaccess.TextRegionAccessBuilder; +import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.testing.InjectWith; +import org.eclipse.xtext.testing.XtextRunner; +import org.eclipse.xtext.testing.util.ParseHelper; +import org.eclipse.xtext.xbase.lib.Exceptions; +import org.eclipse.xtext.xbase.lib.Extension; +import org.eclipse.xtext.xbase.lib.Functions.Function1; +import org.eclipse.xtext.xbase.lib.IterableExtensions; +import org.eclipse.xtext.xbase.lib.ListExtensions; +import org.eclipse.xtext.xbase.lib.Procedures.Procedure1; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * @author Moritz Eysholdt - Initial contribution and API + */ +@RunWith(XtextRunner.class) +@InjectWith(FormatterTestLanguageInjectorProvider.class) +@SuppressWarnings("all") +public class FormatterReplacementsTest { + @Inject + private Provider requestProvider; + + @Inject + private TextRegionAccessBuilder regionBuilder; + + @Inject + private ParseHelper parseHelper; + + @Inject + @Extension + private FormatterTestLanguageGrammarAccess _formatterTestLanguageGrammarAccess; + + @Test + public void testIdentityEditsAreFiltered() { + try { + final GenericFormatter _function = new GenericFormatter() { + @Override + protected void format(final IDList model, @Extension final ITextRegionExtensions regions, @Extension final IFormattableDocument document) { + ISemanticRegionsFinder _regionFor = regions.regionFor(model); + TerminalRule _iDRule = FormatterReplacementsTest.this._formatterTestLanguageGrammarAccess.getIDRule(); + List _ruleCallsTo = _regionFor.ruleCallsTo(_iDRule); + final Consumer _function = (ISemanticRegion it) -> { + final Procedure1 _function_1 = (IHiddenRegionFormatter it_1) -> { + it_1.autowrap(); + it_1.oneSpace(); + }; + document.prepend(it, _function_1); + }; + _ruleCallsTo.forEach(_function); + } + }; + final GenericFormatter formatter = _function; + final IDList parsed = this.parseHelper.parse("idlist aaa bbb"); + final FormatterRequest request = this.requestProvider.get(); + request.setAllowIdentityEdits(false); + Resource _eResource = parsed.eResource(); + TextRegionAccessBuilder _forNodeModel = this.regionBuilder.forNodeModel(((XtextResource) _eResource)); + ITextRegionAccess _create = _forNodeModel.create(); + request.setTextRegionAccess(_create); + final List replacements = formatter.format(request); + final Function1 _function_1 = (ITextReplacement it) -> { + StringConcatenation _builder = new StringConcatenation(); + _builder.append("\""); + String _text = it.getText(); + _builder.append(_text, ""); + _builder.append("\" -> \""); + String _replacementText = it.getReplacementText(); + _builder.append(_replacementText, ""); + _builder.append("\""); + _builder.append("\n", ""); + return _builder.toString(); + }; + List _map = ListExtensions.map(replacements, _function_1); + final String actual = IterableExtensions.join(_map); + StringConcatenation _builder = new StringConcatenation(); + _builder.append("\" \" -> \" \""); + _builder.newLine(); + final String expected = _builder.toString(); + Assert.assertEquals(expected, actual); + } catch (Throwable _e) { + throw Exceptions.sneakyThrow(_e); + } + } +} diff --git a/org.eclipse.xtext/src/org/eclipse/xtext/formatting2/internal/TextReplacerContext.java b/org.eclipse.xtext/src/org/eclipse/xtext/formatting2/internal/TextReplacerContext.java index f28ccdc26..612e253e8 100644 --- a/org.eclipse.xtext/src/org/eclipse/xtext/formatting2/internal/TextReplacerContext.java +++ b/org.eclipse.xtext/src/org/eclipse/xtext/formatting2/internal/TextReplacerContext.java @@ -8,6 +8,7 @@ import java.util.List; import org.eclipse.xtext.formatting2.AbstractFormatter2; import org.eclipse.xtext.formatting2.FormatterPreferenceKeys; +import org.eclipse.xtext.formatting2.FormatterRequest; import org.eclipse.xtext.formatting2.IFormattableDocument; import org.eclipse.xtext.formatting2.ITextReplacer; import org.eclipse.xtext.formatting2.ITextReplacerContext; @@ -217,6 +218,7 @@ public class TextReplacerContext implements ITextReplacerContext { public void addReplacement(ITextReplacement replacement) { Preconditions.checkNotNull(replacer); ITextSegment replacerRegion = replacer.getRegion(); + FormatterRequest request = document.getRequest(); if (!replacerRegion.contains(replacement)) { String frameTitle = replacer.getClass().getSimpleName(); ITextSegment frameRegion = replacer.getRegion(); @@ -224,13 +226,16 @@ public class TextReplacerContext implements ITextReplacerContext { @SuppressWarnings("unchecked") RegionsOutsideFrameException exception = new RegionsOutsideFrameException(frameTitle, frameRegion, Tuples.create(replacerTitle, (ITextSegment) replacement)); - document.getRequest().getExceptionHandler().accept(exception); + request.getExceptionHandler().accept(exception); return; } if (!isInRequestedRange(replacement)) { return; } - if (document.getRequest().isFormatUndefinedHiddenRegionsOnly()) { + if (!request.allowIdentityEdits() && isIdentityEdit(replacement)) { + return; + } + if (request.isFormatUndefinedHiddenRegionsOnly()) { IHiddenRegion hidden = null; if (replacerRegion instanceof IHiddenRegionPart) hidden = ((IHiddenRegionPart) replacerRegion).getHiddenRegion(); @@ -242,10 +247,14 @@ public class TextReplacerContext implements ITextReplacerContext { try { replacements.add(replacement); } catch (ConflictingRegionsException e) { - document.getRequest().getExceptionHandler().accept(e); + request.getExceptionHandler().accept(e); } } + protected boolean isIdentityEdit(ITextReplacement replacement) { + return replacement.getText().equals(replacement.getReplacementText()); + } + @Override public void setAutowrap(boolean value) { this.autowrap = value;