/******************************************************************************* * Copyright (c) 2008, 2009 Borland Software Corporation 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 * * Contributors: * Borland Software Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.m2m.internal.qvt.oml.ast.parser; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EEnumLiteral; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EOperation; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EParameter; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.m2m.internal.qvt.oml.ast.env.QVTParsingOptions; import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalEnv; import org.eclipse.m2m.internal.qvt.oml.cst.ObjectExpCS; import org.eclipse.m2m.internal.qvt.oml.expressions.Module; import org.eclipse.ocl.Environment; import org.eclipse.ocl.cst.CSTNode; import org.eclipse.ocl.cst.CallExpCS; import org.eclipse.ocl.cst.OCLExpressionCS; import org.eclipse.ocl.cst.SimpleNameCS; import org.eclipse.ocl.cst.VariableExpCS; import org.eclipse.ocl.ecore.CallOperationAction; import org.eclipse.ocl.ecore.Constraint; import org.eclipse.ocl.ecore.SendSignalAction; import org.eclipse.ocl.expressions.CallExp; import org.eclipse.ocl.expressions.OperationCallExp; import org.eclipse.ocl.expressions.PropertyCallExp; import org.eclipse.ocl.expressions.Variable; import org.eclipse.ocl.expressions.VariableExp; /** * Used to perform validation checks on obsolete usage of calls on implicit source object. * TODO - * 1) Perform appropriate renamings, to get rid of being a deprecation issue, but a normal validation. * 2) Move me to the central QVT validator class */ class DeprecatedImplicitSourceCallHelper { /** * Checks the given call expression if it does not used obsolete calls to * implicit source object. * <p> * <li/> <code>self</code> is not allowed to be implicitly resolved within * the contextual operation scope. * <li/> <code>this</code> is not allowed to be implicitly resolved when calling non-module owned * operation/property * * @param callExpCS * CST node representing the call, can be {@link VariableExpCS} * or {@link CallExpCS} * @param resultAST * AST representation of the call expression * @param env * the environment to receive validation problems */ static void validateCallExp(OCLExpressionCS callExpCS, CallExp<EClassifier> resultAST, Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) { CSTNode causeNode = null; if(callExpCS instanceof CallExpCS) { CallExpCS actualCallExpCS = (CallExpCS) callExpCS; if(actualCallExpCS.getSource() != null) { return; } causeNode = (actualCallExpCS.getSimpleNameCS() != null) ? actualCallExpCS.getSimpleNameCS() : callExpCS; } else if(callExpCS instanceof VariableExpCS && resultAST instanceof PropertyCallExp<?, ?>) { // property call using implicit source causeNode = callExpCS; } if(causeNode != null) { // call performed on implicit source if(resultAST instanceof CallExp<?>) { CallExp<EClassifier> call = (CallExp<EClassifier>) resultAST; if(call.getSource() instanceof VariableExp<?, ?>) { @SuppressWarnings("unchecked") VariableExp<EClassifier, EParameter> varExp = (VariableExp<EClassifier, EParameter>) call.getSource(); Variable<EClassifier, EParameter> refVar = varExp.getReferredVariable(); if(refVar != null && refVar.getName() != null) { String refVarName = refVar.getName(); if(QvtOperationalEnv.SELF_VARIABLE_NAME.equals(refVarName)) { boolean isImplicitSelfOk = false; EObject tempCS = callExpCS; while (tempCS != null) { if (tempCS instanceof ObjectExpCS) { ObjectExpCS objectExpCS = (ObjectExpCS) tempCS; SimpleNameCS referredObject = objectExpCS.getSimpleNameCS(); if (referredObject != null) { if (QvtOperationalEnv.SELF_VARIABLE_NAME.equals(referredObject.getValue())) { isImplicitSelfOk = true; break; } } } tempCS = tempCS.eContainer(); } if (!isImplicitSelfOk && isExplicitSelfEnforced(env)) { QvtOperationalUtil.reportError(env, ValidationMessages.DeprecatedImplicitSourceCall_contextualImplicitCall, causeNode); } } else if(refVarName != null && refVarName.equals(QvtOperationalEnv.THIS)) { if(resultAST instanceof OperationCallExp<?, ?>) { @SuppressWarnings("unchecked") OperationCallExp<EClassifier, EOperation> operCall = (OperationCallExp<EClassifier, EOperation>)resultAST; EOperation referredOperation = operCall.getReferredOperation(); if(referredOperation != null && !isModuleOperation(referredOperation, env)) { QvtOperationalUtil.reportWarning(env, ValidationMessages.DeprecatedImplicitSourceCall_moduleScopeImplicitCall, causeNode); } } else if(resultAST instanceof PropertyCallExp<?, ?>) { @SuppressWarnings("unchecked") PropertyCallExp<EClassifier, EStructuralFeature> propCall = (PropertyCallExp<EClassifier, EStructuralFeature>) resultAST; EStructuralFeature referredProperty = propCall.getReferredProperty(); if(referredProperty != null && !isModuleProperty(referredProperty, env)) { QvtOperationalUtil.reportWarning(env, ValidationMessages.DeprecatedImplicitSourceCall_moduleScopeImplicitCall, causeNode); } } } } } } } } private static boolean isModuleOperation(EOperation operation, Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) { EClassifier owningClassifier = env.getUMLReflection().getOwningClassifier(operation); return owningClassifier instanceof Module; } private static boolean isModuleProperty(EStructuralFeature feature, Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) { return env.getUMLReflection().getOwningClassifier(feature) instanceof Module; } private static boolean isExplicitSelfEnforced(Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) { return Boolean.TRUE.equals(QVTParsingOptions.getValue(env, QVTParsingOptions.ENFORCE_EXPLICIT_SELF_VARIABLE)); } }