[serializer] never attempt to call ValueConverter with wrong rule

---Example---
Rule: name=FQN | name=STRING;
-------------

When FQN has been parsed but the serializer decided to write out 
STRING it was calling the IValueConverter with FQN's INode and rule 
STRING. That's obviously wrong input for the ValueConverter. 

The fix just prevents the IValueConverter to be called in this scenario,
causing the INode's text to be ignored; Instead fresh output is
generated via IValueConverter.toString(...) 

Signed-off-by: Moritz Eysholdt <moritz.eysholdt@typefox.io>
This commit is contained in:
Moritz Eysholdt 2016-04-06 17:07:36 +02:00
parent 29ddc6b881
commit 59b17ef430
2 changed files with 26 additions and 9 deletions

View file

@ -37,15 +37,22 @@ public class LinkingHelper {
* may be any crossreferencable element, i.e. a keyword or a rulecall
*/
public String getRuleNameFrom(EObject grammarElement) {
AbstractRule rule = getRuleFrom(grammarElement);
return rule != null ? rule.getName() : null;
}
/**
* @since 2.10
*/
public AbstractRule getRuleFrom(EObject grammarElement) {
if (!(grammarElement instanceof Keyword || grammarElement instanceof RuleCall || grammarElement instanceof CrossReference))
throw new IllegalArgumentException("grammarElement is of type: '" + grammarElement.eClass().getName() + "'");
AbstractRule rule = null;
EObject elementToUse = grammarElement;
if (grammarElement instanceof CrossReference)
elementToUse = ((CrossReference) grammarElement).getTerminal();
if (elementToUse instanceof RuleCall)
rule = ((RuleCall) elementToUse).getRule();
return rule != null ? rule.getName() : null;
return ((RuleCall) elementToUse).getRule();
return null;
}
public String getCrossRefNodeAsString(INode node, boolean convert) {

View file

@ -8,14 +8,16 @@
package org.eclipse.xtext.serializer.tokens;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.AbstractRule;
import org.eclipse.xtext.RuleCall;
import org.eclipse.xtext.conversion.IValueConverterService;
import org.eclipse.xtext.linking.impl.LinkingHelper;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.parsetree.reconstr.impl.TokenUtil;
import org.eclipse.xtext.serializer.diagnostic.ISerializationDiagnostic.Acceptor;
import org.eclipse.xtext.xtext.RuleNames;
import org.eclipse.xtext.serializer.diagnostic.ITokenDiagnosticProvider;
import org.eclipse.xtext.xtext.RuleNames;
import com.google.inject.Inject;
@ -26,10 +28,13 @@ public class ValueSerializer implements IValueSerializer {
@Inject
private IValueConverterService converter;
@Inject
private RuleNames ruleNames;
@Inject
private LinkingHelper linkingHelper;
@Inject
protected ITokenDiagnosticProvider diagnostics;
@ -54,13 +59,18 @@ public class ValueSerializer implements IValueSerializer {
@Override
public String serializeAssignedValue(EObject context, RuleCall ruleCall, Object value, INode node, Acceptor errors) {
AbstractRule rule = ruleCall.getRule();
String ruleName = ruleNames.getQualifiedName(rule);
if (node != null) {
Object converted = converter.toValue(NodeModelUtils.getTokenText(node), ruleNames.getQualifiedName(ruleCall.getRule()), node);
if (converted != null && converted.equals(value))
return tokenUtil.serializeNode(node);
AbstractRule nodeRule = linkingHelper.getRuleFrom(node.getGrammarElement());
if (rule == nodeRule) {
Object converted = converter.toValue(NodeModelUtils.getTokenText(node), ruleName, node);
if (converted != null && converted.equals(value))
return tokenUtil.serializeNode(node);
}
}
try {
String str = converter.toString(value, ruleNames.getQualifiedName(ruleCall.getRule()));
String str = converter.toString(value, ruleName);
if (str != null)
return str;
if (errors != null)