Hierarchic (java-like) scoping [message #704206] |
Thu, 28 July 2011 11:36 |
Julien Bigot Messages: 26 Registered: July 2009 |
Junior Member |
|
|
Hi, I'm trying to get a java-like nested scoping to work.
That is, having blocks inside each others with elements hiding and shadowing.
block {
var v1 = CST;
block {
var v2 = v1;
}
var v3 = v2; // error, v2 is hidden
block {
var v2 = CST;
var v3 = v2; // shadow upper v3, v2 is unambiguous since the other v2 is hidden
}
}
Right now I'm working on single file instances, so I have no problem of classpath or importURI and I have no notion of named namespace or namespace import so it seems to me this is a rather simple case.
What I have done is create a new ResourceDescriptionStrategy that only exposes the top level declarations, that is it only enters the top level element and only accepts declarations ... rather straightforward.
public class HlaResourceDescriptionStrategy extends DefaultResourceDescriptionStrategy {
public boolean createEObjectDescriptions(EObject eObject, IAcceptor<IEObjectDescription> acceptor) {
if (eObject instanceof Declaration)
super.createEObjectDescriptions(eObject, acceptor);
return eObject instanceof HlaModel;
}
}
However when it comes to the LocalScopeProvider, I dont get what the right implementation is.
I started with a SimpleLocalScopeProvider, however it seems to have no support for nested block hiding/shadowing. From what I understand, it returns (resource scope)->(global scope) where the resource scope contains every named element of the current resource.
So I switched to ImportedNamespaceAwareLocalScopeProvider. Even if I don't have namespace imports, the blocks are (anonymous) namespaces so it makes sense. However, once again I have a problem. from what I understand, it returns (block scope)->...->(block scope)->(resource scope)->(global scope).However, once again, a block scope ionly supports namespace imports, either explicit (I don't have any) or implicit in the case of named blocks.
Once again, the resource scope contains each and every named elements of the current resource with no notion of nesting.
I investigated using a QualifiedNameProvider instead of a SimpleNameProvider but that does not solve the problem of anonymous blocks.
So I guess the conclusion of all that is that I will have to implement my own LocalScopeProvider. It sounds to me like I'm doing a mistake as I am surprised that nested scopes is not part of the common ground supported by xtext.
However, if I have to do it, what would be the right way ?
I see at list two options:
- inherit from AbstractGlobalScopeDelegatingScopeProvider and somehow delegate to AbstractGlobalScopeDelegatingScopeProvider if I want to add namespaces;
- or inherit from AbstractGlobalScopeDelegatingScopeProvider
[Updated on: Thu, 28 July 2011 11:37] Report message to a moderator
|
|
|
|
Re: Hierarchic (java-like) scoping [message #705180 is a reply to message #705171] |
Fri, 29 July 2011 14:39 |
Julien Bigot Messages: 26 Registered: July 2009 |
Junior Member |
|
|
I came up with a distinct solution involving nested IScopes. I don't know if it's the way it's expected to be done but ...
Regarding your memory leak problem, you can solve it by replacing your Hashtable by a java.util.WeakHashMap I guess.
package fr.inria.graal.hlcm.scoping;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.xtext.naming.IQualifiedNameProvider;
import org.eclipse.xtext.resource.ISelectable;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.Scopes;
import org.eclipse.xtext.scoping.impl.AbstractGlobalScopeDelegatingScopeProvider;
import org.eclipse.xtext.scoping.impl.MultimapBasedSelectable;
import org.eclipse.xtext.scoping.impl.SelectableBasedScope;
import org.eclipse.xtext.util.IResourceScopeCache;
import org.eclipse.xtext.util.Tuples;
import com.google.inject.Inject;
import com.google.inject.Provider;
public class HlaScopeProvider extends AbstractGlobalScopeDelegatingScopeProvider {
@Inject
private IQualifiedNameProvider qualifiedNameProvider;
@Inject
private IResourceScopeCache cache;
public void setCache(IResourceScopeCache cache) {
this.cache = cache;
}
public void setNameProvider(IQualifiedNameProvider nameProvider) {
this.qualifiedNameProvider = nameProvider;
}
protected IQualifiedNameProvider getNameProvider() {
return qualifiedNameProvider;
}
public IScope getScope(final EObject context, final EReference reference) {
IScope result = null;
if ( context.eContainer() != null ) {
result = getScope(context.eContainer(), reference);
} else {
result = getGlobalScope(context.eResource(), reference);
}
result = createScope(result, context, reference);
return result;
}
protected IScope createScope(IScope parent, final EObject context, EReference reference) {
ISelectable contextContent = cache.get(Tuples.create(HlaScopeProvider.class.getName(), context, reference),
context.eResource(), new Provider<ISelectable>() {
public ISelectable get() {
return new MultimapBasedSelectable(Scopes.scopedElementsFor(context.eContents(), qualifiedNameProvider));
}
});
return SelectableBasedScope.createScope(parent, contextContent, reference.getEReferenceType(), isIgnoreCase(reference));
}
}
[Updated on: Fri, 29 July 2011 14:41] Report message to a moderator
|
|
|
Powered by
FUDForum. Page generated in 0.03932 seconds