|
@@ -0,0 +1,102 @@
|
|
|
+/**
|
|
|
+ * Copyright (c) 2018 committers of YAKINDU 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:
|
|
|
+ * committers of YAKINDU - initial API and implementation
|
|
|
+ *
|
|
|
+ */
|
|
|
+package org.yakindu.base.expressions.linking;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Optional;
|
|
|
+
|
|
|
+import org.eclipse.emf.ecore.EClass;
|
|
|
+import org.eclipse.emf.ecore.EObject;
|
|
|
+import org.eclipse.emf.ecore.EReference;
|
|
|
+import org.eclipse.xtext.linking.impl.DefaultLinkingService;
|
|
|
+import org.eclipse.xtext.linking.impl.IllegalNodeException;
|
|
|
+import org.eclipse.xtext.naming.IQualifiedNameConverter;
|
|
|
+import org.eclipse.xtext.naming.QualifiedName;
|
|
|
+import org.eclipse.xtext.nodemodel.INode;
|
|
|
+import org.eclipse.xtext.resource.IEObjectDescription;
|
|
|
+import org.eclipse.xtext.scoping.IScope;
|
|
|
+import org.yakindu.base.expressions.expressions.ArgumentExpression;
|
|
|
+import org.yakindu.base.expressions.expressions.ElementReferenceExpression;
|
|
|
+import org.yakindu.base.expressions.expressions.FeatureCall;
|
|
|
+import org.yakindu.base.types.Operation;
|
|
|
+import org.yakindu.base.types.TypesPackage;
|
|
|
+
|
|
|
+import com.google.common.collect.Iterables;
|
|
|
+import com.google.inject.Inject;
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ * Supports operation overloading
|
|
|
+ *
|
|
|
+ * @author andreas muelder - Initial contribution and API
|
|
|
+ *
|
|
|
+ */
|
|
|
+public class OperationOverloadingLinkingService extends DefaultLinkingService {
|
|
|
+
|
|
|
+ @Inject
|
|
|
+ private IQualifiedNameConverter qualifiedNameConverter;
|
|
|
+ @Inject
|
|
|
+ private OperationOverloadingResolver operationsLinker;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<EObject> getLinkedObjects(EObject context, EReference ref, INode node) throws IllegalNodeException {
|
|
|
+ if (context instanceof ArgumentExpression && isOperationCall(context)) {
|
|
|
+ return getLinkedOperation((ArgumentExpression) context, ref, node);
|
|
|
+ }
|
|
|
+ return super.getLinkedObjects(context, ref, node);
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<EObject> getLinkedOperation(ArgumentExpression context, EReference ref, INode node) {
|
|
|
+ final EClass requiredType = ref.getEReferenceType();
|
|
|
+ if (requiredType == null) {
|
|
|
+ return Collections.<EObject>emptyList();
|
|
|
+ }
|
|
|
+ final String crossRefString = getCrossRefNodeAsString(node);
|
|
|
+ if (crossRefString == null || crossRefString.equals("")) {
|
|
|
+ return Collections.<EObject>emptyList();
|
|
|
+ }
|
|
|
+ final IScope scope = getScope(context, ref);
|
|
|
+ final QualifiedName qualifiedLinkName = qualifiedNameConverter.toQualifiedName(crossRefString);
|
|
|
+ // Adoption to super class implementation here to return multi elements
|
|
|
+ final Iterable<IEObjectDescription> eObjectDescription = scope.getElements(qualifiedLinkName);
|
|
|
+ int size = Iterables.size(eObjectDescription);
|
|
|
+ if (size == 0)
|
|
|
+ return Collections.emptyList();
|
|
|
+ if (size == 1)
|
|
|
+ return Collections.singletonList(Iterables.getFirst(eObjectDescription, null).getEObjectOrProxy());
|
|
|
+ // Two operation with same name found here
|
|
|
+ List<IEObjectDescription> candidates = new ArrayList<>();
|
|
|
+ for (IEObjectDescription currentDescription : eObjectDescription) {
|
|
|
+ if (currentDescription.getEClass().isSuperTypeOf(TypesPackage.Literals.OPERATION)) {
|
|
|
+ candidates.add(currentDescription);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Optional<Operation> operation = operationsLinker.linkOperation(candidates, context);
|
|
|
+ if (operation.isPresent()) {
|
|
|
+ return Collections.singletonList(operation.get());
|
|
|
+ }
|
|
|
+ //Link to first operation to get parameter errors instead of linking errors
|
|
|
+ return Collections.singletonList(Iterables.getFirst(eObjectDescription, null).getEObjectOrProxy());
|
|
|
+ }
|
|
|
+
|
|
|
+ protected boolean isOperationCall(EObject context) {
|
|
|
+ if (context instanceof ElementReferenceExpression) {
|
|
|
+ return ((ElementReferenceExpression) context).isOperationCall();
|
|
|
+ }
|
|
|
+ if (context instanceof FeatureCall) {
|
|
|
+ return ((FeatureCall) context).isOperationCall();
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|