/******************************************************************************* * Copyright (c) 2007, 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.editor.ui.hyperlinks; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EParameter; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.hyperlink.IHyperlink; import org.eclipse.m2m.internal.qvt.oml.ast.binding.ASTBindingHelper; import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalEnv; import org.eclipse.m2m.internal.qvt.oml.cst.ParameterDeclarationCS; import org.eclipse.m2m.internal.qvt.oml.cst.TypeSpecCS; import org.eclipse.m2m.internal.qvt.oml.cst.VariableInitializationCS; import org.eclipse.m2m.internal.qvt.oml.editor.ui.CSTHelper; import org.eclipse.m2m.internal.qvt.oml.expressions.ModelParameter; import org.eclipse.m2m.internal.qvt.oml.expressions.OperationalTransformation; import org.eclipse.m2m.internal.qvt.oml.expressions.VarParameter; import org.eclipse.ocl.cst.CSTNode; import org.eclipse.ocl.cst.SimpleNameCS; import org.eclipse.ocl.cst.VariableCS; import org.eclipse.ocl.cst.VariableExpCS; import org.eclipse.ocl.ecore.TupleLiteralExp; import org.eclipse.ocl.ecore.VariableExp; import org.eclipse.ocl.expressions.Variable; import org.eclipse.ocl.utilities.ASTNode; public class VariableHyperlinkDetector implements IHyperlinkDetectorHelper { public IHyperlink detectHyperlink(IDetectionContext context) { CSTNode syntaxElement = context.getSyntaxElement(); CSTNode targetCS = null; if (syntaxElement instanceof SimpleNameCS) { SimpleNameCS nameCS = (SimpleNameCS)context.getSyntaxElement(); CSTNode varDeclElement = resolveVariableDeclaration(nameCS); if(varDeclElement instanceof ParameterDeclarationCS) { ParameterDeclarationCS paramDeclCS = (ParameterDeclarationCS) varDeclElement; SimpleNameCS paramNameCS = paramDeclCS.getSimpleNameCS(); if(paramNameCS != null && paramNameCS.getValue() != null) { targetCS = paramNameCS; } } else if(varDeclElement instanceof VariableInitializationCS) { // resolve declared variable VariableInitializationCS varDecl = (VariableInitializationCS)varDeclElement; SimpleNameCS varName = varDecl.getSimpleNameCS(); if(varName != null && varName.getValue() != null) { targetCS = varName; } } else if(varDeclElement instanceof VariableCS) { targetCS = varDeclElement; } } else if(syntaxElement instanceof VariableCS) { EObject eContainer = syntaxElement.eContainer(); if(eContainer instanceof TupleLiteralExp) { // TODO - not trivial as multiple tuple types CST may exist but are always resolved to // a single TupleType EClassifier instance => no unambiguous way to go to a definition location return null; } } if(targetCS != null) { IRegion linkRegion = HyperlinkUtil.createRegion(syntaxElement); IRegion targetRegion = HyperlinkUtil.createRegion(targetCS); URI sourceURI = context.getModule().getURI(); return new QvtFileHyperlink(linkRegion, sourceURI, targetRegion, targetRegion); } return null; } /** * @return <code>VariableInitializationCS</code> or <code>ParameterDeclarationCS</code> if successfully * resolve, <code>null</code> otherwise. */ public static CSTNode resolveVariableDeclaration(SimpleNameCS nameCS) { if(nameCS.eContainer() instanceof VariableExpCS) { ASTNode varExpNodeAS = ASTBindingHelper.resolveASTNode(nameCS); if(varExpNodeAS instanceof VariableExp) { VariableExp variableExp = (VariableExp) varExpNodeAS; Variable<EClassifier, EParameter> var = variableExp.getReferredVariable(); if(var != null) { if(var.getRepresentedParameter() != null) { EParameter param = var.getRepresentedParameter(); if(param instanceof VarParameter) { // resolve operation parameter reference VarParameter varParam = (VarParameter) param; CSTNode paramCS = ASTBindingHelper.resolveCSTNode(varParam); if(paramCS instanceof ParameterDeclarationCS) { ParameterDeclarationCS paramDeclCS = (ParameterDeclarationCS) paramCS; return paramDeclCS; } } } CSTNode cstVarNode = ASTBindingHelper.resolveCSTNode(var); if(cstVarNode instanceof VariableInitializationCS) { // resolve declared variable VariableInitializationCS varDecl = (VariableInitializationCS) cstVarNode; return varDecl; } else if(cstVarNode instanceof VariableCS) { return cstVarNode; } } } } else if(nameCS.eContainer() instanceof ParameterDeclarationCS) { return (ParameterDeclarationCS) nameCS.eContainer(); } else if(nameCS.eContainer() instanceof TypeSpecCS) { // model extent qualifier used with type TypeSpecCS typeSpecCS = (TypeSpecCS) nameCS.eContainer(); if(nameCS != typeSpecCS.getSimpleNameCS()) { return null; } ModelParameter modelParam = lookupModelParameter(getEnv(nameCS), nameCS.getValue()); if(modelParam != null) { return ASTBindingHelper.resolveCSTNode(modelParam, CSTNode.class); } } return null; } private static QvtOperationalEnv getEnv(CSTNode node) { return (QvtOperationalEnv)CSTHelper.getEnvironment(node); } private static ModelParameter lookupModelParameter(QvtOperationalEnv env, String paramName) { if(env.getModuleContextType() instanceof OperationalTransformation == false) { return null; } OperationalTransformation module = (OperationalTransformation) env.getModuleContextType(); for (ModelParameter nextParam : module.getModelParameter()) { if(paramName.equals(nextParam.getName())) { return nextParam; } } return null; } }