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;
}
这是对论坛中提到的问题的延续:
我使用的示例模型如下
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;
}