All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright (c) 2008 itemis AG (http://www.itemis.eu) 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
 *
 *******************************************************************************/
package org.eclipse.xtext.scoping.impl;

import java.lang.reflect.Method;
import java.util.Collections;

import org.apache.log4j.Logger;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.IScopeProvider;
import org.eclipse.xtext.util.PolymorphicDispatcher;

import com.google.common.base.Predicate;
import com.google.inject.Inject;
import com.google.inject.name.Named;

/**
 * A scope provider that invokes methods reflectively.
 * 
 * At first it looks for methods of the following signature:
 * 
 * IScope scope_[EClassName]_[EReferenceName](MyType context, EReference ref)

*
* * That is if {@link #getScope(EObject, EReference)} is called where EReference is e.g. Property.type and * the ctx is an instance of Property, than the corresponding signature could be:

* IScope scope_Property_type(Property prop, EReference ref)

*
* * If there is no method with the given name and a first parameter type which is compatible to the actual context * object, the implementation invokes {@link #getPredicate(EObject, EReference)} for the eContainer of the context * EObject. For instance of a Property resides in an Entity the {@link #getScope(EObject, EReference)} would be called * for the containing Entity. This is done as long as there is an eContainer.
* If after walking up the containment hierarchy no suitable scoping declaration has been found, the implementation * falls back to invoke methods with the following signature (computed by {@link #getPredicate(EObject, EClass)}):

* * IScope scope_[EClassName](MyType context, EReference ref)

*
* * For instance if a scope provider is asked to return all Entities which are visible from a certain Property, it looks * for a method like this:

* IScope scope_Entity(Property property, EReference ref)

*
Again the first parameter can also be any super type of the actual type and the * implementation walks up the containment hierarchy again.

* * If still no method could be found null is returned * * @author Sven Efftinge - Initial contribution and API * @author Sebastian Zarnekow */ public abstract class AbstractDeclarativeScopeProvider extends AbstractScopeProvider implements IDelegatingScopeProvider { public final static String NAMED_DELEGATE = "org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider.delegate"; public final static String NAMED_ERROR_HANDLER = "org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider.errorHandler"; public final Logger logger = Logger.getLogger(getClass()); @Inject @Named(NAMED_DELEGATE) private IScopeProvider delegate; protected IScope delegateGetScope(EObject context, EReference reference) { return getDelegate().getScope(context, reference); } public void setDelegate(IScopeProvider delegate) { this.delegate = delegate; } public IScopeProvider getDelegate() { return delegate; } @Inject(optional=true) @Named(NAMED_ERROR_HANDLER) private PolymorphicDispatcher.ErrorHandler errorHandler = new PolymorphicDispatcher.NullErrorHandler(); protected Predicate getPredicate(EObject context, EClass type) { String methodName = "scope_" + type.getName(); return PolymorphicDispatcher.Predicates.forName(methodName, 2); } protected Predicate getPredicate(EObject context, EReference reference) { String methodName = "scope_" + reference.getEContainingClass().getName() + "_" + reference.getName(); return PolymorphicDispatcher.Predicates.forName(methodName, 2); } public IScope getScope(EObject context, EReference reference) { IScope scope = polymorphicFindScopeForReferenceName(context, reference); if (scope == null) { scope = polymorphicFindScopeForClassName(context, reference); if (scope == null) { scope = delegateGetScope(context, reference); } } return scope; } protected IScope polymorphicFindScopeForClassName(EObject context, EReference reference) { IScope scope = null; PolymorphicDispatcher dispatcher = new PolymorphicDispatcher( Collections.singletonList(this), getPredicate(context, reference.getEReferenceType()), errorHandler) { @Override protected IScope handleNoSuchMethod(Object... params) { if (PolymorphicDispatcher.NullErrorHandler.class.equals(errorHandler.getClass())) return null; return super.handleNoSuchMethod(params); } }; EObject current = context; while (scope == null && current != null) { scope = dispatcher.invoke(current, reference); current = current.eContainer(); } current = context; while (scope == null && current != null) { scope = dispatcher.invoke(current, reference.getEReferenceType()); if (scope!=null) logger.warn("scope_(EObject,EClass) is deprecated. Use scope_(EObject,EReference) instead."); current = current.eContainer(); } return scope; } protected IScope polymorphicFindScopeForReferenceName(EObject context, EReference reference) { Predicate predicate = getPredicate(context, reference); PolymorphicDispatcher dispatcher = new PolymorphicDispatcher(Collections .singletonList(this), predicate, errorHandler) { @Override protected IScope handleNoSuchMethod(Object... params) { if (PolymorphicDispatcher.NullErrorHandler.class.equals(errorHandler.getClass())) return null; return super.handleNoSuchMethod(params); } }; EObject current = context; IScope scope = null; while (scope == null && current != null) { scope = dispatcher.invoke(current, reference); current = current.eContainer(); } return scope; } public void setErrorHandler(PolymorphicDispatcher.ErrorHandler errorHandler) { this.errorHandler = errorHandler; } public PolymorphicDispatcher.ErrorHandler getErrorHandler() { return errorHandler; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy