blob: 1892eb3ce44cdd820415b9b9539f5aa174e78fbb [file] [log] [blame]
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'ast.dart';
class PublicAbstractor extends RecursiveAstVisitor<void> {
final Map<String, Class> _classes = {};
bool _isPublic(String name) => !name.startsWith('_');
Map<String, Class> get classes => _classes;
@override
void visitClassDeclaration(ClassDeclaration node) {
final className = node.name.lexeme;
if (_isPublic(className)) {
final isAbstract = node.abstractKeyword != null;
final isInterface = node.interfaceKeyword != null;
final extendedClass = node.extendsClause?.superclass.toSource();
final interfaces =
node.implementsClause?.interfaces
.map((type) => type.toSource())
.toList();
_classes[className] = Class(
className,
isAbstract,
isInterface,
extendedClass ?? '',
interfaces ?? [],
);
node.visitChildren(this);
}
}
@override
void visitFieldDeclaration(FieldDeclaration node) {
final className =
(node.parent is ClassDeclaration)
? (node.parent as ClassDeclaration).name.lexeme
: '';
if (className.isEmpty || !_isPublic(className)) return;
for (final variable in node.fields.variables) {
final fieldName = variable.name.lexeme;
if (_isPublic(fieldName)) {
_classes[className]!.addField(
Field(
fieldName,
node.fields.type?.toSource() ?? 'dynamic',
isStatic: node.isStatic,
),
);
}
}
}
@override
void visitMethodDeclaration(MethodDeclaration node) {
final className =
(node.parent is ClassDeclaration)
? (node.parent as ClassDeclaration).name.lexeme
: '';
final methodName = node.name.lexeme;
if (className.isEmpty || !_isPublic(className) || !_isPublic(methodName)) {
return;
}
final returnType = node.returnType?.toSource() ?? 'dynamic';
final parameters = node.parameters?.toSource() ?? '()';
final typeParameters = node.typeParameters?.toSource() ?? '';
final operatorKeyword = node.operatorKeyword?.stringValue ?? '';
if (node.isGetter) {
_classes[className]!.getters.add(
Getter(methodName, returnType, node.isStatic),
);
return;
}
if (node.isSetter) {
_classes[className]!.setters.add(
Setter(
methodName,
returnType,
node.isStatic,
node.parameters?.toSource() ?? '()',
),
);
return;
}
_classes[className]!.addMethod(
Method(
methodName,
returnType,
node.isStatic,
parameters,
typeParameters,
operatorKeyword: operatorKeyword,
),
);
}
@override
void visitConstructorDeclaration(ConstructorDeclaration node) {
final className =
(node.parent is ClassDeclaration)
? (node.parent as ClassDeclaration).name.lexeme
: '';
final constructorName = node.name?.lexeme ?? '';
if (className.isEmpty ||
!_isPublic(className) ||
!_isPublic(constructorName)) {
return;
}
final parameters = node.parameters.toSource();
_classes[className]!.constructors.add(
Constructor(
className,
constructorName,
parameters,
node.factoryKeyword?.stringValue,
),
);
}
List<Class> getBindingsClassesSummary() => _classes.values.toList();
}