如何获取标识符的类型 dart-analyzer
how to get type of identifier dart-analyzer
我正在 class 中处理方法语句,我想在这些语句中找到标识符的类型。
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:build/build.dart';
import 'package:dstore/dstore.dart';
import 'package:dstore_generator/src/utils.dart';
import 'package:source_gen/source_gen.dart';
AstNode getAstNodeFromElement(Element element) {
AnalysisSession session = element.session;
ParsedLibraryResult parsedLibResult =
session.getParsedLibraryByElement(element.library);
ElementDeclarationResult elDeclarationResult =
parsedLibResult.getElementDeclaration(element);
return elDeclarationResult.node;
}
class SelectorsGenerator extends GeneratorForAnnotation<Selectors> {
@override
String generateForAnnotatedElement(
Element element, ConstantReader annotation, BuildStep buildStep) {
if (!(element is ClassElement)) {
throw Exception("Selectors should be applied on class only");
}
final className = element.name;
if (!className.startsWith("_")) {
throw Exception("Selectors functions class should start with _");
}
final modelName = className.substring(1);
final visitor = SelectorsVisitor(modelName);
final astNode = getAstNodeFromElement(element);
astNode.visitChildren(visitor);
return """
// Selector
""";
}
}
class SelectorsVisitor extends SimpleAstVisitor {
final String modelName;
final selectors = <String>[];
SelectorsVisitor(this.modelName);
@override
dynamic visitMethodDeclaration(MethodDeclaration node) {
final fields = convertParamsToFields(node.parameters);
if (fields.isEmpty || fields.length > 1) {
throw Exception(
"Selector functions should be only one param with app state");
}
final field = fields.first;
var name = node.name.toString();
if (node.returnType == null) {
throw Exception("You sould annontate return type of method ${name} ");
}
final rType = node.returnType.toString();
final sType = field.type;
final bvs = SelectorBodyVisitor(field.param!.identifier);
node.body.visitChildren(bvs);
// node.body.visitChildren(visitor)
return super.visitMethodDeclaration(node);
}
}
class SelectorBodyVisitor extends RecursiveAstVisitor {
final Identifier identifier;
final List<List<String>> depsList = [];
SelectorBodyVisitor(this.identifier);
List<String> getListOfPropAccess(PropertyAccess node) {
final result = <String>[];
final prop = node.propertyName.toString();
result.add(prop);
final target = node.target;
print("target type ${target.runtimeType}");
if (target is PropertyAccess) {
result.addAll(getListOfPropAccess(target));
} else if (target is PrefixedIdentifier) {
if (target.prefix.toString() == identifier.toString()) {
// I am trying to get identifier type here
print("IdentifierElement2 ${target.identifier.staticType}");
result.add(target.identifier.toString());
} else {
print("target is not identifier ${target.runtimeType} ${target}");
}
}
return result;
}
@override
dynamic visitPropertyAccess(PropertyAccess node) {
print("***&&& propsAccess ${node}");
final list = getListOfPropAccess(node);
final sa = node.toString().split(".").toList();
if (sa.length - 1 == list.length) {
// property access of state identifier
depsList.add(list.reversed.toList().take(2).toList());
}
print("Property access list ++++=== ++++++ ${list}");
}
@override
dynamic visitPrefixedIdentifier(PrefixedIdentifier node) {
print(
"**##### IdenAccess ${node} id: ${node.identifier} prefix : ${node.prefix} mid :${identifier.toString()}");
if (node.prefix.toString() == identifier.toString()) {
print("IdentifierElement1 ${node.identifier.staticType}");
depsList.add([node.identifier.toString()]);
} else {
print("identifier is not equal ${node.prefix == identifier}");
}
}
}
例子
class User {
final String name;
User(this.name)
}
class Model {
final User user;
Model(this.user)
}
@Selectors()
abstract class MySelectors {
static s1(Model model) {
final n = model.user.name; // i want to know type of name in code generation time , please check this line print("IdentifierElement2 ${target.identifier.staticType}"); in above code , where i am getting null
}
}
找到答案,我必须在 getAstNodeFromElement
方法中使用 getResolvedLibraryByElement
而不是 getParsedLibraryByElement
。
Future<AstNode> getAstNodeFromElement(Element element) async {
AnalysisSession session = element.session;
final s = await session.getResolvedLibraryByElement(element.library);
final s2 = s.getElementDeclaration(element);
return s2.node;
}
我正在 class 中处理方法语句,我想在这些语句中找到标识符的类型。
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:build/build.dart';
import 'package:dstore/dstore.dart';
import 'package:dstore_generator/src/utils.dart';
import 'package:source_gen/source_gen.dart';
AstNode getAstNodeFromElement(Element element) {
AnalysisSession session = element.session;
ParsedLibraryResult parsedLibResult =
session.getParsedLibraryByElement(element.library);
ElementDeclarationResult elDeclarationResult =
parsedLibResult.getElementDeclaration(element);
return elDeclarationResult.node;
}
class SelectorsGenerator extends GeneratorForAnnotation<Selectors> {
@override
String generateForAnnotatedElement(
Element element, ConstantReader annotation, BuildStep buildStep) {
if (!(element is ClassElement)) {
throw Exception("Selectors should be applied on class only");
}
final className = element.name;
if (!className.startsWith("_")) {
throw Exception("Selectors functions class should start with _");
}
final modelName = className.substring(1);
final visitor = SelectorsVisitor(modelName);
final astNode = getAstNodeFromElement(element);
astNode.visitChildren(visitor);
return """
// Selector
""";
}
}
class SelectorsVisitor extends SimpleAstVisitor {
final String modelName;
final selectors = <String>[];
SelectorsVisitor(this.modelName);
@override
dynamic visitMethodDeclaration(MethodDeclaration node) {
final fields = convertParamsToFields(node.parameters);
if (fields.isEmpty || fields.length > 1) {
throw Exception(
"Selector functions should be only one param with app state");
}
final field = fields.first;
var name = node.name.toString();
if (node.returnType == null) {
throw Exception("You sould annontate return type of method ${name} ");
}
final rType = node.returnType.toString();
final sType = field.type;
final bvs = SelectorBodyVisitor(field.param!.identifier);
node.body.visitChildren(bvs);
// node.body.visitChildren(visitor)
return super.visitMethodDeclaration(node);
}
}
class SelectorBodyVisitor extends RecursiveAstVisitor {
final Identifier identifier;
final List<List<String>> depsList = [];
SelectorBodyVisitor(this.identifier);
List<String> getListOfPropAccess(PropertyAccess node) {
final result = <String>[];
final prop = node.propertyName.toString();
result.add(prop);
final target = node.target;
print("target type ${target.runtimeType}");
if (target is PropertyAccess) {
result.addAll(getListOfPropAccess(target));
} else if (target is PrefixedIdentifier) {
if (target.prefix.toString() == identifier.toString()) {
// I am trying to get identifier type here
print("IdentifierElement2 ${target.identifier.staticType}");
result.add(target.identifier.toString());
} else {
print("target is not identifier ${target.runtimeType} ${target}");
}
}
return result;
}
@override
dynamic visitPropertyAccess(PropertyAccess node) {
print("***&&& propsAccess ${node}");
final list = getListOfPropAccess(node);
final sa = node.toString().split(".").toList();
if (sa.length - 1 == list.length) {
// property access of state identifier
depsList.add(list.reversed.toList().take(2).toList());
}
print("Property access list ++++=== ++++++ ${list}");
}
@override
dynamic visitPrefixedIdentifier(PrefixedIdentifier node) {
print(
"**##### IdenAccess ${node} id: ${node.identifier} prefix : ${node.prefix} mid :${identifier.toString()}");
if (node.prefix.toString() == identifier.toString()) {
print("IdentifierElement1 ${node.identifier.staticType}");
depsList.add([node.identifier.toString()]);
} else {
print("identifier is not equal ${node.prefix == identifier}");
}
}
}
例子
class User {
final String name;
User(this.name)
}
class Model {
final User user;
Model(this.user)
}
@Selectors()
abstract class MySelectors {
static s1(Model model) {
final n = model.user.name; // i want to know type of name in code generation time , please check this line print("IdentifierElement2 ${target.identifier.staticType}"); in above code , where i am getting null
}
}
找到答案,我必须在 getAstNodeFromElement
方法中使用 getResolvedLibraryByElement
而不是 getParsedLibraryByElement
。
Future<AstNode> getAstNodeFromElement(Element element) async {
AnalysisSession session = element.session;
final s = await session.getResolvedLibraryByElement(element.library);
final s2 = s.getElementDeclaration(element);
return s2.node;
}