fixed #14: [formatter2] honor FormatterRequest.allowIdentityEdits

Signed-off-by: Moritz Eysholdt <moritz.eysholdt@typefox.io>
This commit is contained in:
Moritz Eysholdt 2016-09-25 21:24:01 +02:00
parent 7f6980e578
commit 6bbad4f142
3 changed files with 180 additions and 3 deletions

View file

@ -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<FormatterRequest> requestProvider
@Inject TextRegionAccessBuilder regionBuilder
@Inject ParseHelper<IDList> parseHelper
@Inject extension FormatterTestLanguageGrammarAccess
@Test def testIdentityEditsAreFiltered() {
val GenericFormatter<IDList> 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)
}
}

View file

@ -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<FormatterRequest> requestProvider;
@Inject
private TextRegionAccessBuilder regionBuilder;
@Inject
private ParseHelper<IDList> parseHelper;
@Inject
@Extension
private FormatterTestLanguageGrammarAccess _formatterTestLanguageGrammarAccess;
@Test
public void testIdentityEditsAreFiltered() {
try {
final GenericFormatter<IDList> _function = new GenericFormatter<IDList>() {
@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<ISemanticRegion> _ruleCallsTo = _regionFor.ruleCallsTo(_iDRule);
final Consumer<ISemanticRegion> _function = (ISemanticRegion it) -> {
final Procedure1<IHiddenRegionFormatter> _function_1 = (IHiddenRegionFormatter it_1) -> {
it_1.autowrap();
it_1.oneSpace();
};
document.prepend(it, _function_1);
};
_ruleCallsTo.forEach(_function);
}
};
final GenericFormatter<IDList> 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<ITextReplacement> replacements = formatter.format(request);
final Function1<ITextReplacement, String> _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<String> _map = ListExtensions.<ITextReplacement, String>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);
}
}
}

View file

@ -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;