
org.eclipse.xtext.serializer.diagnostic.SequencerDiagnosticProvider Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2011 itemis AG (http://www.itemis.eu) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.xtext.serializer.diagnostic;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.ENamedElement;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.xtext.AbstractElement;
import org.eclipse.xtext.IGrammarAccess;
import org.eclipse.xtext.grammaranalysis.impl.GrammarElementTitleSwitch;
import org.eclipse.xtext.serializer.analysis.Context2NameFunction;
import org.eclipse.xtext.serializer.analysis.IGrammarConstraintProvider;
import org.eclipse.xtext.serializer.analysis.IGrammarConstraintProvider.IConstraint;
import org.eclipse.xtext.serializer.analysis.IGrammarConstraintProvider.IConstraintContext;
import org.eclipse.xtext.serializer.analysis.ISemanticSequencerNfaProvider.ISemState;
import org.eclipse.xtext.serializer.sequencer.BacktrackingSemanticSequencer.SerializableObject;
import org.eclipse.xtext.serializer.sequencer.IContextFinder;
import org.eclipse.xtext.util.formallang.ProductionStringFactory;
import org.eclipse.xtext.util.formallang.Nfa;
import org.eclipse.xtext.util.formallang.NfaToProduction;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.inject.Inject;
/**
* @author Moritz Eysholdt - Initial contribution and API
*/
public class SequencerDiagnosticProvider implements ISemanticSequencerDiagnosticProvider {
/**
* @author meysholdt - Initial contribution and API
*/
private final class GetGrammarEle implements Function {
public AbstractElement apply(ISemState from) {
return from.getAssignedGrammarElement();
}
}
public static class NamedElement2Name implements Function {
public String apply(ENamedElement from) {
return from == null ? "null" : from.getName();
}
}
@Inject
protected Context2NameFunction context2Name;
@Inject
protected IGrammarAccess grammarAccess;
@Inject
protected IGrammarConstraintProvider grammarConstraints;
@Inject
protected IContextFinder contextFinder;
public ISerializationDiagnostic createFeatureValueMissing(EObject semanticObject, EStructuralFeature feature) {
String msg = "A value for feature '" + feature.getName() + "' is missing but required.";
return new SerializationDiagnostic(FEATURE_VALUE_MISSING, semanticObject, msg);
}
public ISerializationDiagnostic createInvalidContextOrTypeDiagnostic(EObject semanticObject, EObject context) {
Set contexts = Sets.newHashSet(contextFinder.findContextsByContentsAndContainer(semanticObject, null));
List validTypes = getValidTypes(context);
List recommendedCtxs = Lists.newArrayList();
List otherValidCtxs = Lists.newArrayList();
for (EObject ctx : getValidContexts(semanticObject.eClass())) {
if (contexts.contains(ctx))
recommendedCtxs.add(ctx);
else
otherValidCtxs.add(ctx);
}
String contextName = context2Name.apply(context);
String semanticType = semanticObject.eClass().getName();
String recommendCtxNames = Joiner.on(", ").join(Iterables.transform(recommendedCtxs, context2Name));
String validTypeNames = Joiner.on(", ").join(Iterables.transform(validTypes, new NamedElement2Name()));
StringBuilder msg = new StringBuilder();
msg.append("The context '" + contextName + "' is not valid for type '" + semanticType + "'\n");
msg.append("Recommended contexts for type '" + semanticType + "': " + recommendCtxNames + "\n");
if (!otherValidCtxs.isEmpty())
msg.append("Other valid contexts for type '" + semanticType + "': "
+ Joiner.on(", ").join(Iterables.transform(otherValidCtxs, context2Name)));
msg.append("The context '" + contextName + "' is valid for types: " + validTypeNames + "\n");
return new SerializationDiagnostic(INVALID_CONTEXT_OR_TYPE, semanticObject, msg.toString());
}
protected List getValidContexts(EClass clazz) {
List result = Lists.newArrayList();
List constraints = grammarConstraints.getConstraints(grammarAccess.getGrammar());
for (IConstraintContext ctx : constraints)
for (IConstraint c : ctx.getConstraints())
if (c.getType() == clazz)
result.add(ctx.getContext());
return result;
}
protected List getValidTypes(EObject context) {
List constraints = grammarConstraints.getConstraints(grammarAccess.getGrammar());
for (IConstraintContext ctx : constraints)
if (ctx.getContext() == context) {
List result = Lists.newArrayList();
for (IConstraint c : ctx.getConstraints())
result.add(c.getType());
return result;
}
return Collections.emptyList();
}
public ISerializationDiagnostic createBacktrackingFailedDiagnostic(SerializableObject semanticObject,
EObject context, Nfa nfa) {
GrammarElementTitleSwitch ele2str = new GrammarElementTitleSwitch().showAssignments().setValueForNull(null);
ProductionStringFactory grammarFactory = new ProductionStringFactory(ele2str);
String grammar = new NfaToProduction().nfaToGrammar(nfa, new GetGrammarEle(), grammarFactory);
StringBuilder msg = new StringBuilder();
msg.append("Could not serialize EObject via backtracking.\n");
msg.append("Constraint: " + grammar + "\n");
msg.append(semanticObject.getValuesString());
return new SerializationDiagnostic(BACKTRACKING_FAILED, semanticObject.getEObject(), context, msg.toString());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy