我尝试像这样定制范围:
在扩展AbstractMyDslScopeProvider的文件MyDslScopeProvider中, 我使用此签名实现了该功能:
override def IScope getScope(EObject context, EReference reference)
我用过这样的案例
if (reference == SpectraPackage.Literals.SOMETHING__POINTER)
但我的语法功能是它有参数,我们可以在本地变量中声明。我不希望那些局部变量和该函数的参数从外部可见,我希望它们只在函数内部可见,所以我做了类似的事情:
if (contextDecl instanceof function) {
val fun= contextDecl as function
val allContentsCurrFile = EcoreUtil2.getAllContentsOfType(fun,Constant)
EObjectsInScope.addAll(fun.params)
EObjectsInScope.addAll(allContentsCurrFile)
return Scopes.scopeFor(EObjectsInScope)
}
else{
val removeEobjects = newArrayList()
EObjectsInScope.addAll(EcoreUtil2.getAllContentsOfType(root,EObject))
val funList= EcoreUtil2.getAllContentsOfType(root,function) as List<function>
for(function f: funList){
removeEobjects.addAll(f.varDeclList)
removeEobjects.addAll(f.params.params)
removeEobjects.addAll(EcoreUtil2.getAllContentsOfType(f,Constant))
}
EObjectsInScope.removeAll(removeEobjects)
return Scopes.scopeFor(EObjectsInScope)
这对于获取所有EObject并删除我不希望从外部可见的变量(这需要花费很多时间)非常低效。 有一种方法可以提高效率吗? 感谢。
答案 0 :(得分:0)
编辑:您可能对我对"Xtext: IResourceScopeCache for Avoid expensive scope calculation"
的回答感兴趣首先,如果你在谈论局部变量,你可能不希望在声明它们之前允许使用局部变量,例如。
function foo() {
x = x + 1;
int x = 0;
}
所以你实际上是通过使用getAllContentsOfType()做了太多工作。
您正在尝试使用优化实现什么目标?在功能内部提供更好的内容辅助性能?具有小功能体的大量型号的速度更快?许多大型功能的速度更快?
请记住避免过早优化 - 保持代码可维护性更为重要,并且只有在不能扩展到实际需要处理的工作负载时才能优化速度。您是否使用分析器查找热点?在性能瓶颈方面,人的直觉可能是非常错误的。
无论如何,假设您需要提高作用域的速度,但是您没有大量的工作负载,作为第一个镜头,我建议使用TreeIterator遍历函数体,收集应该可见的局部变量,并使用EcoreUtil2.getAllContainers(context)的返回值作为何时使用prune()以及何时使用next()的指南。
即。
import static extension org.eclipse.xtext.EcoreUtil2.*
// ...
val predecessors = new ArrayList<EObject>
val iterator = EcoreUtils.getAllContents(function, true)
// Could be optimized further
val descentGuide = context.allContainers.dropWhile[it != function].toList.reverseView.iterator
var current = iterator.next
var nextDescent = descentGuide.next
while(current != context) {
// collect list with local variables here
predecessors += current
if(current == nextDescent) {
// Reached another ancestor of context - will look for the following ancestor next
nextDescent = descentGuide.next
} else {
iterator.prune
}
current = iterator.next
}
// Reverse so innermost declarations shadow outer declarations
val localVariables = predecessors.filter(LocalVariableDeclaration).toList.reverseView
我没有编译/测试代码,但我希望这个想法变得清晰。
while循环应该在最后终止,因为在某些时候,将会到达context
- 但为了更加健壮,将&& iterator.hasNext
添加到while循环可能是有意义的。