Macro. Find the declaration to introspect by URI and name, when from elements.
This makes the output more compact. This also allows to introspect declarations that are otherwise hard to reference, such as functions. I will add more in following CLs. Change-Id: I4775beca6aac5e642028b05f40aac31b079ba9de Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/341391 Commit-Queue: Konstantin Shcheglov <scheglov@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Phil Quitslund <pquitslund@google.com>
This commit is contained in:
committed by
Commit Queue
parent
1800039c2a
commit
55bd60be32
@@ -904,9 +904,8 @@ class _DefinitionPhaseIntrospector extends _DeclarationPhaseIntrospector
|
||||
@override
|
||||
Future<macro.Declaration> declarationOf(
|
||||
covariant macro.Identifier identifier,
|
||||
) {
|
||||
// TODO(scheglov): implement declarationOf
|
||||
throw UnimplementedError();
|
||||
) async {
|
||||
return declarationBuilder.declarationOf(identifier);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -105,6 +105,26 @@ class DeclarationBuilder {
|
||||
throw UnimplementedError('${node.runtimeType}');
|
||||
}
|
||||
|
||||
/// See [macro.DefinitionPhaseIntrospector.declarationOf].
|
||||
macro.DeclarationImpl declarationOf(macro.Identifier identifier) {
|
||||
if (identifier is! IdentifierImpl) {
|
||||
throw ArgumentError('Not analyzer identifier.');
|
||||
}
|
||||
|
||||
final element = identifier.element;
|
||||
if (element == null) {
|
||||
throw ArgumentError('Identifier without element.');
|
||||
}
|
||||
|
||||
final node = nodeOfElement(element);
|
||||
if (node != null) {
|
||||
// TODO(scheglov): implement
|
||||
throw UnimplementedError();
|
||||
} else {
|
||||
return fromElement.declarationOf(element);
|
||||
}
|
||||
}
|
||||
|
||||
macro.TypeAnnotation inferOmittedType(
|
||||
macro.OmittedTypeAnnotation omittedType,
|
||||
) {
|
||||
@@ -437,10 +457,40 @@ class DeclarationBuilderFromElement {
|
||||
return _constructorMap[element] ??= _constructorElement(element);
|
||||
}
|
||||
|
||||
/// See [macro.DefinitionPhaseIntrospector.declarationOf].
|
||||
macro.DeclarationImpl declarationOf(Element element) {
|
||||
switch (element) {
|
||||
case FunctionElementImpl():
|
||||
return functionElement(element);
|
||||
default:
|
||||
// TODO(scheglov): other elements
|
||||
return typeDeclarationOf(element);
|
||||
}
|
||||
}
|
||||
|
||||
macro.FieldDeclarationImpl fieldElement(FieldElementImpl element) {
|
||||
return _fieldMap[element] ??= _fieldElement(element);
|
||||
}
|
||||
|
||||
FunctionDeclarationImpl functionElement(ExecutableElementImpl element) {
|
||||
return FunctionDeclarationImpl._(
|
||||
element: element,
|
||||
id: macro.RemoteInstance.uniqueId,
|
||||
identifier: identifier(element),
|
||||
library: library(element),
|
||||
metadata: _buildMetadata(element),
|
||||
hasBody: !element.isAbstract,
|
||||
hasExternal: element.isExternal,
|
||||
isGetter: element is PropertyAccessorElementImpl && element.isGetter,
|
||||
isOperator: element.isOperator,
|
||||
isSetter: element is PropertyAccessorElementImpl && element.isSetter,
|
||||
namedParameters: _namedFormalParameters(element.parameters),
|
||||
positionalParameters: _positionalFormalParameters(element.parameters),
|
||||
returnType: _dartType(element.returnType),
|
||||
typeParameters: element.typeParameters.map(_typeParameter).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
macro.IdentifierImpl identifier(Element element) {
|
||||
final name = switch (element) {
|
||||
PropertyAccessorElement(isSetter: true) => element.displayName,
|
||||
@@ -483,12 +533,14 @@ class DeclarationBuilderFromElement {
|
||||
|
||||
/// See [macro.DeclarationPhaseIntrospector.typeDeclarationOf].
|
||||
macro.TypeDeclarationImpl typeDeclarationOf(Element element) {
|
||||
if (element is ClassElementImpl) {
|
||||
return classElement(element);
|
||||
} else if (element is MixinElementImpl) {
|
||||
return mixinElement(element);
|
||||
} else {
|
||||
throw ArgumentError('element: $element');
|
||||
switch (element) {
|
||||
case ClassElementImpl():
|
||||
return classElement(element);
|
||||
case MixinElementImpl():
|
||||
return mixinElement(element);
|
||||
default:
|
||||
// TODO(scheglov): other elements
|
||||
throw ArgumentError('element: $element');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -131,6 +131,58 @@ import 'package:_fe_analyzer_shared/src/macros/api.dart';
|
||||
}
|
||||
}
|
||||
|
||||
/*macro*/ class IntrospectDeclaration implements FunctionDefinitionMacro {
|
||||
final String uriStr;
|
||||
final String name;
|
||||
final bool withUnnamedConstructor;
|
||||
|
||||
IntrospectDeclaration({
|
||||
required this.uriStr,
|
||||
required this.name,
|
||||
this.withUnnamedConstructor = false,
|
||||
});
|
||||
|
||||
@override
|
||||
Future<void> buildDefinitionForFunction(declaration, builder) async {
|
||||
final buffer = StringBuffer();
|
||||
final sink = TreeStringSink(
|
||||
sink: buffer,
|
||||
indent: '',
|
||||
);
|
||||
|
||||
final printer = _Printer(
|
||||
sink: sink,
|
||||
withMetadata: true,
|
||||
withUnnamedConstructor: withUnnamedConstructor,
|
||||
introspector: builder,
|
||||
withDetailsFor: {name},
|
||||
);
|
||||
|
||||
// ignore: deprecated_member_use
|
||||
final identifier = await builder.resolveIdentifier(
|
||||
Uri.parse(uriStr),
|
||||
name,
|
||||
);
|
||||
final declaration = await builder.declarationOf(identifier);
|
||||
switch (declaration) {
|
||||
case ClassDeclaration():
|
||||
await printer.writeClassDeclaration(declaration);
|
||||
case FunctionDeclaration():
|
||||
await printer.writeFunctionDeclaration(declaration);
|
||||
case MixinDeclaration():
|
||||
await printer.writeMixinDeclaration(declaration);
|
||||
default:
|
||||
throw UnimplementedError('${declaration.runtimeType}');
|
||||
}
|
||||
|
||||
final text = buffer.toString();
|
||||
|
||||
builder.augment(
|
||||
FunctionBodyCode.fromString('=> r"""$text""";'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrapper around a [StringSink] for writing tree structures.
|
||||
class TreeStringSink {
|
||||
final StringSink _sink;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user