/******************************************************************************* * Copyright (c) 2010, 2015 Willink Transformations 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: * E.D.Willink - initial API and implementation *******************************************************************************/ package org.eclipse.ocl.xtext.essentialocl.attributes; import java.util.List; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EObject; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.ocl.pivot.CollectionType; import org.eclipse.ocl.pivot.IterateExp; import org.eclipse.ocl.pivot.LoopExp; import org.eclipse.ocl.pivot.OCLExpression; import org.eclipse.ocl.pivot.PivotPackage; import org.eclipse.ocl.pivot.Type; import org.eclipse.ocl.pivot.Variable; import org.eclipse.ocl.pivot.internal.manager.PivotMetamodelManager; import org.eclipse.ocl.pivot.internal.scoping.AbstractAttribution; import org.eclipse.ocl.pivot.internal.scoping.EnvironmentView; import org.eclipse.ocl.pivot.internal.scoping.ScopeView; import org.eclipse.ocl.pivot.utilities.PivotUtil; import org.eclipse.ocl.xtext.essentialoclcs.AbstractNameExpCS; import org.eclipse.ocl.xtext.essentialoclcs.ExpCS; import org.eclipse.ocl.xtext.essentialoclcs.InfixExpCS; import org.eclipse.ocl.xtext.essentialoclcs.NavigatingArgCS; import org.eclipse.ocl.xtext.essentialoclcs.NavigationRole; import org.eclipse.ocl.xtext.essentialoclcs.RoundBracketedClauseCS; public class NavigatingArgCSAttribution extends AbstractAttribution { public static final @NonNull NavigatingArgCSAttribution INSTANCE = new NavigatingArgCSAttribution(); @Override public ScopeView computeLookup(@NonNull EObject target, @NonNull EnvironmentView environmentView, @NonNull ScopeView scopeView) { NavigatingArgCS fromArgument = (NavigatingArgCS)target; NavigationRole role = fromArgument.getRole(); RoundBracketedClauseCS csRoundBracketedClause = fromArgument.getOwningRoundBracketedClause(); AbstractNameExpCS targetElement = csRoundBracketedClause.getOwningNameExp(); assert targetElement != null; InfixExpCS csNavigationOperator = NavigationUtil.getNavigationInfixExp(targetElement); OCLExpression pivot = PivotUtil.getPivot(OCLExpression.class, targetElement); // NB QVTr's RelationCallExp is not a CallExp if (pivot instanceof LoopExp) { // FIXME This is null for nested iteration if (role == NavigationRole.EXPRESSION) { for (Variable iterator : ((LoopExp)pivot).getOwnedIterators()) { if (iterator.isIsImplicit()) { environmentView.addElementsOfScope(iterator.getType(), scopeView); } else { environmentView.addNamedElement(iterator); } if (environmentView.hasFinalResult()) { return null; } } if (pivot instanceof IterateExp) { Variable result = ((IterateExp)pivot).getOwnedResult(); if (result.isIsImplicit()) { environmentView.addElementsOfScope(result.getType(), scopeView); } else { environmentView.addNamedElement(result); } if (environmentView.hasFinalResult()) { return null; } } } else if (role == NavigationRole.ITERATOR) { // Happens during save List<Variable> iterators = ((LoopExp)pivot).getOwnedIterators(); assert iterators != null; environmentView.addNamedElements(iterators); } else if (role == NavigationRole.ACCUMULATOR) { Variable result = ((IterateExp)pivot).getOwnedResult(); if (result != null) { environmentView.addNamedElement(result); } } } else if (pivot != null) { // OperationCallExp } else { // No pivot resolved yet if (role == NavigationRole.EXPRESSION) { // // Challenges: // for x->select(oclIsKindOf(T)) must accept both T as a type (and as a source property) // for x->select(something(T)) must accept both T as a source property (and as a type) // if ((csNavigationOperator != null) && PivotUtil.isAggregateNavigationOperator(csNavigationOperator.getName())) { ExpCS csSource = csNavigationOperator.getSource(); OCLExpression source = PivotUtil.getPivot(OCLExpression.class, csSource); if (source != null) { Type type = source.getType(); Type elementType; CollectionType collectionType; PivotMetamodelManager metamodelManager = environmentView.getEnvironmentFactory().getMetamodelManager(); if (type instanceof CollectionType) { // collection->collection-operation(name... collectionType = (CollectionType)type; elementType = collectionType.getElementType(); ExpCS csArgument = csNavigationOperator.getArgument(); assert csArgument == targetElement; } else { elementType = type; collectionType = metamodelManager.getStandardLibrary().getSetType(); } if (NavigationUtil.isIteration(metamodelManager, csRoundBracketedClause, collectionType)) { if (environmentView.accepts(PivotPackage.Literals.TYPE)) { EClassifier requiredType = environmentView.getRequiredType(); try { environmentView.setRequiredType(PivotPackage.Literals.TYPE); environmentView.computeLookups(scopeView.getParent().getParent().getParent()); } finally { environmentView.setRequiredType(requiredType); } } environmentView.addElementsOfScope(elementType, scopeView); if (environmentView.hasFinalResult()) { // If we found a type return null; // but look no further for variables } } } } } } if (csNavigationOperator != null) { return scopeView.getParent().getParent().getParent().getParent(); // Leapfrog over RoundBracketedClauseCS, InvocationExpCS and its source operator } else { return scopeView.getParent().getParent().getParent(); // Leapfrog over RoundBracketedClauseCS, InvocationExpCS } } }