[263773] Adjust named arguments in case of overrides

This commit is contained in:
Sebastian Zarnekow 2015-08-13 13:20:55 +02:00
parent daada4dd08
commit 800c35080a
4 changed files with 58 additions and 10 deletions

View file

@ -33,6 +33,7 @@ import org.eclipse.xtext.GeneratedMetamodel;
import org.eclipse.xtext.Grammar;
import org.eclipse.xtext.GrammarUtil;
import org.eclipse.xtext.NamedArgument;
import org.eclipse.xtext.Parameter;
import org.eclipse.xtext.ParserRule;
import org.eclipse.xtext.ReferencedMetamodel;
import org.eclipse.xtext.RuleCall;
@ -409,10 +410,32 @@ public class XtextLinker extends Linker {
}
final List<RuleCall> allRuleCalls = EcoreUtil2.getAllContentsOfType(grammar, RuleCall.class);
for (RuleCall call : allRuleCalls) {
if (call.getRule() != null && !call.isExplicitlyCalled()) {
AbstractRule rule = rulePerName.get(call.getRule().getName());
if (rule != null)
AbstractRule calledRule = call.getRule();
if (calledRule != null && !call.isExplicitlyCalled()) {
AbstractRule rule = rulePerName.get(calledRule.getName());
if (rule != null) {
call.setRule(rule);
if (!call.getArguments().isEmpty()) {
if (calledRule instanceof ParserRule && rule instanceof ParserRule) {
updateNamedArguments(
call,
((ParserRule) calledRule).getParameters(),
((ParserRule) rule).getParameters());
}
}
}
}
}
}
private void updateNamedArguments(RuleCall call, List<Parameter> superParams,
List<Parameter> overridingParameters) {
for(NamedArgument argument: call.getArguments()) {
Parameter superParameter = argument.getParameter();
for(int i = 0, max = Math.min(superParams.size(), overridingParameters.size()); i < max ; i++) {
if (superParams.get(i) == superParameter) {
argument.setParameter(overridingParameters.get(i));
}
}
}
}

View file

@ -774,14 +774,14 @@ public class Xtext2EcoreTransformer {
"Overridden rule " + rule.getName() + " does not declare any parameters", rule);
}
StringBuilder message = new StringBuilder("Parameter list is incompatible with inherited ");
message.append(rule.getName()).append("[");
message.append(rule.getName()).append("<");
for(int i = 0; i < overridden.getParameters().size(); i++) {
if (i != 0) {
message.append(", ");
}
message.append(overridden.getParameters().get(i).getName());
}
message.append("]");
message.append(">");
throw new TransformationException(TransformationErrorCode.InvalidRuleOverride,
message.toString(), rule);
}

View file

@ -22,6 +22,8 @@ import org.eclipse.xtext.Alternatives
import org.eclipse.xtext.Negation
import org.eclipse.xtext.ParameterReference
import org.eclipse.xtext.LiteralCondition
import org.eclipse.emf.common.util.URI
import org.eclipse.xtext.util.LazyStringInputStream
/**
* @author Sven Efftinge - Initial contribution and API
@ -98,6 +100,31 @@ class XtextLinkerTest extends AbstractXtextTests {
assertFalse((argument.value as LiteralCondition).isTrue)
}
@Test def void testNamedParameterAdjustment() throws Exception {
val grammarAsString = '''
grammar test.Lang with org.eclipse.xtext.common.Terminals
generate test 'http://test'
Root<MyParam>: rule=Rule<true>;
Rule<MyParam>: name=ID child=Root<false>?;
'''
val grammar = grammarAsString.model as Grammar
val resourceSet = grammar.eResource.resourceSet
val otherResource = resourceSet.createResource(URI.createURI('other.xtext'))
otherResource.load(new LazyStringInputStream('''
grammar test.SubLang with test.Lang
import 'http://test'
Root<MyParam>: rule=super::Rule<true>;
'''), null)
val subGrammar = otherResource.contents.head as Grammar
val rootRule = subGrammar.rules.head as ParserRule
val parentRule = grammar.rules.last as ParserRule
val lastAssignment = (parentRule.alternatives as Group).elements.last as Assignment
val ruleCall = lastAssignment.terminal as RuleCall
val argument = ruleCall.arguments.head
assertEquals(rootRule.parameters.head, argument.parameter)
assertFalse((argument.value as LiteralCondition).isTrue)
}
@Test def void testExplicitRuleCallsAreTracked() throws Exception {
val grammarAsString = '''
grammar test.Lang with org.eclipse.xtext.common.Terminals

View file

@ -1817,12 +1817,10 @@ class Xtext2EcoreTransformerTest extends AbstractXtextTests {
var typeD = ePackage.type("TypeD") as EClass
assertNotNull(typeD)
assertNotNull(typeD.feature("x"))
assertEquals(1,
typeD.features.
size)
}
assertEquals(1, typeD.features.size)
}
@Test def void testBug346685_a05() throws Exception {
@Test def void testBug346685_a05() throws Exception {
var String grammar = '''grammar test with org.eclipse.xtext.common.Terminals generate test 'http://test'«»'''
grammar += " RuleA returns TypeA: RuleB? ({TypeC.x=current} 'x' | {TypeD.x=current} 'y')? name+=STRING;"
grammar += " RuleB returns TypeB: {TypeB} 'ignore';"