How to get the fully qualified target of the Invocation method?

I am trying to find ways to use a specific method. In this case, I want to find the use of / invocations foo.go() , but NOT bar.go() . In the code below, all go() calls will be found in ANY class. In the code below, node.target gives me just x , which is the name var, but I'm struggling to figure out which class the method belongs to.

test.dart

 void main() { var x = new Foo(); x.go(); x = new Bar(); x.go(); } class Foo { go() { print('I am foo'); } } class Bar { go() { print('I am bar'); } } 

analyze.dart

 import 'package:analyzer/analyzer.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/visitor.dart'; void main() { var targetFile = parseDartFile('test.dart'); var visitor = new UsageVisitor('foo.go'); targetFile.visitChildren(visitor); } class UsageVisitor extends UnifyingAstVisitor { String _class; String _method; UsageVisitor(this._class, this._method); @override visitMethodInvocation(MethodInvocation node) { print({ 'target' : node.target.toString(), // in both cases, gives "x" -- I need "Foo" and "Bar", respectively 'methodName': node.methodName.toString() // gives "go" }); return super.visitNode(node); } } 

How to tell the difference (at the analyzer level) between foo.go() and bar.go() ?

+5
source share
2 answers

The problem is that test.dart parsed without the context needed to eliminate the elements contained inside.

An example of this is included in the analyzer package in the Dart SDK.

Destroying it to its steps:

1 - Configuring converters

 PhysicalResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE; DartSdk sdk = new FolderBasedDartSdk(resourceProvider, resourceProvider.getFolder(args[0])); var resolvers = [ new DartUriResolver(sdk), new ResourceUriResolver(resourceProvider) ]; 

2 - Create AnalysisContext with Transformers

 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext() ..sourceFactory = new SourceFactory(resolvers); 

3 - Add Source to ChangeSet

 Source source = new FileSource(resourceProvider.getFile(args[1])); ChangeSet changeSet = new ChangeSet()..addedSource(source); 

3.1 - Apply ChangeSet to AnalysisContext

 context.applyChanges(changeSet); 

3.2 - Get LibraryElement

I am not sure that this is always necessary. Perhaps you can skip it for simple files. ยฏ (โ—‰โ—กโ—”) / ยฏ

 LibraryElement libElement = context.computeLibraryElement(source); 

4 - Disassemble your Source !

 CompilationUnit resolvedUnit = context.resolveCompilationUnit(source, libElement); 

5 - Launch Visitor

 resolvedUnit.accept(visitor) 

Unfortunately, there is much more code than just calling parseDartFile() , but the good news is that your Visitor should work without further changes.

Good luck

+2
source

I found something, but I'm not used to the analyzer, maybe it can be simplified, and it works only for you.

 @override visitMethodInvocation(MethodInvocation node) { if (node.methodName.toString() == "go" && node.target.toString() == "x") { for (dynamic child in node.parent?.parent?.childEntities) { if (child is VariableDeclarationStatement) { if ((child.childEntities.first as VariableDeclarationList).type.toString() == "Foo" && ((child.childEntities.first as VariableDeclarationList).childEntities.elementAt(1) as VariableDeclaration) .beginToken .toString() == "x") { print(node); } } } } return super.visitNode(node); } 
+1
source

Source: https://habr.com/ru/post/1262897/


All Articles