Xtext 中的交叉引用非常慢。我该如何改进它?

Cross referencing in Xtext is very slow. How do i improve it?

这是对论坛中提到的问题的延续: .

我使用的示例模型如下

grammar org.xtext.example.testdsl.TestDsl with org.eclipse.xtext.common.Terminals
generate testDsl "http://www.test.com/test/example/TestDsl"

Model:
prog+=Program*;

Program: g=Greeting  de+=DataEntry* s+=Statement*;
Greeting: 'Hello' t=ProgPara '!';
ProgPara: 'PROGRAM'  pname=Progname ';';
Progname : name=ID;

DataEntry:  a=INT (v=Varname| in=Indexname) ';';   
Varname : name = ID;

Statement: c=CopyStmt ';';
CopyStmt: 'COPY' 'TO' qname=[IndexVarname|ID] ;
IndexVarname : (Indexname|Varname);   
Indexname : '(' name = ID ')';

Named:Progname|Indexname|Varname;

我有一个使用类似语法的文件,这个文件相当大,有大约 12000 行代码和 2000 个奇怪的 Progname 或 Varname,并且在每个实例中它都试图解析范围提供程序中的类型。语法中大约有 326 个元素。

 val candidates1 = EcoreUtil2.getAllContentsOfType(rootElement, Indexname);
 val candidates2 = EcoreUtil2.getAllContentsOfType(rootElement, Varname);
 val candidates = candidates1 + candidates2;
 return Scopes.scopeFor(candidates);

由于重复调用 getScope(),该文件将永远无法在编辑器中打开。即使打开任何小的编辑也太慢了。请建议我如何解决这个问题。

我尝试为上述代码添加缓存支持,如下所示:

class TestDslScopeProvider extends AbstractTestDslScopeProvider {
  @Inject
    IResourceScopeCache cache;

  override getScope(EObject context, EReference reference) {
    if (context instanceof CopyStmt) {
        if (reference.featureID == TestDslPackage.COPY_STMT__QNAME) {
            val candidates = cache.get(
                context,
                reference.eResource,
                [|findQNameCandidates(context, reference)]
            );
            return Scopes.scopeFor(candidates);
        }   
      }
      return super.getScope(context, reference);        
  }

  def findQNameCandidates(EObject context, EReference reference) {
    val rootElement = EcoreUtil2.getRootContainer(context);
    val candidates1 = EcoreUtil2.getAllContentsOfType(rootElement, Indexname);
    val candidates2 = EcoreUtil2.getAllContentsOfType(rootElement, Varname);
    return candidates1 + candidates2;
  }
}

到现在还是很慢。没有区别。如果我用引用对象替换上下文作为缓存的键,那么速度很快但是所有交叉引用的链接都丢失了并且我得到了错误。我无法指出我哪里做的不对。

谢谢,
安妮莎

以下适合我

@Inject
IResourceScopeCache cache;

override getScope(EObject context, EReference reference) {
    if (context instanceof CopyStmt) {
        if (reference.featureID == MyDslPackage.COPY_STMT__QNAME) {
            val candidates = cache.get(
                "COPY_STMT__QNAME_scope",
                context.eResource,
                [|findQNameCandidates(context, reference)]
            );
            return Scopes.scopeFor(candidates);
        }
    }
    return super.getScope(context, reference);
}

def findQNameCandidates(EObject context, EReference reference) {
    val rootElement = EcoreUtil2.getRootContainer(context);
    val candidates1 = EcoreUtil2.getAllContentsOfType(rootElement, IndexVarname);
    return candidates1;
}