package it.xsemantics.dsl.validation;
import it.xsemantics.dsl.typing.TupleType;
import it.xsemantics.dsl.typing.XsemanticsTypeSystem;
import it.xsemantics.dsl.util.XsemanticsNodeModelUtils;
import it.xsemantics.dsl.util.XsemanticsUtils;
import it.xsemantics.dsl.util.XsemanticsXExpressionHelper;
import it.xsemantics.dsl.xsemantics.AuxiliaryDescription;
import it.xsemantics.dsl.xsemantics.AuxiliaryFunction;
import it.xsemantics.dsl.xsemantics.CheckRule;
import it.xsemantics.dsl.xsemantics.Injected;
import it.xsemantics.dsl.xsemantics.InputParameter;
import it.xsemantics.dsl.xsemantics.JudgmentDescription;
import it.xsemantics.dsl.xsemantics.JudgmentParameter;
import it.xsemantics.dsl.xsemantics.Rule;
import it.xsemantics.dsl.xsemantics.RuleConclusion;
import it.xsemantics.dsl.xsemantics.RuleConclusionElement;
import it.xsemantics.dsl.xsemantics.RuleInvocation;
import it.xsemantics.dsl.xsemantics.RuleParameter;
import it.xsemantics.dsl.xsemantics.XsemanticsPackage;
import it.xsemantics.dsl.xsemantics.XsemanticsSystem;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.common.types.JvmFormalParameter;
import org.eclipse.xtext.common.types.JvmIdentifiableElement;
import org.eclipse.xtext.common.types.JvmParameterizedTypeReference;
import org.eclipse.xtext.common.types.JvmTypeReference;
import org.eclipse.xtext.common.types.TypesPackage;
import org.eclipse.xtext.validation.Check;
import org.eclipse.xtext.validation.ValidationMessageAcceptor;
import org.eclipse.xtext.xbase.XAssignment;
import org.eclipse.xtext.xbase.XClosure;
import org.eclipse.xtext.xbase.XExpression;
import org.eclipse.xtext.xbase.XFeatureCall;
import org.eclipse.xtext.xbase.XReturnExpression;
import org.eclipse.xtext.xbase.XThrowExpression;
import org.eclipse.xtext.xbase.XbasePackage.Literals;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import com.google.inject.Inject;
public class XsemanticsJavaValidator extends AbstractXsemanticsValidator {
@Inject
protected XsemanticsTypeSystem typeSystem;
@Inject
protected XsemanticsUtils xsemanticsUtils;
@Inject
protected XsemanticsJavaValidatorHelper helper;
@Inject
protected XsemanticsXExpressionHelper xExpressionHelper;
@Inject
protected XsemanticsNodeModelUtils nodeModelUtils;
public final static int maxOfOutputParams = 3;
protected boolean enableWarnings = true;
@Override
@Check
public void checkAssignment(XAssignment assignment) {
// we allow assignment to output parameters
JvmIdentifiableElement assignmentFeature = assignment.getFeature();
if (assignmentFeature instanceof JvmFormalParameter) {
if (xsemanticsUtils
.isInputParam((JvmFormalParameter) assignmentFeature)) {
error("Assignment to input parameter",
Literals.XASSIGNMENT__ASSIGNABLE,
ValidationMessageAcceptor.INSIGNIFICANT_INDEX,
IssueCodes.ASSIGNMENT_TO_INPUT_PARAM);
}
return;
}
super.checkAssignment(assignment);
}
@Override
@Check
public void checkReturn(XReturnExpression expr) {
error("Return statements are not allowed here", expr, null,
IssueCodes.RETURN_NOT_ALLOWED);
}
// @Override
// protected boolean supportsCheckedExceptions() {
// // we generate Java code which already handles exceptions
// return false;
// }
@Override
protected boolean isImplicitReturn(XExpression expr) {
if (isContainedInAuxiliaryFunction(expr)) {
return super.isImplicitReturn(expr);
}
// we will deal with this during generation
return false;
}
protected boolean isContainedInAuxiliaryFunction(XExpression expr) {
return EcoreUtil2.getContainerOfType(expr, AuxiliaryFunction.class) != null;
}
@Check
public void checkThrow(XThrowExpression expr) {
error("Throw statements are not allowed here", expr, null,
IssueCodes.THROW_NOT_ALLOWED);
}
@Override
protected boolean isLocallyUsed(EObject target, EObject containerToFindUsage) {
if (containerToFindUsage instanceof RuleInvocation) {
// we don't want warning when a variable declaration appears as
// output argument: it is implicitly used for the result
return true;
}
return super.isLocallyUsed(target, containerToFindUsage);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.xtext.xbase.validation.XbaseJavaValidator#
* isValueExpectedRecursive(org.eclipse.xtext.xbase.XExpression)
*/
@Override
protected boolean isValueExpectedRecursive(XExpression expr) {
// this is used by Xbase validator to check expressions with
// side effects, by inspecting expr's container
// so we must customize it when the container is one of our
// custom XExpressions
final boolean valueExpectedRecursive = super
.isValueExpectedRecursive(expr);
return valueExpectedRecursive
|| xExpressionHelper.isXsemanticsXExpression(expr.eContainer());
}
@Check
public void checkJudgmentDescription(JudgmentDescription judgmentDescription) {
checkNoDuplicateJudgmentDescriptionSymbols(judgmentDescription);
checkNumOfOutputParams(judgmentDescription);
checkNumOfInputParams(judgmentDescription);
}
@Check
public void checkJudgmentDescriptionHasRules(
JudgmentDescription judgmentDescription) {
if (judgmentDescription.isOverride())
return;
if (enableWarnings
&& xsemanticsUtils.rulesForJudgmentDescription(
judgmentDescription).isEmpty()) {
warning("No rule defined for the judgment description",
XsemanticsPackage.Literals.JUDGMENT_DESCRIPTION
.getEIDAttribute(),
IssueCodes.NO_RULE_FOR_JUDGMENT_DESCRIPTION);
}
}
@Check
public void checkInputParameter(InputParameter param) {
if (helper.findDuplicateParameter(param)) {
error("Duplicate parameter '" + param.getParameter().getName()
+ "'",
XsemanticsPackage.Literals.INPUT_PARAMETER__PARAMETER,
IssueCodes.DUPLICATE_PARAM_NAME);
}
}
@Check
public void checkNoDuplicateJudgmentDescription(
JudgmentDescription judgmentDescription) {
JudgmentDescription judgmentDescriptionWithTheSameName = helper
.judgmentDescriptionWithTheSameName(judgmentDescription);
if (judgmentDescriptionWithTheSameName != null
&& !judgmentDescription.isOverride()) {
error("Duplicate judgment '"
+ judgmentDescription.getName()
+ "'"
+ reportContainingSystemName(judgmentDescriptionWithTheSameName),
XsemanticsPackage.Literals.JUDGMENT_DESCRIPTION__NAME,
IssueCodes.DUPLICATE_JUDGMENT_NAME);
}
}
protected void checkNoDuplicateJudgmentDescriptionSymbols(
JudgmentDescription judgmentDescription) {
String judgmentSymbol = judgmentDescription.getJudgmentSymbol();
List<String> relationSymbols = judgmentDescription.getRelationSymbols();
if (xsemanticsUtils.getJudgmentDescriptions(
xsemanticsUtils.containingSystem(judgmentDescription),
judgmentSymbol, relationSymbols).size() > 1) {
error("Duplicate JudgmentDescription symbols: "
+ symbolsRepresentation(judgmentSymbol, relationSymbols),
XsemanticsPackage.Literals.JUDGMENT_DESCRIPTION__JUDGMENT_SYMBOL,
IssueCodes.DUPLICATE_JUDGMENT_DESCRIPTION_SYMBOLS);
}
}
protected void checkNumOfOutputParams(
JudgmentDescription judgmentDescription) {
if (xsemanticsUtils.outputJudgmentParameters(judgmentDescription)
.size() > maxOfOutputParams) {
error("No more than " + maxOfOutputParams
+ " output parameters are handled at the moment",
XsemanticsPackage.Literals.JUDGMENT_DESCRIPTION__JUDGMENT_PARAMETERS,
IssueCodes.TOO_MANY_OUTPUT_PARAMS);
}
}
protected void checkNumOfInputParams(JudgmentDescription judgmentDescription) {
if (xsemanticsUtils.inputParams(judgmentDescription).isEmpty()) {
error("No input parameter; at least one is needed",
XsemanticsPackage.Literals.JUDGMENT_DESCRIPTION__JUDGMENT_PARAMETERS,
IssueCodes.NO_INPUT_PARAM);
}
}
@Check
public void checkRule(Rule rule) {
JudgmentDescription judgmentDescription = checkRuleConformantToJudgmentDescription(rule);
if (judgmentDescription != null) {
List<JudgmentParameter> judgmentParameters = judgmentDescription
.getJudgmentParameters();
List<RuleConclusionElement> conclusionElements = rule
.getConclusion().getConclusionElements();
// judgmentParameters.size() == conclusionElements.size())
// otherwise we could not find a JudgmentDescription for the rule
Iterator<JudgmentParameter> judgmentParametersIt = judgmentParameters
.iterator();
for (RuleConclusionElement ruleConclusionElement : conclusionElements) {
if (!xsemanticsUtils.isOutputParameter(judgmentParametersIt
.next())
&& !(ruleConclusionElement instanceof RuleParameter)) {
error("Must be a parameter, not an expression",
ruleConclusionElement,
XsemanticsPackage.Literals.RULE_CONCLUSION_ELEMENT
.getEIDAttribute(),
IssueCodes.NOT_PARAMETER);
}
}
}
}
@Check
public void checkNoCheckRulesWithTheSameName(Rule rule) {
if (!helper.noRulesWithTheSameName(rule)) {
error("Duplicate rule '" + rule.getName() + "'", rule,
XsemanticsPackage.Literals.RULE__NAME,
IssueCodes.DUPLICATE_RULE_NAME);
}
if (!helper.noRulesWithTheSameNameOfCheckRule(rule)) {
error("Duplicate checkrule with the same name", rule,
XsemanticsPackage.Literals.RULE__NAME,
IssueCodes.DUPLICATE_RULE_NAME);
}
}
@Check
public void checkNoRulesWithTheSameName(CheckRule rule) {
if (!helper.noCheckRulesWithTheSameName(rule)) {
error("Duplicate checkrule '" + rule.getName() + "'", rule,
XsemanticsPackage.Literals.CHECK_RULE__NAME,
IssueCodes.DUPLICATE_RULE_NAME);
}
if (!helper.noCheckRulesWithTheSameNameOfRule(rule)) {
error("Duplicate rule with the same name", rule,
XsemanticsPackage.Literals.CHECK_RULE__NAME,
IssueCodes.DUPLICATE_RULE_NAME);
}
}
@Check
public void checkValidOverride(Rule rule) {
XsemanticsSystem system = xsemanticsUtils.containingSystem(rule);
if (system != null) {
if (rule.isOverride()) {
XsemanticsSystem superSystem = xsemanticsUtils
.superSystemDefinition(system);
if (superSystem == null) {
error("Cannot override rule without system 'extends'",
rule, XsemanticsPackage.Literals.RULE__OVERRIDE,
IssueCodes.OVERRIDE_WITHOUT_SYSTEM_EXTENDS);
} else {
List<Rule> rulesOfTheSameKind = xsemanticsUtils
.allRulesOfTheSameKind(superSystem, rule);
TupleType tupleType = typeSystem.getInputTypes(rule);
Rule ruleToOverride = null;
for (Rule rule2 : rulesOfTheSameKind) {
TupleType tupleType2 = typeSystem.getInputTypes(rule2);
if (typeSystem.equals(tupleType, tupleType2, rule)) {
ruleToOverride = rule2;
break;
}
}
if (ruleToOverride == null) {
error("No rule of the same kind to override: "
+ tupleTypeRepresentation(tupleType), rule,
XsemanticsPackage.Literals.RULE__OVERRIDE,
IssueCodes.NO_RULE_TO_OVERRIDE_OF_THE_SAME_KIND);
} else if (!ruleToOverride.getName().equals(rule.getName())) {
error("Must have the same name of the rule to override: "
+ ruleToOverride.getName(),
rule,
XsemanticsPackage.Literals.RULE__OVERRIDE,
IssueCodes.OVERRIDE_RULE_MUST_HAVE_THE_SAME_NAME);
}
}
}
}
}
@Check
public void checkValidOverride(CheckRule rule) {
XsemanticsSystem system = xsemanticsUtils.containingSystem(rule);
if (system != null) {
if (rule.isOverride()) {
XsemanticsSystem superSystem = xsemanticsUtils
.superSystemDefinition(system);
if (superSystem == null) {
error("Cannot override checkrule without system 'extends'",
rule,
XsemanticsPackage.Literals.CHECK_RULE__OVERRIDE,
IssueCodes.OVERRIDE_WITHOUT_SYSTEM_EXTENDS);
} else {
ArrayList<CheckRule> inheritedCheckRules = xsemanticsUtils
.allCheckRules(superSystem);
CheckRule inheritedRule = null;
for (CheckRule checkRule2 : inheritedCheckRules) {
if (typeSystem.equals(rule.getElement().getParameter()
.getParameterType(), checkRule2.getElement()
.getParameter().getParameterType(), rule)
&& rule.getName().equals(checkRule2.getName())) {
inheritedRule = checkRule2;
}
}
if (inheritedRule == null)
error("No checkrule to override: " + rule.getName(),
rule,
XsemanticsPackage.Literals.CHECK_RULE__OVERRIDE,
IssueCodes.NO_RULE_TO_OVERRIDE_OF_THE_SAME_KIND);
}
}
}
}
@Check
public void checkValidOverride(JudgmentDescription judgment) {
XsemanticsSystem system = xsemanticsUtils.containingSystem(judgment);
if (system != null) {
if (judgment.isOverride()) {
XsemanticsSystem superSystem = xsemanticsUtils
.superSystemDefinition(system);
if (superSystem == null) {
error("Cannot override judgment without system 'extends'",
judgment,
XsemanticsPackage.Literals.JUDGMENT_DESCRIPTION__OVERRIDE,
IssueCodes.OVERRIDE_WITHOUT_SYSTEM_EXTENDS);
} else {
List<JudgmentDescription> inheritedJudgments = xsemanticsUtils
.allJudgments(superSystem,
judgment.getJudgmentSymbol(),
judgment.getRelationSymbols());
JudgmentDescription judgmentToOverride = null;
for (JudgmentDescription judgment2 : inheritedJudgments) {
if (typeSystem.equals(judgment, judgment2)) {
judgmentToOverride = judgment2;
break;
}
}
if (judgmentToOverride == null) {
error("No judgment of the same kind to override: "
+ nodeModelUtils.getProgramText(judgment),
judgment,
XsemanticsPackage.Literals.JUDGMENT_DESCRIPTION__OVERRIDE,
IssueCodes.NO_JUDGMENT_TO_OVERRIDE_OF_THE_SAME_KIND);
} else if (!judgmentToOverride.getName().equals(
judgment.getName())) {
error("Must have the same name of the judgment to override: "
+ judgmentToOverride.getName(),
judgment,
XsemanticsPackage.Literals.JUDGMENT_DESCRIPTION__OVERRIDE,
IssueCodes.OVERRIDE_JUDGMENT_MUST_HAVE_THE_SAME_NAME);
}
}
}
}
}
@Check
public void checkRuleInvocation(RuleInvocation ruleInvocation) {
JudgmentDescription judgmentDescription = checkRuleInvocationConformantToJudgmentDescription(ruleInvocation);
if (judgmentDescription != null) {
List<JudgmentParameter> judgmentParameters = judgmentDescription
.getJudgmentParameters();
List<XExpression> invocationExpressions = ruleInvocation
.getExpressions();
// judgmentParamters.size() == conclusionElements.size())
// otherwise we could not find a JudgmentDescription for the rule
Iterator<JudgmentParameter> judgmentParametersIt = judgmentParameters
.iterator();
for (XExpression ruleInvocationExpression : invocationExpressions) {
if (xsemanticsUtils.isOutputParameter(judgmentParametersIt
.next())) {
if (!xsemanticsUtils
.validOutputArgExpression(ruleInvocationExpression)) {
error("Not a valid argument for output parameter: "
+ nodeModelUtils
.getProgramText(ruleInvocationExpression),
ruleInvocationExpression,
null,
IssueCodes.NOT_VALID_OUTPUT_ARG);
}
} else {
if (!xsemanticsUtils
.validInputArgExpression(ruleInvocationExpression)) {
error("Not a valid argument for input parameter: "
+ nodeModelUtils
.getProgramText(ruleInvocationExpression),
ruleInvocationExpression,
null,
IssueCodes.NOT_VALID_INPUT_ARG);
}
}
}
}
}
@Check
public void checkSystem(XsemanticsSystem system) {
JvmParameterizedTypeReference validatorExtends = system
.getValidatorExtends();
if (validatorExtends != null) {
if (!typeSystem.isAbstractDeclarativeValidator(validatorExtends,
system)) {
error("Not an AbstractDeclarativeValidator: "
+ getNameOfTypes(validatorExtends),
XsemanticsPackage.Literals.XSEMANTICS_SYSTEM__VALIDATOR_EXTENDS,
IssueCodes.NOT_VALIDATOR);
}
}
JvmParameterizedTypeReference superSystem = system.getSuperSystem();
if (superSystem != null) {
if (!typeSystem.isValidSuperSystem(superSystem, system)) {
error("Not an Xsemantics system: "
+ getNameOfTypes(superSystem),
XsemanticsPackage.Literals.XSEMANTICS_SYSTEM__SUPER_SYSTEM,
IssueCodes.NOT_VALID_SUPER_SYSTEM);
}
if (validatorExtends != null) {
error("system 'extends' cannot coexist with 'validatorExtends'",
XsemanticsPackage.Literals.XSEMANTICS_SYSTEM__SUPER_SYSTEM,
IssueCodes.EXTENDS_CANNOT_COEXIST_WITH_VALIDATOR_EXTENDS);
error("system 'extends' cannot coexist with 'validatorExtends'",
XsemanticsPackage.Literals.XSEMANTICS_SYSTEM__VALIDATOR_EXTENDS,
IssueCodes.EXTENDS_CANNOT_COEXIST_WITH_VALIDATOR_EXTENDS);
}
}
List<XsemanticsSystem> superSystems = xsemanticsUtils
.allSuperSystemDefinitions(system);
if (superSystems.contains(system)) {
error("Cycle in extends relation",
XsemanticsPackage.Literals.XSEMANTICS_SYSTEM__SUPER_SYSTEM,
IssueCodes.CYCLIC_HIERARCHY);
}
}
@Check
protected void checkNoDuplicateCheckRulesWithSameArguments(CheckRule rule) {
if (rule.isOverride())
return;
XsemanticsSystem system = xsemanticsUtils
.superSystemDefinition(xsemanticsUtils.containingSystem(rule));
if (system != null) {
List<CheckRule> rulesWithTheSameName = xsemanticsUtils
.allCheckRulesByName(system, rule);
for (CheckRule checkRule : rulesWithTheSameName) {
error("Duplicate checkrule with the same name"
+ reportContainingSystemName(checkRule),
XsemanticsPackage.Literals.CHECK_RULE__NAME,
IssueCodes.DUPLICATE_RULE_NAME);
}
}
}
@Check
protected void checkNoDuplicateRulesWithSameArguments(Rule rule) {
List<Rule> rulesOfTheSameKind = xsemanticsUtils
.allRulesOfTheSameKind(rule);
if (rulesOfTheSameKind.size() > 1) {
TupleType tupleType = typeSystem.getInputTypes(rule);
for (Rule rule2 : rulesOfTheSameKind) {
if (rule2 != rule && !rule.isOverride()) {
TupleType tupleType2 = typeSystem.getInputTypes(rule2);
if (typeSystem.equals(tupleType, tupleType2, rule)) {
error("Duplicate rule of the same kind with parameters: "
+ tupleTypeRepresentation(tupleType)
+ reportContainingSystemName(rule2),
XsemanticsPackage.Literals.RULE__CONCLUSION,
IssueCodes.DUPLICATE_RULE_WITH_SAME_ARGUMENTS);
break;
}
}
}
}
}
@Check
public void checkAuxiliaryDescription(AuxiliaryDescription aux) {
if (helper.auxiliaryDescriptionWithTheSameName(aux) != null) {
error("Duplicate auxiliary description '" + aux.getName() + "'",
XsemanticsPackage.Literals.AUXILIARY_DESCRIPTION__NAME,
IssueCodes.DUPLICATE_AUXILIARY_NAME);
}
if (helper.auxiliaryDescriptionWithTheSameNameOfJudgment(aux) != null) {
error("Duplicate judgment with the same name '" + aux.getName()
+ "'",
XsemanticsPackage.Literals.AUXILIARY_DESCRIPTION__NAME,
IssueCodes.DUPLICATE_AUXILIARY_NAME);
}
}
@Check
public void checkAuxiliaryFunctions(AuxiliaryDescription aux) {
List<AuxiliaryFunction> functionsForAuxiliaryDescrition = xsemanticsUtils.functionsForAuxiliaryDescrition(aux);
if (enableWarnings
&& functionsForAuxiliaryDescrition
.isEmpty()) {
warning("No function defined for the auxiliary description",
XsemanticsPackage.Literals.AUXILIARY_DESCRIPTION
.getEIDAttribute(),
IssueCodes.NO_AUXFUN_FOR_AUX_DESCRIPTION);
}
if (functionsForAuxiliaryDescrition.size() > 1) {
for (AuxiliaryFunction auxiliaryFunction : functionsForAuxiliaryDescrition) {
TupleType tupleType = typeSystem.getInputTypes(auxiliaryFunction);
for (AuxiliaryFunction auxiliaryFunction2 : functionsForAuxiliaryDescrition) {
if (auxiliaryFunction == auxiliaryFunction2)
continue;
TupleType tupleType2 = typeSystem.getInputTypes(auxiliaryFunction2);
if (typeSystem.equals(tupleType, tupleType2, auxiliaryFunction)) {
error("Duplicate auxiliary function of the same kind with parameters: "
+ tupleTypeRepresentation(tupleType)
+ reportContainingSystemName(auxiliaryFunction2),
auxiliaryFunction2,
XsemanticsPackage.Literals.AUXILIARY_FUNCTION__PARAMETERS,
IssueCodes.DUPLICATE_AUXFUN_WITH_SAME_ARGUMENTS);
break;
}
}
}
}
}
@Check
public void checkAuxiliaryFunctionHasAuxiliaryDescription(
AuxiliaryFunction aux) {
AuxiliaryDescription auxiliaryDescription = xsemanticsUtils
.auxiliaryDescription(aux);
if (auxiliaryDescription == null)
error("No auxiliary description for auxiliary function '"
+ aux.getName() + "'",
XsemanticsPackage.Literals.AUXILIARY_FUNCTION__NAME,
IssueCodes.NO_AUXDESC_FOR_AUX_FUNCTION);
else
checkConformanceOfAuxiliaryFunction(aux, auxiliaryDescription);
}
@Check
public void checkOutputParamAccessWithinClosure(XFeatureCall featureCall) {
JvmIdentifiableElement feature = featureCall.getFeature();
if (feature instanceof JvmFormalParameter) {
EObject container = feature.eContainer();
if (container instanceof RuleParameter) {
if (xsemanticsUtils.isOutputParam((RuleParameter) container)
&& insideClosure(featureCall)) {
error("Cannot refer to an output parameter "
+ feature.getIdentifier()
+ " from within a closure", featureCall, null,
IssueCodes.ACCESS_TO_OUTPUT_PARAM_WITHIN_CLOSURE);
}
}
return;
}
}
@Check
public void checkInjected(Injected i) {
if (helper.hasDuplicateInjectedField(i)) {
error("Duplicate injection '" + i.getName() + "'",
XsemanticsPackage.eINSTANCE.getInjected_Name(),
IssueCodes.DUPLICATE_INJECTED_FIELD);
}
}
private boolean insideClosure(XFeatureCall featureCall) {
return EcoreUtil2.getContainerOfType(featureCall,
XClosure.class) != null;
}
protected void checkConformanceOfAuxiliaryFunction(AuxiliaryFunction aux,
AuxiliaryDescription auxiliaryDescription) {
List<JvmFormalParameter> funParams = aux.getParameters();
List<JvmFormalParameter> descParams = auxiliaryDescription
.getParameters();
if (funParams.size() != descParams.size())
error("expected " + descParams.size() + " parameter(s), but was "
+ funParams.size(),
aux,
XsemanticsPackage.Literals.AUXILIARY_FUNCTION__PARAMETERS,
IssueCodes.PARAMS_SIZE_DONT_MATCH);
else {
Iterator<JvmFormalParameter> funParamsIt = funParams.iterator();
for (JvmFormalParameter jvmFormalParameter : descParams) {
JvmTypeReference expected = typeSystem
.getType(jvmFormalParameter);
JvmFormalParameter funParam = funParamsIt.next();
JvmTypeReference actual = typeSystem.getType(funParam);
if (!typeSystem.isConformant(expected, actual, funParam)) {
error("parameter type "
+ getNameOfTypes(actual)
+ " is not subtype of AuxiliaryDescription declared type "
+ getNameOfTypes(expected),
funParam,
TypesPackage.Literals.JVM_FORMAL_PARAMETER__PARAMETER_TYPE,
IssueCodes.NOT_SUBTYPE);
}
}
}
}
protected String reportContainingSystemName(EObject object) {
return ", in system: "
+ xsemanticsUtils.containingSystem(object).getName();
}
protected JudgmentDescription checkRuleConformantToJudgmentDescription(
Rule rule) {
RuleConclusion conclusion = rule.getConclusion();
return checkConformanceAgainstJudgmentDescription(conclusion,
conclusion.getJudgmentSymbol(),
conclusion.getRelationSymbols(),
conclusion.getConclusionElements(), "Rule conclusion",
XsemanticsPackage.Literals.RULE__CONCLUSION,
XsemanticsPackage.Literals.RULE_CONCLUSION_ELEMENT
.getEIDAttribute());
}
protected JudgmentDescription checkRuleInvocationConformantToJudgmentDescription(
RuleInvocation ruleInvocation) {
return checkConformanceAgainstJudgmentDescription(
ruleInvocation,
ruleInvocation.getJudgmentSymbol(),
ruleInvocation.getRelationSymbols(),
ruleInvocation.getExpressions(),
"Rule invocation",
XsemanticsPackage.Literals.RULE_INVOCATION.getEIDAttribute(),
null);
}
protected JudgmentDescription checkConformanceAgainstJudgmentDescription(
EObject element, String judgmentSymbol,
Iterable<String> relationSymbols,
Iterable<? extends EObject> elements,
final String elementDescription, EStructuralFeature elementFeature,
EStructuralFeature conformanceFeature) {
JudgmentDescription judgmentDescription = xsemanticsUtils
.judgmentDescription(element, judgmentSymbol, relationSymbols);
if (judgmentDescription == null) {
error("No Judgment description for: "
+ symbolsRepresentation(judgmentSymbol, relationSymbols),
elementFeature, IssueCodes.NO_JUDGMENT_DESCRIPTION);
} else {
List<JudgmentParameter> judgmentParameters = judgmentDescription
.getJudgmentParameters();
Iterator<? extends EObject> elementsIt = elements.iterator();
for (JudgmentParameter judgmentParameter : judgmentParameters) {
// the rule might still be incomplete, thus we must check
// whether there is an element to check against.
// Recall that the judgment has been searched for using only
// the symbols, not the rele conclusion elements
if (elementsIt.hasNext())
checkConformance(judgmentParameter, elementsIt.next(),
elementDescription, conformanceFeature);
}
}
return judgmentDescription;
}
protected void checkConformance(JudgmentParameter judgmentParameter,
EObject element, final String elementDescription,
EStructuralFeature feature) {
JvmTypeReference expected = typeSystem.getType(judgmentParameter);
JvmTypeReference actual = typeSystem.getType(element);
if (!typeSystem.isConformant(expected, actual, element)) {
error(elementDescription + " type " + getNameOfTypes(actual)
+ " is not subtype of JudgmentDescription declared type "
+ getNameOfTypes(expected), element, feature,
IssueCodes.NOT_SUBTYPE);
}
}
protected String symbolsRepresentation(String judgmentSymbol,
Iterable<String> relationSymbols) {
return judgmentSymbol + " "
+ IterableExtensions.join(relationSymbols, " ");
}
protected String tupleTypeRepresentation(TupleType tupleType) {
StringBuilder builder = new StringBuilder();
Iterator<JvmTypeReference> it = tupleType.iterator();
while (it.hasNext()) {
builder.append(getNameOfTypes(it.next()));
if (it.hasNext())
builder.append(", ");
}
return builder.toString();
}
private Object getNameOfTypes(JvmTypeReference typeRef) {
return (typeRef == null) ? "<null>" : typeRef.getSimpleName();
}
public boolean isEnableWarnings() {
return enableWarnings;
}
public void setEnableWarnings(boolean enableWarnings) {
this.enableWarnings = enableWarnings;
}
}