问题
I have the same problem that described is this link
I want to use IResourceScopeCache in my getScope function I implemented, but I don't know how to do it. Didn't found anything that helped me. I have this file: MyDslScopeProvider.xtend that I override getScope() there. How can I use the cache there?
override def IScope getScope(EObject context, EReference reference) {
if (reference == SpectraPackage.Literals.TEMPORAL_PRIMARY_EXPR__POINTER) {
val contextDecl = EcoreUtil2.getContainerOfType(context, Decl);
val root = EcoreUtil2.getContainerOfType(context, Model)
val elements = root.elements
val List<EObject> EObjectsInScope = newArrayList
if (contextDecl instanceof Predicate) {
val pred = contextDecl as Predicate
EObjectsInScope.addAll(pred.params.params)
EObjectsInScope.addAll(consts)
EObjectsInScope.addAll(varDecls)
return Scopes.scopeFor(EObjectsInScope)
}
else if (contextDecl instanceof Pattern) {
val patt = contextDecl as Pattern
EObjectsInScope.addAll(patt.varDeclList)
EObjectsInScope.addAll(patt.params.params)
return Scopes.scopeFor(EObjectsInScope)
}
else{
//geting all the elements I need.(didn't added it here because it's a lot of code)
return Scopes.scopeFor(EObjectsInScope)
}
return Scopes.scopeFor(EObjectsInScope)
}
}
return super.getScope(context, reference);
}
I have 3 different cases.
回答1:
The interface IResourceScopeCache
allows to store values computed for a given resource in a map using keys of your choice.
It has two methods: <T> T get(Object key, Resource res, Provider<T> provider)
and void clear(Resource res)
.
get
checks whether a value was already computed for the given key and resource. If it is already present, the cached value is returned, and otherwise the provider is used to calculate the value, which then is stored in the cache for subsequent re-use. clear
removes the computed value for the given key, if present.
You have to inject a field of type IResourceScopeCache and think about a scheme to generate cache keys from the context EObject:
You have to make sure that whenever you retrieve the value for a given cache key and resource, the results of the cache computation (provider
) would be identical if the computation was actually performed, so it is correct to re-use the cached values. Especially, you have to make sure that the result of the computation depends only on the contents of the resource you pass to the get
method because the cached values are only re-computed when that resource is changed.
However, while doing that, you have to make sure that you don't unnecessarily have different cache keys where the computation results are bound to be identical, in order to maximize re-use and minimize duplicate computations.
From the code example in your forum post I cannot see very good candidates for caching. But maybe there is something I can't see from the example.
Local variables are not the best candidates for caching for at least two reasons:
- Blocks and statements don't have names you could use for cache keys.
- Even if you do that, local variables are only available for use in expressions/statements after their declaration, so every statement might have a different set of available local variables. This makes it harder to achieve a reasonable amount of reuse with a reasonable amount of effort.
If you want to do it anyway, maybe you could calculate cache keys using the statements' position in the containment hierarchy, similar to proxy URI fragments (cf. org.eclipse.xtext.linking.lazy.LazyURIEncoder), but not using strings, and re-use the computed valued of the preceding statements (and containing blocks for the first statement of a block).
来源:https://stackoverflow.com/questions/39748810/iresourcescopecache-for-avoid-expensive-scope-calculation