2016-09-26 21 views
0

我想自定義範圍界定如下:XTEXT:自定義作用域有效的方式

在擴展AbstractMyDslScopeProvider文件MyDslScopeProvider, 我實現了這個簽名的功能:

override def IScope getScope(EObject context, EReference reference) 

,我用例像這樣

​​

但我在我的語法中有函數,它有參數,我們可以聲明在本地v ARS。我不希望那些本地變量和函數的參數是從外部可見,我想他們是隻有內部功能,所以我做了這樣的事情可見:

 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

您能分享完整的代碼嗎?我不明白你想要刪除的元素最終如何在'EObjectsInScope'中結束。 –

回答

0

編輯:您可能也有興趣在我的回答"Xtext: IResourceScopeCache for Avoid expensive scope calculation"

首先,如果你談論的是局部變量,你可能不希望允許使用本地變量的聲明之前,例如

function foo() { 
    x = x + 1; 
    int x = 0; 
} 

所以你實際上是通過使用getAllContentsOfType()做了太多的工作。

你究竟在嘗試使用優化來達到什麼目的?更好的內容功能幫助內部功能?對於具有小型功能機構的大量模型,速度更快?許多大型功能的速度更快?

請記住,以避免過早優化 - 保持代碼可維護性更重要,並且僅在速度不能擴展到實際需要處理的工作負載時優化速度。你使用探查器來尋找熱點嗎?當涉及到性能瓶頸時,人類的直覺可能會非常錯誤。

無論如何,假設你需要提高範圍界定的速度,但你沒有大量的工作量,作爲第一個鏡頭,我建議使用TreeIterator來遍歷收集應該是局部變量的函數體可見的,以及使用EcoreUtil2.getAllContainers(context)的返回值作爲使用prune()和何時使用next()的指導。

I.e.

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循環中。