package csep.example.cake.scoping;
import java.util.Collections;
import java.util.List;
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.eclipse.xtext.scoping.IScopeProvider;
import com.google.inject.Inject;
/**
* When {@link LinkingServiceWithNode.getLinkedObjects} is called, an {@link INode} instance is provided so we can calculate the name of the referred variable.
* The problem is that the call to getScope doesn't pass that node,
* so the underlying scopingprovider has no way to get that name.
* XXX: This is a hack to solve this problem.
* @author adam
*
*/
public class LinkingServiceWithNode extends DefaultLinkingService {
@Inject
private IQualifiedNameConverter qualifiedNameConverter;
private INode linkNode;
/**
* Basically a copy of super, only linkNode is remembered before calling getScope
*/
public List<EObject> getLinkedObjects(EObject context, EReference ref, INode node)
throws IllegalNodeException {
final EClass requiredType = ref.getEReferenceType();
if (requiredType == null)
return Collections.<EObject> emptyList();
final String crossRefString = getCrossRefNodeAsString(node);
if (crossRefString != null && !crossRefString.equals("")) {
linkNode = node;
final IScope scope = getScope(context, ref);
linkNode = null;
QualifiedName qualifiedLinkName = qualifiedNameConverter.toQualifiedName(crossRefString);
IEObjectDescription eObjectDescription = scope.getSingleElement(qualifiedLinkName);
if (eObjectDescription != null)
return Collections.singletonList(eObjectDescription.getEObjectOrProxy());
}
return Collections.emptyList();
}
/**
* Mostly a copy of super
*/
protected IScope getScope(EObject context, EReference reference) {
IScopeProvider scopeProvider = getScopeProvider();
if (scopeProvider == null)
throw new IllegalStateException("scopeProvider must not be null.");
try {
registerImportedNamesAdapter(context);
if (scopeProvider instanceof IScopeProviderWithNode) {
((IScopeProviderWithNode)scopeProvider).setNode(linkNode);
}
return scopeProvider.getScope(context, reference);
} finally {
unRegisterImportedNamesAdapter();
}
}
}