我使用Rascal来分析Eclipse Java项目并识别此项目中的类依赖项。更确切地说:当且仅当类A具有(1)使用类型B的参数或(2)使用类型B的局部变量的方法时,类A依赖于类B.这里,我只对依赖感兴趣关系A - > B,其中A和B在我的项目中都是两个类,并且都是不同的类。我已经从我的Eclipse项目创建了一个M3模型,并且能够使用以下内容识别所需的参数(类型B):
{ <e.name, f> | e <- model@declarations, e.name.scheme == "java+parameter", f <- model@typeDependency[e.name], !(/java/ := f.path), f.scheme != "java+primitiveType" }
在这里,我获取了我的M3模型的所有声明,过滤参数并使用@typeDependency
注释我检索相应的类型(我不知道如何操纵我在使用{{1}时获得的信息而不是)。最后,我使用最后两个语句来过滤掉类型与项目中的类无关的所有参数,如String和Integer参数。由于我对Rascal很陌生,我想不出另一种方法来实现这一点。
我现在的问题是:如何为我的项目检索B类型的局部变量?使用方案@types
与"java+variable"
结合使用是不够的,因为这还包括Iterator或String类型的变量,它们与我项目中的其他类有依赖关系,我对这些类型的变量不感兴趣。而且,结果集包含像
@typeDependency
其中B b = field.method();
是该类中的全局变量。因此,从field
到类本身存在类型依赖关系,我也希望从我的结果中排除这些依赖关系。所以,我相信b
并没有向我提供我需要的信息。
我发现this related post似乎用Rascal处理局部变量,但它使用AST而不是M3。我不确定如何在这个设置中使用AST(就像我说的,我只是Rascal的初学者)并且想知道是否可以用M3完成。我该怎么办?
编辑:为了清楚我想要达到的目标,我将举一个小例子。假设我的项目有两个类@typeDependency
和A
,而B
包含一些方法(B
,methodB1
,...)。
此外,类methodB2
具有以下结构:
A
我希望能够检索的变量是class A {
void methodA1(){
B importantVar;
importantVar.methodB1();
...
String someVar1 = importantVar.methodB2();
int someVar2 = importantVar.methodB3();
}
void methodA2(){
A someVar3;
...
}
}
,因为它是一个局部变量,它的类型为importantVar
(我的项目中的一个类)。我对B
和someVar1
不感兴趣,因为它们是具有与我的项目无关的类型的局部变量。在我之前为参数提供的代码示例中,我使用最后两个语句过滤掉了这些类型。此外,我对someVar2
也不感兴趣,因为它具有类型someVar3
并且出现在同一个类中。
我认为我应该能够使用A
检索我想要的局部变量,但我不确定如何。使用@types
时,我得到@types
,我已经查看了此数据类型的定义,以了解如何操作它。 TypeSymbol
中的大多数数据类型都有一个名为TypeSymbol
的位置,我知道如何操作它。但问题是,我还收到了一些没有此位置的类型,例如decl
和\int()
。在这些情况下,位置\array(..)
未定义。
答案 0 :(得分:3)
如果您只想分析特定的TypeSymbol
,请使用模式匹配。这是一个例子。
TypeSymbol t;
if (class(l,_) := t) {
println(l);
}
或理解
{ l | <_,class(l,_)> <- m3@types};
或作为理解中查找的一部分:
{ <v, l> | <_,v> <- m3@containment, isVariable(v), class(l,_) <- m3@types[v]};
答案 1 :(得分:1)
您可以使用M3模型中的containment
关系。所有局部变量都在declarations
关系中声明,但它们也出现在containment
中。如果您想获取方法m
中的所有变量,可以查看containment[m]
并过滤java+variable
方案。
有趣的角落情况是指方法包含匿名类。如果需要过滤嵌套变量,则需要在containment
中进一步查看(如传递闭包)
匿名嵌套类。
顺便说一下,M3模型有实用谓词isVariable
,isClass
等,还有classes(M3)
等。