From 59b17ef43033239c31a811aeb013b83c66137f63 Mon Sep 17 00:00:00 2001 From: Moritz Eysholdt Date: Wed, 6 Apr 2016 17:07:36 +0200 Subject: [PATCH] [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 --- .../xtext/linking/impl/LinkingHelper.java | 13 ++++++++--- .../serializer/tokens/ValueSerializer.java | 22 ++++++++++++++----- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/linking/impl/LinkingHelper.java b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/linking/impl/LinkingHelper.java index 9ac1c54a0..96c60edec 100644 --- a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/linking/impl/LinkingHelper.java +++ b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/linking/impl/LinkingHelper.java @@ -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) { diff --git a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/serializer/tokens/ValueSerializer.java b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/serializer/tokens/ValueSerializer.java index 1c43091a8..90bfd2924 100644 --- a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/serializer/tokens/ValueSerializer.java +++ b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/serializer/tokens/ValueSerializer.java @@ -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)