如何获得MethodInvocation的完全限定目标?

KOG*_*OGI 6 static-analysis abstract-syntax-tree dart

我试图找到一种特定方法的用法.在这种情况下,我想找到的用法/调用foo.go(),但不是bar.go().下面的代码将找到go()任何类的所有调用.在下面的代码中,node.target简单地给出了我x的var名称,但我正在努力弄清楚方法属于哪个类.

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');
  }
}
Run Code Online (Sandbox Code Playgroud)

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

我如何区分(在分析仪级别),foo.go()和之间bar.go()

Jon*_*man 3

问题是test.dart没有解析其中包含的元素所需的上下文的情况下进行解析。

\n\n

Dart SDK 中的分析器包中包含这样的示例

\n\n

将其分解为以下步骤:

\n\n

1 - 设置解析器

\n\n
PhysicalResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;\nDartSdk sdk = new FolderBasedDartSdk(resourceProvider, resourceProvider.getFolder(args[0]));\n\nvar resolvers = [\n  new DartUriResolver(sdk),\n  new ResourceUriResolver(resourceProvider)\n];\n
Run Code Online (Sandbox Code Playgroud)\n\n

AnalysisContext2 -使用解析器创建

\n\n
AnalysisContext context = AnalysisEngine.instance.createAnalysisContext()\n  ..sourceFactory = new SourceFactory(resolvers);\n
Run Code Online (Sandbox Code Playgroud)\n\n

3 - 将您的添加SourceChangeSet

\n\n
Source source = new FileSource(resourceProvider.getFile(args[1]));\nChangeSet changeSet = new ChangeSet()..addedSource(source);\n
Run Code Online (Sandbox Code Playgroud)\n\n

3.1 - 将ChangeSet应用于AnalysisContext

\n\n
context.applyChanges(changeSet);\n
Run Code Online (Sandbox Code Playgroud)\n\n

3.2 - 获取LibraryElement

\n\n

我不确定这是否总是需要的。也许对于简单的文件可以跳过它。\xc2\xaf(\xe2\x97\x89\xe2\x97\xa1\xe2\x97\x94)/\xc2\xaf

\n\n
LibraryElement libElement = context.computeLibraryElement(source);\n
Run Code Online (Sandbox Code Playgroud)\n\n

4 - 解析你的Source

\n\n
CompilationUnit resolvedUnit = context.resolveCompilationUnit(source, libElement);\n
Run Code Online (Sandbox Code Playgroud)\n\n

5 - 运行你的Visitor

\n\n
resolvedUnit.accept(visitor)\n
Run Code Online (Sandbox Code Playgroud)\n\n

不幸的是,这比仅仅调用要多得多的代码parseDartFile()但好消息是您Visitor应该无需进一步更改即可工作。

\n\n

祝你好运!

\n