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

IResourceScopeCache for Avoid expensive scope calculation

我遇到了与 is this link

描述的相同问题

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

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 个不同的案例。

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

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

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

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

根据您论坛中的代码示例 post 我看不到很好的缓存候选者。但也许有一些我从这个例子中看不到的东西。

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

  1. 块和语句没有可用于缓存键的名称。
  2. 即使您这样做,局部变量也只能在声明后在 expressions/statements 中使用,因此每个语句可能有一组不同的可用局部变量。这使得通过合理的努力实现合理的重用变得更加困难。

如果您无论如何都想这样做,也许您可​​以使用语句在包含层次结构中的位置来计算缓存键,类似于代理 URI 片段(参见 org.eclipse.xtext.linking.lazy.LazyURIEncoder),但不使用字符串,并且重新使用前面语句的计算值(以及块的第一条语句的包含块)。