PsiClass Visitor

Hi

I am trying to build an analysis where I can detect which methods and variables from other classes a PsiClass uses using a visitor, namely JavaElementVisitor.

Suppose we have a class like Foo:

class Foo {

void compute() {
Bar bar = new Bar();
Baz baz = new Baz();
FooBar fooBar = new FooBar();

if (baz.someVariable > 10) {
bar.doSomething(fooBar.someOtherVariable);
}
}

}

In the above example, Foo uses Bar's doSomething method, Baz's someVariable as well as FooBar's someOtherVariable.

My current understanding is that I can detect the doSomething method call using the visitMethodCallExpression, and use resolveMethod to see where doSomething comes from.

However, I'm unsure about how I would detect either someVariable or someOtherVariable.

The closest I got is to identify that the baz.someVariable is a PsiReferenceExpression. It looks to me however that unlike a PsiMethodCallExpression which is only applicable to method calls, there's a whole cohort of expression which can be a PsiReferenceExpression. 

Thank you!

Radu

 

0
4 comments

Hi,

Your assumption is correct and references to the variables are represented as PsiReferenceExpressions. 

BTW you can use Tools | View PSI Structure of Current File... action to check how the text is represented in the PSI.

Anna

0
Avatar
Permanently deleted user

Hi Anna,

Thank you for your confirmation.

Yes, I use PsiViewer to analyse PsiTree structure, that's how I got to notice the abundance of PsiReferenceExpressions which is why I was slightly confused.

Having played around a little bit, I've narrowed my specific variable lookup to something that looks roughly like this

void visitReferenceExpression(PsiReferenceExpression expression) {
if (!expression.isQualified) return;

PsiElement expressionParent = expression.parent();
if (expressionParent instanceof PsiReferenceExpression) return;

PsiElement expressionSource = expression.resolve();
if (!(expressionSource instanceof PsiField)) return;

// get class of the PsiField etc.
}

Expression must be qualified as I am only interested in variables of other classes, and the parent of the expression mustn't be a PsiReferenceExpression as it means this is a branch of a broader PsiReferenceExpression.

Do you think the implementation is ok? Also, would there be any issues by providing this algorithm to an overridden visitReferenceExpression?

Thank you!

Radu 

0
Avatar
Permanently deleted user

Just realised the first condition of my search is incomplete; I meant to write

if (!expression.isQualified() || expression.getQualifierExpression() instanceof PsiThisExpression) return;

 

0

what about references like ClassFQN.ourStaticField or classA.myFieldB.myFieldC. All in all the implementation looks similar to what we have normally, should be ok.

Anna

0

Please sign in to leave a comment.