如何获得 MethodInvocation 的完全限定目标?
How to get the fully-qualified target of a MethodInvocation?
我正在尝试查找特定方法的用法。在这种情况下,我想找到 foo.go()
的 usages/invocations,而不是 bar.go()
。下面的代码将在任何 class 上找到 go()
的所有调用。在下面的代码中,node.target
简单地给了我 x
这是 var 名称,但我正在努力弄清楚该方法属于哪个 class。
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);
}
}
如何区分 foo.go()
和 bar.go()
之间的差异(在分析器级别)?
我找到了一些东西,但我不习惯分析器,也许它可以简化并且只适用于你的情况。
@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);
}
问题是 test.dart
正在 解析时没有上下文 需要解析其中包含的元素。
analyzer package within the Dart SDK
中包含一个示例
将其分解为您拥有的步骤:
1 - 设置解析器
PhysicalResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;
DartSdk sdk = new FolderBasedDartSdk(resourceProvider, resourceProvider.getFolder(args[0]));
var resolvers = [
new DartUriResolver(sdk),
new ResourceUriResolver(resourceProvider)
];
2 - 使用解析器
创建一个 AnalysisContext
AnalysisContext context = AnalysisEngine.instance.createAnalysisContext()
..sourceFactory = new SourceFactory(resolvers);
3 - 将您的 Source
添加到 ChangeSet
Source source = new FileSource(resourceProvider.getFile(args[1]));
ChangeSet changeSet = new ChangeSet()..addedSource(source);
3.1 - 将 ChangeSet
应用于 AnalysisContext
context.applyChanges(changeSet);
3.2 - 获取 LibraryElement
我不确定是否总是需要这样做。也许对于简单的文件可以跳过。¯(◉◡◔)/¯
LibraryElement libElement = context.computeLibraryElement(source);
4 - 解析你的 Source
!
CompilationUnit resolvedUnit = context.resolveCompilationUnit(source, libElement);
5 - 运行 你的 Visitor
resolvedUnit.accept(visitor)
不幸的是,这 比调用 parseDartFile()
多了很多 代码,但好消息是您的 Visitor
无需进一步更改即可正常工作。
祝你好运!
我正在尝试查找特定方法的用法。在这种情况下,我想找到 foo.go()
的 usages/invocations,而不是 bar.go()
。下面的代码将在任何 class 上找到 go()
的所有调用。在下面的代码中,node.target
简单地给了我 x
这是 var 名称,但我正在努力弄清楚该方法属于哪个 class。
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);
}
}
如何区分 foo.go()
和 bar.go()
之间的差异(在分析器级别)?
我找到了一些东西,但我不习惯分析器,也许它可以简化并且只适用于你的情况。
@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);
}
问题是 test.dart
正在 解析时没有上下文 需要解析其中包含的元素。
analyzer package within the Dart SDK
中包含一个示例将其分解为您拥有的步骤:
1 - 设置解析器
PhysicalResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;
DartSdk sdk = new FolderBasedDartSdk(resourceProvider, resourceProvider.getFolder(args[0]));
var resolvers = [
new DartUriResolver(sdk),
new ResourceUriResolver(resourceProvider)
];
2 - 使用解析器
创建一个AnalysisContext
AnalysisContext context = AnalysisEngine.instance.createAnalysisContext()
..sourceFactory = new SourceFactory(resolvers);
3 - 将您的 Source
添加到 ChangeSet
Source source = new FileSource(resourceProvider.getFile(args[1]));
ChangeSet changeSet = new ChangeSet()..addedSource(source);
3.1 - 将 ChangeSet
应用于 AnalysisContext
context.applyChanges(changeSet);
3.2 - 获取 LibraryElement
我不确定是否总是需要这样做。也许对于简单的文件可以跳过。¯(◉◡◔)/¯
LibraryElement libElement = context.computeLibraryElement(source);
4 - 解析你的 Source
!
CompilationUnit resolvedUnit = context.resolveCompilationUnit(source, libElement);
5 - 运行 你的 Visitor
resolvedUnit.accept(visitor)
不幸的是,这 比调用 parseDartFile()
多了很多 代码,但好消息是您的 Visitor
无需进一步更改即可正常工作。
祝你好运!