mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-16 08:48:55 +00:00
[263773] Adjust named arguments in case of overrides
This commit is contained in:
parent
daada4dd08
commit
800c35080a
4 changed files with 58 additions and 10 deletions
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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';"
|
||||
|
|
Loading…
Reference in a new issue