IResourceScopeCache用于避免昂贵的范围计算

时间:2016-09-28 13:21:48

标签: xtext scoping

我遇到了与is this link

相同的问题

我想在我实现的getScope函数中使用IResourceScopeCache,但我不知道该怎么做。没找到任何帮助我的东西。 我有这个文件:我在那里覆盖getScope()的MyDslScopeProvider.xtend。 我如何在那里使用缓存?

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);

}

我有3种不同的情况。

1 个答案:

答案 0 :(得分:2)

接口IResourceScopeCache允许使用您选择的键在地图中存储为给定资源计算的值。 它有两种方法:<T> T get(Object key, Resource res, Provider<T> provider)void clear(Resource res)get检查是否已为给定的密钥和资源计算了值。如果它已经存在,则返回缓存的值,否则使用提供程序计算该值,然后将该值存储在缓存中以供后续重用。 clear删除给定键的计算值(如果存在)。

您必须注入IResourceScopeCache类型的字段,并考虑从上下文EObject生成缓存键的方案:

您必须确保无论何时检索给定缓存键和资源的值,如果计算实际执行,缓存计算的结果(provider)都是相同的,因此它是正确的重用缓存的值。特别是,您必须确保计算结果仅取决于传递给get方法的资源的内容,因为缓存的值仅在更改资源时重新计算。

然而,在执行此操作时,您必须确保不必要地使用不同的缓存键,其中计算结果必须相同,以便最大限度地重复使用并最大限度地减少重复计算。

从论坛帖子中的代码示例中,我看不到非常好的缓存候选者。但也许我可以从这个例子中看到一些东西。

局部变量不是缓存的最佳候选者,至少有两个原因:

  1. 块和语句没有可用于缓存键的名称。
  2. 即使你这样做,局部变量只能在声明后的表达式/语句中使用,因此每个语句可能有一组不同的可用局部变量。这使得通过合理的努力来实现合理的重用量变得更加困难。
  3. 如果你想要这样做,也许你可以使用语句&#39;来计算缓存密钥。在包含层次结构中的位置,类似于代理URI片段(参见org.eclipse.xtext.linking.lazy.LazyURIEncoder),但不使用字符串,并重用前面语句的计算值(并包含第一个的块)块的陈述)。