mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-16 08:48:55 +00:00
[464867] fixed 'ITextRegionAccess cannot handle duplicate keywords'
https://bugs.eclipse.org/bugs/show_bug.cgi?id=464867 Signed-off-by: Moritz Eysholdt <moritz.eysholdt@itemis.de>
This commit is contained in:
parent
4296349f3e
commit
7dc4339d7f
3 changed files with 79 additions and 7 deletions
|
@ -13,6 +13,8 @@ import org.eclipse.emf.ecore.EObject;
|
|||
import org.eclipse.emf.ecore.EStructuralFeature;
|
||||
import org.eclipse.xtext.AbstractRule;
|
||||
import org.eclipse.xtext.Action;
|
||||
import org.eclipse.xtext.CrossReference;
|
||||
import org.eclipse.xtext.Keyword;
|
||||
import org.eclipse.xtext.ParserRule;
|
||||
import org.eclipse.xtext.RuleCall;
|
||||
import org.eclipse.xtext.nodemodel.ILeafNode;
|
||||
|
@ -166,6 +168,8 @@ public interface ITextRegionAccess {
|
|||
*/
|
||||
ISemanticRegion regionForKeyword(EObject owner, String keyword);
|
||||
|
||||
ISemanticRegion regionForKeyword(EObject owner, Keyword keyword);
|
||||
|
||||
ITextSegment regionForOffset(int offset, int length);
|
||||
|
||||
IEObjectRegion regionForRootEObject();
|
||||
|
@ -178,6 +182,8 @@ public interface ITextRegionAccess {
|
|||
|
||||
ISemanticRegion regionForRuleCall(EObject owner, RuleCall ruleCall);
|
||||
|
||||
ISemanticRegion regionForCrossRef(EObject owner, CrossReference crossRef);
|
||||
|
||||
List<ISemanticRegion> regionsForRuleCalls(EObject owner, RuleCall... ruleCalls);
|
||||
|
||||
List<IEObjectRegion> regionsForAllEObjects();
|
||||
|
@ -186,7 +192,11 @@ public interface ITextRegionAccess {
|
|||
* @return All {@link ISemanticRegion semantic regions} that represent one of the provided 'keyword's and directly
|
||||
* belong to the provided 'EObject'. Keywords of child-EObjects are not considered.
|
||||
*/
|
||||
List<ISemanticRegion> regionsForKeywords(EObject owner, String... string);
|
||||
List<ISemanticRegion> regionsForKeywords(EObject owner, String... keywords);
|
||||
|
||||
List<ISemanticRegion> regionsForKeywords(EObject owner, Keyword... keywords);
|
||||
|
||||
List<ISemanticRegion> regionsForCrossRefs(EObject owner, CrossReference... crossRefs);
|
||||
|
||||
/**
|
||||
* @return All {@link ISemanticRegion semantic regions} that represent a RuleCall to one of the provided
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.eclipse.emf.ecore.EReference;
|
|||
import org.eclipse.emf.ecore.EStructuralFeature;
|
||||
import org.eclipse.xtext.AbstractRule;
|
||||
import org.eclipse.xtext.Assignment;
|
||||
import org.eclipse.xtext.CrossReference;
|
||||
import org.eclipse.xtext.GrammarUtil;
|
||||
import org.eclipse.xtext.Keyword;
|
||||
import org.eclipse.xtext.RuleCall;
|
||||
|
@ -168,6 +169,19 @@ public abstract class AbstractRegionAccess implements ITextRegionAccess {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ISemanticRegion regionForCrossRef(EObject owner, CrossReference crossRef) {
|
||||
return regionForRuleCall(owner, (RuleCall) crossRef.getTerminal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ISemanticRegion> regionsForCrossRefs(EObject owner, CrossReference... crossRefs) {
|
||||
List<RuleCall> rcs = Lists.newArrayList();
|
||||
for (int i = 0; i < crossRefs.length; i++)
|
||||
rcs.add((RuleCall) crossRefs[i].getTerminal());
|
||||
return regionsForRuleCalls(owner, rcs.toArray(new RuleCall[rcs.size()]));
|
||||
}
|
||||
|
||||
protected void assertNoContainment(EStructuralFeature feat) {
|
||||
if (!(feat instanceof EAttribute) && !(feat instanceof EReference && !((EReference) feat).isContainment()))
|
||||
throw new IllegalStateException("Only EAttributes and CrossReferences allowed.");
|
||||
|
@ -183,7 +197,7 @@ public abstract class AbstractRegionAccess implements ITextRegionAccess {
|
|||
}
|
||||
AbstractEObjectRegion tokens = regionForEObject(owner);
|
||||
if (tokens == null)
|
||||
return null;
|
||||
return Collections.emptyList();
|
||||
List<ISemanticRegion> result = Lists.newArrayList();
|
||||
for (ISemanticRegion region : tokens.getSemanticLeafRegions()) {
|
||||
Assignment assignment = GrammarUtil.containingAssignment(region.getGrammarElement());
|
||||
|
@ -209,6 +223,17 @@ public abstract class AbstractRegionAccess implements ITextRegionAccess {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ISemanticRegion regionForKeyword(EObject owner, Keyword keyword) {
|
||||
AbstractEObjectRegion tokens = regionForEObject(owner);
|
||||
if (tokens == null)
|
||||
return null;
|
||||
for (ISemanticRegion region : tokens.getSemanticLeafRegions())
|
||||
if (region.getGrammarElement() == keyword)
|
||||
return region;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ISemanticRegion regionForRuleCall(EObject owner, RuleCall ruleCall) {
|
||||
assertNoEObjectRuleCall(ruleCall);
|
||||
|
@ -227,7 +252,7 @@ public abstract class AbstractRegionAccess implements ITextRegionAccess {
|
|||
assertNoEObjectRuleCall(ruleCalls[i]);
|
||||
AbstractEObjectRegion tokens = regionForEObject(owner);
|
||||
if (tokens == null)
|
||||
return null;
|
||||
return Collections.emptyList();
|
||||
List<ISemanticRegion> result = Lists.newArrayList();
|
||||
for (ISemanticRegion region : tokens.getSemanticLeafRegions())
|
||||
for (int i = 0; i < ruleCalls.length; i++)
|
||||
|
@ -275,7 +300,20 @@ public abstract class AbstractRegionAccess implements ITextRegionAccess {
|
|||
if (kwSet.contains(kw.getValue()))
|
||||
result.add(token);
|
||||
}
|
||||
return result;
|
||||
return ImmutableList.copyOf(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ISemanticRegion> regionsForKeywords(EObject owner, Keyword... keywords) {
|
||||
AbstractEObjectRegion tokens = regionForEObject(owner);
|
||||
if (tokens == null)
|
||||
return Collections.emptyList();
|
||||
List<ISemanticRegion> result = Lists.newArrayList();
|
||||
for (ISemanticRegion region : tokens.getSemanticLeafRegions())
|
||||
for (int i = 0; i < keywords.length; i++)
|
||||
if (region.getGrammarElement() == keywords[i])
|
||||
result.add(region);
|
||||
return ImmutableList.copyOf(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -57,7 +57,7 @@ class RegionAccessAccessTest {
|
|||
assertEquals("foo", actual, actuals)
|
||||
}
|
||||
|
||||
def void regionForFeatureContainmentReference() {
|
||||
@Test def void regionForFeatureContainmentReference() {
|
||||
val mixed = '''6 (foo) action'''.parseAs(AssignedAction)
|
||||
val access = mixed.toAccess
|
||||
try {
|
||||
|
@ -112,8 +112,8 @@ class RegionAccessAccessTest {
|
|||
assertEquals("foo", actual, actuals)
|
||||
}
|
||||
|
||||
def void regionForRuleCallEObjectParserRule() {
|
||||
val mixed = '''6 (child foo)'''.parseAs(Mixed)
|
||||
@Test def void regionForRuleCallEObjectParserRule() {
|
||||
val mixed = '''6 (child (foo))'''.parseAs(Mixed)
|
||||
val access = mixed.toAccess
|
||||
try {
|
||||
access.regionForRuleCall(mixed, mixedAccess.eobjMixedParserRuleCall_2_2_1_1_0)
|
||||
|
@ -127,6 +127,30 @@ class RegionAccessAccessTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test def void regionForKeywordString() {
|
||||
val mixed = '''6 (foo)'''.parseAs(Mixed)
|
||||
val access = mixed.toAccess
|
||||
val actual = access.regionForKeyword(mixed, "(")
|
||||
val actuals = access.regionsForKeywords(mixed, "(")
|
||||
assertEquals("(", actual, actuals)
|
||||
}
|
||||
|
||||
@Test def void regionForKeyword() {
|
||||
val mixed = '''6 (foo)'''.parseAs(Mixed)
|
||||
val access = mixed.toAccess
|
||||
val actual = access.regionForKeyword(mixed, mixedAccess.leftParenthesisKeyword_0)
|
||||
val actuals = access.regionsForKeywords(mixed, mixedAccess.leftParenthesisKeyword_0)
|
||||
assertEquals("(", actual, actuals)
|
||||
}
|
||||
|
||||
@Test def void regionForCrossReference() {
|
||||
val mixed = '''6 (ref foo) action (foo) end'''.parseAs(AssignedAction)
|
||||
val access = mixed.toAccess
|
||||
val actual = access.regionForCrossRef(mixed.child, mixedAccess.refMixedCrossReference_2_2_3_1_0)
|
||||
val actuals = access.regionsForCrossRefs(mixed.child, mixedAccess.refMixedCrossReference_2_2_3_1_0)
|
||||
assertEquals("foo", actual, actuals)
|
||||
}
|
||||
|
||||
def private <T extends EObject> parseAs(CharSequence seq, Class<T> cls) {
|
||||
val result = seq.parse
|
||||
result.assertNoErrors
|
||||
|
|
Loading…
Reference in a new issue