| // Copyright (c) 2017, 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/element/element.dart'; | |
| import 'package:analyzer/dart/element/type.dart'; | |
| import 'package:analyzer/src/dart/ast/ast.dart' | |
| show ExpressionImpl, V1Projection; | |
| import 'package:analyzer/src/dart/element/element.dart'; | |
| import 'package:analyzer/src/dart/element/field_name_non_promotability_info.dart'; | |
| import 'package:analyzer/src/error/inference_error.dart'; | |
| import 'package:analyzer_utilities/testing/tree_string_sink.dart'; | |
| import 'package:collection/collection.dart'; | |
| import 'package:test/test.dart'; | |
| import '../../util/element_printer.dart'; | |
| import 'resolved_ast_printer.dart'; | |
| String getLibraryText({ | |
| required LibraryElementImpl library, | |
| required ElementTextConfiguration configuration, | |
| String indent = '', | |
| }) { | |
| var buffer = StringBuffer(); | |
| var sink = TreeStringSink(sink: buffer, indent: ''); | |
| writeLibrary(sink: sink, library: library, configuration: configuration); | |
| return buffer.toString(); | |
| } | |
| void writeLibrary({ | |
| required TreeStringSink sink, | |
| required LibraryElementImpl library, | |
| required ElementTextConfiguration configuration, | |
| }) { | |
| var elementPrinter = ElementPrinter( | |
| sink: sink, | |
| configuration: configuration.elementPrinterConfiguration, | |
| ); | |
| var writer2 = _Element2Writer( | |
| sink: sink, | |
| elementPrinter: elementPrinter, | |
| configuration: configuration, | |
| ); | |
| writer2.writeLibraryElement(library); | |
| } | |
| class ElementTextConfiguration { | |
| ElementPrinterConfiguration elementPrinterConfiguration = | |
| ElementPrinterConfiguration(); | |
| bool Function(Object) filter; | |
| bool withAllSupertypes = false; | |
| bool withCodeRanges = false; | |
| bool withConstantInitializers = true; | |
| bool withConstructors = true; | |
| bool withDefaultType = false; | |
| bool withDisplayName = false; | |
| bool withExportScope = false; | |
| bool withFunctionTypeParameters = false; | |
| bool withImports = true; | |
| bool withLibraryAugmentations = false; | |
| bool withLibraryFragments = true; | |
| bool withMetadata = true; | |
| bool withNonSynthetic = false; | |
| bool withRedirectedConstructors = false; | |
| bool withReferences = true; | |
| bool withReturnType = true; | |
| bool withSyntheticDartCoreImport = false; | |
| bool withSyntheticGetters = true; | |
| ElementTextConfiguration({this.filter = _filterTrue}); | |
| void forClassConstructors({Set<String> classNames = const {}}) { | |
| filter = (o) { | |
| switch (o) { | |
| case LibraryFragment(): | |
| return true; | |
| case ClassFragmentImpl(): | |
| return classNames.contains(o.name); | |
| case ClassElement(): | |
| return classNames.contains(o.name); | |
| case ConstructorFragment(): | |
| case ConstructorElement(): | |
| return true; | |
| } | |
| return false; | |
| }; | |
| } | |
| void forPromotableFields({ | |
| Set<String> classNames = const {}, | |
| Set<String> enumNames = const {}, | |
| Set<String> extensionTypeNames = const {}, | |
| Set<String> mixinNames = const {}, | |
| Set<String> fieldNames = const {}, | |
| }) { | |
| filter = (o) { | |
| switch (o) { | |
| case LibraryFragment(): | |
| return false; | |
| case ClassElement(): | |
| return classNames.contains(o.name); | |
| case ConstructorElement(): | |
| return false; | |
| case EnumElement(): | |
| return enumNames.contains(o.name); | |
| case ExtensionTypeElement(): | |
| return extensionTypeNames.contains(o.name); | |
| case FieldElement(): | |
| return fieldNames.isEmpty || fieldNames.contains(o.name); | |
| case MixinElement(): | |
| return mixinNames.contains(o.name); | |
| case PropertyAccessorElement(): | |
| return false; | |
| } | |
| return true; | |
| }; | |
| } | |
| static bool _filterTrue(Object element) => true; | |
| } | |
| /// Writes the canonical text presentation of elements. | |
| abstract class _AbstractElementWriter { | |
| final TreeStringSink _sink; | |
| final ElementPrinter _elementPrinter; | |
| final ElementTextConfiguration configuration; | |
| _AbstractElementWriter({ | |
| required TreeStringSink sink, | |
| required ElementPrinter elementPrinter, | |
| required this.configuration, | |
| }) : _sink = sink, | |
| _elementPrinter = elementPrinter; | |
| IdMap get _idMap => _elementPrinter.idMap; | |
| ResolvedAstPrinter _createAstPrinter() { | |
| return ResolvedAstPrinter( | |
| sink: _sink, | |
| elementPrinter: _elementPrinter, | |
| configuration: ResolvedNodeTextConfiguration() | |
| // TODO(scheglov): https://github.com/dart-lang/sdk/issues/49101 | |
| ..withParameterElements = false, | |
| withOffsets: true, | |
| ); | |
| } | |
| void _writeDirectiveUri(DirectiveUri uri) { | |
| if (uri is DirectiveUriWithLibraryImpl) { | |
| _sink.write('${uri.library.source.uri}'); | |
| } else if (uri is DirectiveUriWithUnit) { | |
| _sink.write('${uri.libraryFragment.source.uri}'); | |
| } else if (uri is DirectiveUriWithSource) { | |
| _sink.write("source '${uri.source.uri}'"); | |
| } else if (uri is DirectiveUriWithRelativeUri) { | |
| _sink.write("relativeUri '${uri.relativeUri}'"); | |
| } else if (uri is DirectiveUriWithRelativeUriString) { | |
| _sink.write("relativeUriString '${uri.relativeUriString}'"); | |
| } else { | |
| _sink.write('noRelativeUriString'); | |
| } | |
| } | |
| void _writeExportEntries(LibraryElementImpl e) { | |
| var exportEntries = e.exportEntries.toList(); | |
| exportEntries.sortBy((e) => e.reference.debugString()); | |
| for (var entry in exportEntries) { | |
| _sink.writeIndentedLine(() { | |
| if (entry.isDeclared) { | |
| _sink.write('declared '); | |
| } else { | |
| _sink.write('exported${entry.locations} '); | |
| } | |
| _elementPrinter.writeReference(entry.reference); | |
| }); | |
| } | |
| } | |
| void _writeFieldNameNonPromotabilityInfo( | |
| Map<String, FieldNameNonPromotabilityInfo>? info, | |
| ) { | |
| if (info == null || info.isEmpty) { | |
| return; | |
| } | |
| _sink.writelnWithIndent('fieldNameNonPromotabilityInfo'); | |
| _sink.withIndent(() { | |
| for (var entry in info.entries) { | |
| _sink.writelnWithIndent(entry.key); | |
| _sink.withIndent(() { | |
| _elementPrinter.writeElementList2( | |
| 'conflictingFields', | |
| entry.value.conflictingFields, | |
| ); | |
| _elementPrinter.writeElementList2( | |
| 'conflictingGetters', | |
| entry.value.conflictingGetters, | |
| ); | |
| _elementPrinter.writeElementList2( | |
| 'conflictingNsmClasses', | |
| entry.value.conflictingNsmClasses, | |
| ); | |
| }); | |
| } | |
| }); | |
| } | |
| void _writeNode(AstNode node) { | |
| _sink.writeIndent(); | |
| _createAstPrinter().writeNode(node); | |
| } | |
| void _writeReference(ElementImpl e) { | |
| if (!configuration.withReferences) { | |
| return; | |
| } | |
| var reference = e.reference; | |
| if (reference != null) { | |
| _sink.writeIndentedLine(() { | |
| _sink.write('reference: '); | |
| _elementPrinter.writeReference(reference); | |
| }); | |
| } | |
| } | |
| } | |
| /// Writes the canonical text presentation of elements. | |
| class _Element2Writer extends _AbstractElementWriter { | |
| _Element2Writer({ | |
| required super.sink, | |
| required super.elementPrinter, | |
| required super.configuration, | |
| }); | |
| void writeLibraryElement(LibraryElementImpl e) { | |
| expect(e.enclosingElement, isNull); | |
| _sink.writelnWithIndent('library'); | |
| _sink.withIndent(() { | |
| _writeReference(e); | |
| var name = e.name; | |
| if (name.isNotEmpty) { | |
| _sink.writelnWithIndent('name: $name'); | |
| } | |
| _writeDocumentation(e.documentationComment); | |
| _writeMetadata(e.metadata); | |
| _writeSinceSdkVersion(e); | |
| // _writeList( | |
| // 'libraryExports', | |
| // e.libraryExports, | |
| // _writeLibraryExportElement, | |
| // ); | |
| if (configuration.withLibraryFragments) { | |
| _writeFragmentList( | |
| 'fragments', | |
| null, | |
| e.fragments, | |
| _writeLibraryFragment, | |
| ); | |
| } | |
| _writeElementList('classes', e, e.classes, _writeInstanceElement); | |
| _writeElementList('enums', e, e.enums, _writeInstanceElement); | |
| _writeElementList('extensions', e, e.extensions, _writeInstanceElement); | |
| _writeElementList( | |
| 'extensionTypes', | |
| e, | |
| e.extensionTypes, | |
| _writeInstanceElement, | |
| ); | |
| _writeElementList('mixins', e, e.mixins, _writeInstanceElement); | |
| _writeElementList( | |
| 'typeAliases', | |
| e, | |
| e.typeAliases, | |
| _writeTypeAliasElement, | |
| ); | |
| _writeElementList( | |
| 'topLevelVariables', | |
| e, | |
| e.topLevelVariables, | |
| _writeTopLevelVariableElement, | |
| ); | |
| _writeElementList( | |
| 'getters', | |
| e, | |
| e.getters.where((getter) { | |
| if (!configuration.withSyntheticGetters && getter.isOriginVariable) { | |
| return false; | |
| } | |
| return true; | |
| }).toList(), | |
| _writeGetterElement, | |
| ); | |
| _writeElementList('setters', e, e.setters, _writeSetterElement); | |
| _writeElementList( | |
| 'functions', | |
| e, | |
| e.topLevelFunctions, | |
| _writeTopLevelFunctionElement, | |
| ); | |
| if (configuration.withExportScope) { | |
| _sink.writelnWithIndent('exportEntries'); | |
| _sink.withIndent(() { | |
| _writeExportEntries(e); | |
| }); | |
| _sink.writelnWithIndent('exportNamespace'); | |
| _sink.withIndent(() { | |
| _writeExportNamespace(e); | |
| }); | |
| } | |
| _writeFieldNameNonPromotabilityInfo(e.fieldNameNonPromotabilityInfo); | |
| }); | |
| } | |
| void _assertHasExactlyOneTrue(List<bool> flags) { | |
| expect(flags.where((flag) => flag).length, 1); | |
| } | |
| void _writeConstantInitializerExpression(String name, Expression expression) { | |
| expect( | |
| expression.thisOrAncestorOfType2<CompilationUnit>(), | |
| isNull, | |
| reason: 'Element constant initializers must be detached.', | |
| ); | |
| // ignore: analyzer_to_be_deprecated_use | |
| var v1 = V1Projection.toV1Expression(expression as ExpressionImpl); | |
| if (!identical(v1, expression)) { | |
| expect( | |
| // ignore: analyzer_to_be_deprecated_use | |
| v1.thisOrAncestorOfType<CompilationUnit>(), | |
| isNull, | |
| reason: 'V1 projections of element initializers must be detached.', | |
| ); | |
| } | |
| if (_idMap.existingExpressionId(expression) case var id?) { | |
| _sink.writelnWithIndent('$name: $id'); | |
| } else { | |
| var id = _idMap[expression]; | |
| _sink.writelnWithIndent('$name: $id'); | |
| _sink.withIndent(() { | |
| _writeNode(expression); | |
| }); | |
| } | |
| } | |
| void _writeConstructorElement(ConstructorElement e) { | |
| e as ConstructorElementImpl; | |
| // Check that the reference exists, and filled with the element. | |
| // var reference = e.reference; | |
| // if (reference == null) { | |
| // fail('Every constructor must have a reference.'); | |
| // } | |
| _sink.writeIndentedLine(() { | |
| _sink.writeHeaderFlags(e.flagsForTesting); | |
| _assertHasExactlyOneTrue([ | |
| e.isOriginDeclaration, | |
| e.isOriginExtensionTypeRecovery, | |
| e.isOriginImplicitDefault, | |
| e.isOriginMixinApplication, | |
| ]); | |
| expect(e.isAbstract, isFalse); | |
| _writeElementName(e); | |
| }); | |
| _sink.withIndent(() { | |
| _writeReference(e); | |
| _writeFragmentReference('firstFragment', e.firstFragment); | |
| _writeFragmentReference( | |
| 'previousFragmentOfDifferentKind', | |
| e.previousFragmentOfDifferentKind, | |
| ); | |
| _writeDocumentation(e.documentationComment); | |
| _writeMetadata(e.metadata); | |
| _writeSinceSdkVersion(e); | |
| // _writeDisplayName(e); | |
| _writeElementList( | |
| 'formalParameters', | |
| e, | |
| e.formalParameters, | |
| _writeFormalParameterElement, | |
| ); | |
| _writeList('constantInitializers', e.constantInitializers, _writeNode); | |
| var superConstructor = e.superConstructor; | |
| if (superConstructor != null) { | |
| var enclosingElement = superConstructor.enclosingElement; | |
| if (enclosingElement is ClassElementImpl && | |
| !enclosingElement.isDartCoreObject) { | |
| _writeElementReference('superConstructor', superConstructor); | |
| } | |
| } | |
| var redirectedConstructor = e.redirectedConstructor; | |
| if (redirectedConstructor != null) { | |
| _writeElementReference('redirectedConstructor', redirectedConstructor); | |
| } | |
| // _writeNonSyntheticElement(e); | |
| }); | |
| // if (e.isSynthetic) { | |
| // expect(e.nameOffset, -1); | |
| // expect(e.nonSynthetic, same(e.enclosingElement)); | |
| // } else { | |
| // expect(e.nameOffset, isPositive); | |
| // } | |
| } | |
| void _writeConstructorFragment(ConstructorFragment f) { | |
| f as ConstructorFragmentImpl; | |
| _sink.writeIndentedLine(() { | |
| _writeObjectId(f); | |
| _sink.writeHeaderFlags(f.flagsForTesting); | |
| _assertHasExactlyOneTrue([ | |
| f.isOriginDeclaration, | |
| f.isOriginExtensionTypeRecovery, | |
| f.isOriginImplicitDefault, | |
| f.isOriginMixinApplication, | |
| ]); | |
| expect(f.isAbstract, isFalse); | |
| _writeFragmentName(f); | |
| }); | |
| _sink.withIndent(() { | |
| _writeElementReference('element', f.element); | |
| _writeDocumentation(f.documentationComment); | |
| _writeMetadata(f.metadata); | |
| if (configuration.withCodeRanges) { | |
| if (f.isOriginDeclaration) { | |
| _sink.writelnWithIndent('codeOffset: ${f.codeOffset}'); | |
| _sink.writelnWithIndent('codeLength: ${f.codeLength}'); | |
| } | |
| } | |
| if (f.newKeywordOffset case var newKeywordOffset?) { | |
| _sink.writelnWithIndent('newKeywordOffset: $newKeywordOffset'); | |
| } | |
| if (f.factoryKeywordOffset case var factoryKeywordOffset?) { | |
| _sink.writelnWithIndent('factoryKeywordOffset: $factoryKeywordOffset'); | |
| } | |
| _sink.writelnWithIndent('typeName: ${f.typeName}'); | |
| if (f.typeNameOffset case var typeNameOffset?) { | |
| _sink.writelnWithIndent('typeNameOffset: $typeNameOffset'); | |
| } | |
| if (f.periodOffset case var periodOffset?) { | |
| _sink.writelnWithIndent('periodOffset: $periodOffset'); | |
| } | |
| if (f.thisKeywordOffset case var thisKeywordOffset?) { | |
| _sink.writelnWithIndent('thisKeywordOffset: $thisKeywordOffset'); | |
| } | |
| if (f.primaryHeaderCodeRange case var range?) { | |
| _sink.writelnWithIndent( | |
| 'primaryHeaderCodeRange: ${range.offset} + ${range.length}', | |
| ); | |
| } | |
| if (f.primaryBodyCodeRange case var range?) { | |
| _sink.writelnWithIndent( | |
| 'primaryBodyCodeRange: ${range.offset} + ${range.length}', | |
| ); | |
| } | |
| _writeFragmentList( | |
| 'formalParameters', | |
| f, | |
| f.formalParameters, | |
| _writeFormalParameterFragment, | |
| ); | |
| // _writeNonSyntheticElement(f); | |
| _writeFragmentReference('nextFragment', f.nextFragment); | |
| _writeFragmentReference('previousFragment', f.previousFragment); | |
| }); | |
| expect(f.isAsynchronous, isFalse); | |
| expect(f.isGenerator, isFalse); | |
| } | |
| void _writeDocumentation(String? documentation) { | |
| if (documentation != null) { | |
| var str = documentation; | |
| str = str.replaceAll('\n', r'\n'); | |
| str = str.replaceAll('\r', r'\r'); | |
| _sink.writelnWithIndent('documentationComment: $str'); | |
| } | |
| } | |
| void _writeElementList<E extends ElementImpl>( | |
| String name, | |
| ElementImpl expectedEnclosingElement, | |
| List<E> elements, | |
| void Function(E) write, | |
| ) { | |
| var filtered = elements.where(configuration.filter).toList(); | |
| if (filtered.isNotEmpty) { | |
| _sink.writelnWithIndent(name); | |
| _sink.withIndent(() { | |
| for (var element in filtered) { | |
| expect(element.enclosingElement, expectedEnclosingElement); | |
| write(element); | |
| } | |
| }); | |
| } | |
| } | |
| void _writeElementName(Element e) { | |
| var name = e.name ?? '<null-name>'; | |
| _sink.write(name); | |
| switch (e) { | |
| case MethodElement(): | |
| if (e.name == '-' && e.formalParameters.isEmpty) { | |
| expect(e.lookupName, 'unary-'); | |
| } else { | |
| expect(e.lookupName, e.name); | |
| } | |
| case SetterElement(): | |
| if (e.name case var name?) { | |
| expect(e.lookupName, '$name='); | |
| } else { | |
| expect(e.lookupName, isNull); | |
| } | |
| default: | |
| expect(e.lookupName, e.name); | |
| } | |
| } | |
| void _writeElementReference(String name, Element? e) { | |
| if (!configuration.withReferences) { | |
| return; | |
| } | |
| if (e == null) { | |
| return; | |
| } | |
| _elementPrinter.writeNamedElement2(name, e); | |
| } | |
| void _writeExportNamespace(LibraryElement e) { | |
| var map = e.exportNamespace.definedNames2; | |
| var sortedEntries = map.entries.sortedBy((entry) => entry.key); | |
| for (var entry in sortedEntries) { | |
| _elementPrinter.writeNamedElement2(entry.key, entry.value); | |
| } | |
| } | |
| void _writeFieldElement(FieldElementImpl e) { | |
| e as InternalFieldElement; | |
| DartType type = e.type; | |
| expect(type, isNotNull); | |
| // if (e.isSynthetic) { | |
| // expect(e.nameOffset, -1); | |
| // } else { | |
| // if (!e.isAugmentation) { | |
| // expect(e.getter, isNotNull); | |
| // } | |
| // expect(e.nameOffset, isPositive); | |
| // _assertNonSyntheticElementSelf(e); | |
| // } | |
| _sink.writeIndentedLine(() { | |
| _sink.writeHeaderFlags(e.flagsForTesting); | |
| _assertHasExactlyOneTrue([ | |
| e.isOriginDeclaration, | |
| e.isOriginDeclaringFormalParameter, | |
| e.isOriginEnumValues, | |
| e.isOriginExtensionTypeRecoveryRepresentation, | |
| e.isOriginGetterSetter, | |
| ]); | |
| _writeElementName(e); | |
| }); | |
| _sink.withIndent(() { | |
| _writeReference(e); | |
| _writeFragmentReference('firstFragment', e.firstFragment); | |
| _writeFragmentReference( | |
| 'previousFragmentOfDifferentKind', | |
| e.previousFragmentOfDifferentKind, | |
| ); | |
| _writeDocumentation(e.documentationComment); | |
| _writeMetadata(e.metadata); | |
| _writeSinceSdkVersion(e); | |
| // _writeCodeRange(e); | |
| _writeTypeInferenceError(e.typeInferenceError); | |
| _writeType('type', e.type); | |
| // _writeShouldUseTypeForInitializerInference(e); | |
| _writeVariableElementConstantInitializer(e); | |
| // _writeNonSyntheticElement(e); | |
| _writeElementReference('getter', e.getter); | |
| _writeElementReference('setter', e.setter); | |
| _writeElementReference( | |
| 'declaringFormalParameter', | |
| e.declaringFormalParameter, | |
| ); | |
| }); | |
| } | |
| void _writeFieldFragment(FieldFragmentImpl f) { | |
| // TODO(brianwilkerson): Implement `type`. | |
| // DartType type = e.type; | |
| // expect(type, isNotNull); | |
| // if (f.isSynthetic) { | |
| // expect(f.nameOffset, -1); | |
| // } else { | |
| // // TODO(brianwilkerson): Implement `isAugmentation`. | |
| // if (!f.isAugmentation) { | |
| // expect(f.getter2, isNotNull); | |
| // } | |
| // expect(f.nameOffset, isPositive); | |
| // // _assertNonSyntheticElementSelf(e); | |
| // } | |
| _sink.writeIndentedLine(() { | |
| _writeObjectId(f); | |
| _sink.writeHeaderFlags(f.flagsForTesting); | |
| _assertHasExactlyOneTrue([ | |
| f.isOriginDeclaration, | |
| f.isOriginDeclaringFormalParameter, | |
| f.isOriginEnumValues, | |
| f.isOriginExtensionTypeRecoveryRepresentation, | |
| f.isOriginGetterSetter, | |
| ]); | |
| _writeFragmentName(f); | |
| }); | |
| _sink.withIndent(() { | |
| _writeElementReference('element', f.element); | |
| _writeDocumentation(f.documentationComment); | |
| _writeMetadata(f.metadata); | |
| // _writeSinceSdkVersion(f.sinceSdkVersion); | |
| // _writeCodeRange(f); | |
| // _writeType('type', f.type); | |
| // _writeShouldUseTypeForInitializerInference(f); | |
| _writeVariableFragmentInitializer(f); | |
| // _writeNonSyntheticElement(f); | |
| _writeFragmentReference('inducedGetter', f.inducedGetter); | |
| _writeFragmentReference('inducedSetter', f.inducedSetter); | |
| _writeFragmentReference('previousFragment', f.previousFragment); | |
| _writeFragmentReference('nextFragment', f.nextFragment); | |
| }); | |
| } | |
| void _writeFormalParameterElement(FormalParameterElement e) { | |
| e as FormalParameterElementImpl; | |
| expect(e.reference, isNull); | |
| _sink.writeIndentedLine(() { | |
| _writeObjectId(e); | |
| if (e.isRequiredPositional) { | |
| _sink.write('requiredPositional '); | |
| } else if (e.isOptionalPositional) { | |
| _sink.write('optionalPositional '); | |
| } else if (e.isRequiredNamed) { | |
| _sink.write('requiredNamed '); | |
| } else if (e.isOptionalNamed) { | |
| _sink.write('optionalNamed '); | |
| } | |
| _sink.writeHeaderFlags(e.flagsForTesting); | |
| switch (e) { | |
| case FieldFormalParameterElementImpl(): | |
| _sink.write('this.'); | |
| case SuperFormalParameterElementImpl(): | |
| _sink.write('super.'); | |
| } | |
| _writeElementName(e); | |
| }); | |
| _sink.withIndent(() { | |
| _writeFragmentReference('firstFragment', e.firstFragment); | |
| _writeType('type', e.type); | |
| _writeDocumentation(e.documentationComment); | |
| _writeMetadata(e.metadata); | |
| _writeSinceSdkVersion(e); | |
| _writeVariableElementConstantInitializer(e); | |
| switch (e) { | |
| case FieldFormalParameterElementImpl(): | |
| if (e.privateName case var privateName?) { | |
| _sink.writelnWithIndent('privateName: $privateName'); | |
| } | |
| _elementPrinter.writeNamedElement2('field', e.field); | |
| case SuperFormalParameterElementImpl(): | |
| _elementPrinter.writeNamedElement2( | |
| 'superConstructorParameter', | |
| e.superConstructorParameter, | |
| ); | |
| } | |
| }); | |
| } | |
| void _writeFormalParameterFragment(FormalParameterFragment f) { | |
| f as FormalParameterFragmentImpl; | |
| _sink.writeIndentedLine(() { | |
| _writeObjectId(f); | |
| if (f.isRequiredPositional) { | |
| _sink.write('requiredPositional '); | |
| } else if (f.isOptionalPositional) { | |
| _sink.write('optionalPositional '); | |
| } else if (f.isRequiredNamed) { | |
| _sink.write('requiredNamed '); | |
| } else if (f.isOptionalNamed) { | |
| _sink.write('optionalNamed '); | |
| } | |
| _sink.writeHeaderFlags(f.flagsForTesting); | |
| if (f is FieldFormalParameterFragmentImpl) { | |
| _sink.write('this.'); | |
| } else if (f is SuperFormalParameterFragmentImpl) { | |
| _sink.write('super.'); | |
| } | |
| _writeFragmentName(f); | |
| }); | |
| _sink.withIndent(() { | |
| _writeElementReference('element', f.element); | |
| _writeDocumentation(f.documentationComment); | |
| _writeMetadata(f.metadata); | |
| // _writeCodeRange(f); | |
| _writeVariableFragmentInitializer(f); | |
| _writeFragmentReference('previousFragment', f.previousFragment); | |
| _writeFragmentReference('nextFragment', f.nextFragment); | |
| }); | |
| } | |
| void _writeFragmentBodyModifiers(ExecutableFragment f) { | |
| if (f.isAsynchronous) { | |
| expect(f.isSynchronous, isFalse); | |
| _sink.write(' async'); | |
| } | |
| if (f.isSynchronous && f.isGenerator) { | |
| expect(f.isAsynchronous, isFalse); | |
| _sink.write(' sync'); | |
| } | |
| _sink.writeIf(f.isGenerator, '*'); | |
| } | |
| void _writeFragmentList<E extends Fragment>( | |
| String name, | |
| Fragment? expectedEnclosingFragment, | |
| List<E> elements, | |
| void Function(E) write, | |
| ) { | |
| var filtered = elements.where(configuration.filter).toList(); | |
| if (filtered.isNotEmpty) { | |
| _sink.writelnWithIndent(name); | |
| _sink.withIndent(() { | |
| for (var element in filtered) { | |
| if (expectedEnclosingFragment != null) { | |
| expect(element.enclosingFragment, expectedEnclosingFragment); | |
| } | |
| write(element); | |
| } | |
| }); | |
| } | |
| } | |
| void _writeFragmentName(FragmentImpl f) { | |
| if (f.name == null) { | |
| expect(f.nameOffset, isNull); | |
| } | |
| _sink.write(f.name ?? '<null-name>'); | |
| _writeFragmentOffsets(f); | |
| } | |
| void _writeFragmentOffsets(FragmentImpl f) { | |
| if (f is LibraryFragmentImpl) { | |
| expect(f.nameOffset, isNull); | |
| expect(f.firstTokenOffset, 0); | |
| if (f.offset == 0) { | |
| return; | |
| } | |
| } | |
| _sink.write(' (nameOffset:${f.nameOffset ?? '<null>'})'); | |
| _sink.write(' (firstTokenOffset:${f.firstTokenOffset ?? '<null>'})'); | |
| _sink.write(' (offset:${f.offset})'); | |
| } | |
| void _writeFragmentReference(String name, Fragment? f) { | |
| if (!configuration.withReferences) { | |
| return; | |
| } | |
| if (f == null) { | |
| return; | |
| } | |
| _sink.writeIndentedLine(() { | |
| _sink.write(name); | |
| _sink.write(': '); | |
| _sink.write(_idMap[f]); | |
| }); | |
| } | |
| void _writeGetterElement(GetterElementImpl e) { | |
| var variable = e.variable; | |
| var variableEnclosing = variable.enclosingElement; | |
| if (variableEnclosing is LibraryElement) { | |
| expect(variableEnclosing.topLevelVariables, contains(variable)); | |
| } else if (variableEnclosing is InterfaceElement) { | |
| // TODO(augmentations): Remove the invocations of `field.baseElement`. | |
| // There shouldn't be any members in the list of fields. | |
| expect( | |
| variableEnclosing.fields.map((field) => field.baseElement), | |
| contains(variable.baseElement), | |
| ); | |
| } | |
| // if (e.isSynthetic) { | |
| // expect(e.nameOffset, -1); | |
| // } else { | |
| // expect(e.nameOffset, isPositive); | |
| // _assertNonSyntheticElementSelf(e); | |
| // } | |
| _sink.writeIndentedLine(() { | |
| _sink.writeHeaderFlags(e.flagsForTesting); | |
| _assertHasExactlyOneTrue([e.isOriginDeclaration, e.isOriginVariable]); | |
| _writeElementName(e); | |
| }); | |
| _sink.withIndent(() { | |
| _writeReference(e); | |
| _writeFragmentReference('firstFragment', e.firstFragment); | |
| _writeFragmentReference( | |
| 'previousFragmentOfDifferentKind', | |
| e.previousFragmentOfDifferentKind, | |
| ); | |
| _writeDocumentation(e.documentationComment); | |
| _writeMetadata(e.metadata); | |
| _writeSinceSdkVersion(e); | |
| expect(e.typeParameters, isEmpty); | |
| _writeElementList( | |
| 'formalParameters', | |
| e, | |
| e.formalParameters, | |
| _writeFormalParameterElement, | |
| ); | |
| _writeReturnType(e.returnType); | |
| _writeElementReference('variable', e.variable); | |
| // _writeNonSyntheticElement(e); | |
| }); | |
| } | |
| void _writeGetterFragment(GetterFragmentImpl f) { | |
| // if (f.isSynthetic) { | |
| // expect(f.nameOffset, -1); | |
| // } else { | |
| // expect(f.nameOffset, isPositive); | |
| // _assertNonSyntheticElementSelf(f); | |
| // } | |
| _sink.writeIndentedLine(() { | |
| _writeObjectId(f); | |
| _sink.writeHeaderFlags(f.flagsForTesting); | |
| _assertHasExactlyOneTrue([ | |
| f.isOriginDeclaration, | |
| f.isOriginInterface, | |
| f.isOriginVariable, | |
| ]); | |
| _writeFragmentName(f); | |
| // _writeBodyModifiers(e); | |
| }); | |
| _sink.withIndent(() { | |
| _writeElementReference('element', f.element); | |
| _writeDocumentation(f.documentationComment); | |
| _writeMetadata(f.metadata); | |
| // _writeCodeRange(f); | |
| _writeFragmentReference('inducingVariable', f.inducingVariable); | |
| // expect(f.typeParameters2, isEmpty); | |
| _writeFragmentList( | |
| 'formalParameters', | |
| f, | |
| f.formalParameters, | |
| _writeFormalParameterFragment, | |
| ); | |
| // _writeNonSyntheticElement(f); | |
| _writeFragmentReference('previousFragment', f.previousFragment); | |
| _writeFragmentReference('nextFragment', f.nextFragment); | |
| }); | |
| } | |
| void _writeImportElementPrefix(PrefixFragmentImpl? fragment) { | |
| if (fragment != null) { | |
| _sink.writeIf(fragment.isDeferred, ' deferred'); | |
| _sink.write(' as '); | |
| _writeFragmentName(fragment); | |
| } | |
| } | |
| void _writeInstanceElement(InstanceElementImpl e) { | |
| expect(e.thisOrAncestorOfType<InstanceElement>(), same(e)); | |
| expect(e.thisOrAncestorOfType<GetterElement>(), isNull); | |
| expect(e.thisOrAncestorMatching((_) => true), same(e)); | |
| expect(e.thisOrAncestorMatching((_) => false), isNull); | |
| _sink.writeIndentedLine(() { | |
| switch (e) { | |
| case ClassElementImpl(): | |
| _sink.writeHeaderFlags(e.flagsForTesting); | |
| _sink.write('class '); | |
| case EnumElementImpl(): | |
| _sink.writeHeaderFlags(e.flagsForTesting); | |
| _sink.write('enum '); | |
| case ExtensionElementImpl(): | |
| _sink.write('extension '); | |
| case ExtensionTypeElementImpl(): | |
| _sink.writeHeaderFlags(e.flagsForTesting); | |
| _sink.write('extension type '); | |
| case MixinElementImpl(): | |
| _sink.writeHeaderFlags(e.flagsForTesting); | |
| _sink.write('mixin '); | |
| } | |
| _writeElementName(e); | |
| }); | |
| _sink.withIndent(() { | |
| _writeReference(e); | |
| _writeFragmentReference('firstFragment', e.firstFragment); | |
| _writeFragmentReference( | |
| 'previousFragmentOfDifferentKind', | |
| e.previousFragmentOfDifferentKind, | |
| ); | |
| _writeDocumentation(e.documentationComment); | |
| // _writeMetadata(e.metadata); | |
| _writeSinceSdkVersion(e); | |
| _writeElementList( | |
| 'typeParameters', | |
| e, | |
| e.typeParameters, | |
| _writeTypeParameterElement, | |
| ); | |
| void writeSupertype(InterfaceElement e) { | |
| if (e.supertype case var supertype?) { | |
| if (supertype.element.name != 'Object' || e.mixins.isNotEmpty) { | |
| _writeType('supertype', supertype); | |
| } | |
| } | |
| } | |
| switch (e) { | |
| case ClassElementImpl(): | |
| writeSupertype(e); | |
| _elementPrinter.writeTypeList('mixins', e.mixins); | |
| _elementPrinter.writeTypeList('interfaces', e.interfaces); | |
| case EnumElementImpl(): | |
| writeSupertype(e); | |
| _elementPrinter.writeTypeList('mixins', e.mixins); | |
| _elementPrinter.writeTypeList('interfaces', e.interfaces); | |
| case ExtensionElementImpl(): | |
| _elementPrinter.writeNamedType('extendedType', e.extendedType); | |
| _elementPrinter.writeNamedElement2('onDeclaration', e.onDeclaration); | |
| case ExtensionTypeElementImpl(): | |
| expect(e.supertype, isNull); | |
| _elementPrinter.writeNamedElement2( | |
| 'representation', | |
| e.representation, | |
| ); | |
| _elementPrinter.writeNamedElement2( | |
| 'primaryConstructor', | |
| e.primaryConstructor, | |
| ); | |
| _elementPrinter.writeNamedType('typeErasure', e.typeErasure); | |
| _elementPrinter.writeTypeList('interfaces', e.interfaces); | |
| case MixinElementImpl(): | |
| expect(e.supertype, isNull); | |
| _elementPrinter.writeTypeList( | |
| 'superclassConstraints', | |
| e.superclassConstraints, | |
| ); | |
| expect(e.mixins, isEmpty); | |
| _elementPrinter.writeTypeList('interfaces', e.interfaces); | |
| } | |
| if (configuration.withAllSupertypes && e is InterfaceElementImpl) { | |
| var sorted = e.allSupertypes.sortedBy((t) => t.element.name!); | |
| _elementPrinter.writeTypeList('allSupertypes', sorted); | |
| } | |
| _writeElementList('fields', e, e.fields, _writeFieldElement); | |
| if (e is InterfaceElementImpl) { | |
| var constructors = e.constructors; | |
| if (e is MixinElementImpl) { | |
| expect(constructors, isEmpty); | |
| } else if (configuration.withConstructors) { | |
| _writeElementList( | |
| 'constructors', | |
| e, | |
| constructors, | |
| _writeConstructorElement, | |
| ); | |
| } | |
| } | |
| _writeElementList('getters', e, e.getters, _writeGetterElement); | |
| _writeElementList('setters', e, e.setters, _writeSetterElement); | |
| _writeElementList('methods', e, e.methods, _writeMethodElement); | |
| }); | |
| } | |
| void _writeInstanceFragment(InstanceFragmentImpl f) { | |
| _sink.writeIndentedLine(() { | |
| _writeObjectId(f); | |
| switch (f) { | |
| case ClassFragmentImpl(): | |
| _sink.writeHeaderFlags(f.flagsForTesting); | |
| _sink.write('class '); | |
| case EnumFragmentImpl(): | |
| _sink.writeHeaderFlags(f.flagsForTesting); | |
| _sink.write('enum '); | |
| case ExtensionFragmentImpl(): | |
| _sink.writeHeaderFlags(f.flagsForTesting); | |
| _sink.write('extension '); | |
| case ExtensionTypeFragmentImpl(): | |
| _sink.writeHeaderFlags(f.flagsForTesting); | |
| _sink.write('extension type '); | |
| case MixinFragmentImpl(): | |
| _sink.writeHeaderFlags(f.flagsForTesting); | |
| _sink.write('mixin '); | |
| } | |
| _writeFragmentName(f); | |
| }); | |
| _sink.withIndent(() { | |
| _writeElementReference('element', f.element); | |
| _writeFragmentReference('previousFragment', f.previousFragment); | |
| _writeFragmentReference('nextFragment', f.nextFragment); | |
| if (f is InterfaceFragmentImpl && f.withClauseMixinStartIndex != 0) { | |
| _sink.writeIndentedLine(() { | |
| _sink.write( | |
| 'withClauseMixinStartIndex: ${f.withClauseMixinStartIndex}', | |
| ); | |
| }); | |
| } | |
| _writeFragmentList( | |
| 'typeParameters', | |
| f, | |
| f.typeParameters, | |
| _writeTypeParameterFragment, | |
| ); | |
| _writeFragmentList('fields', f, f.fields, _writeFieldFragment); | |
| if (f is InterfaceFragmentImpl) { | |
| var constructors = f.constructors; | |
| if (f is MixinElement) { | |
| expect(constructors, isEmpty); | |
| } else if (configuration.withConstructors) { | |
| _writeFragmentList( | |
| 'constructors', | |
| f, | |
| constructors, | |
| _writeConstructorFragment, | |
| ); | |
| } | |
| } | |
| _writeFragmentList('getters', f, f.getters, _writeGetterFragment); | |
| _writeFragmentList('setters', f, f.setters, _writeSetterFragment); | |
| _writeFragmentList('methods', f, f.methods, _writeMethodFragment); | |
| }); | |
| } | |
| void _writeLibraryExport(LibraryExportImpl e) { | |
| _sink.writeIndentedLine(() { | |
| _writeDirectiveUri(e.uri); | |
| }); | |
| _sink.withIndent(() { | |
| _writeMetadata(e.metadata); | |
| _writeNamespaceCombinators(e.combinators); | |
| }); | |
| } | |
| void _writeLibraryFragment(LibraryFragmentImpl f) { | |
| _sink.writeIndentedLine(() { | |
| _writeObjectId(f); | |
| _sink.writeHeaderFlags(f.flagsForTesting); | |
| var uriStr = f.source.uri.toString(); | |
| if (uriStr == 'package:test/test.dart') { | |
| _sink.write('<testLibraryFragment>'); | |
| } else { | |
| _sink.write(uriStr); | |
| } | |
| _writeFragmentOffsets(f); | |
| }); | |
| _sink.withIndent(() { | |
| _writeElementReference('element', f.element); | |
| _writeFragmentReference('enclosingFragment', f.enclosingFragment); | |
| _writeFragmentReference('previousFragment', f.previousFragment); | |
| _writeFragmentReference('nextFragment', f.nextFragment); | |
| if (configuration.withImports) { | |
| var imports = f.libraryImports.where((import) { | |
| return configuration.withSyntheticDartCoreImport || | |
| !import.isSynthetic; | |
| }).toList(); | |
| _writeList('libraryImports', imports, _writeLibraryImport); | |
| } | |
| _writeList('prefixes', f.prefixes, _writePrefixElement); | |
| _writeList('libraryExports', f.libraryExports, _writeLibraryExport); | |
| _writeList('parts', f.parts, _writePartInclude); | |
| _writeFragmentList('classes', f, f.classes, _writeInstanceFragment); | |
| _writeFragmentList('enums', f, f.enums, _writeInstanceFragment); | |
| _writeFragmentList('extensions', f, f.extensions, _writeInstanceFragment); | |
| _writeFragmentList( | |
| 'extensionTypes', | |
| f, | |
| f.extensionTypes, | |
| _writeInstanceFragment, | |
| ); | |
| _writeFragmentList('mixins', f, f.mixins, _writeInstanceFragment); | |
| _writeFragmentList( | |
| 'typeAliases', | |
| f, | |
| f.typeAliases, | |
| _writeTypeAliasFragment, | |
| ); | |
| _writeFragmentList( | |
| 'topLevelVariables', | |
| f, | |
| f.topLevelVariables, | |
| _writeTopLevelVariableFragment, | |
| ); | |
| _writeFragmentList('getters', f, f.getters, _writeGetterFragment); | |
| _writeFragmentList('setters', f, f.setters, _writeSetterFragment); | |
| _writeFragmentList( | |
| 'functions', | |
| f, | |
| f.functions, | |
| _writeTopLevelFunctionFragment, | |
| ); | |
| }); | |
| } | |
| void _writeLibraryImport(LibraryImportImpl e) { | |
| _sink.writeIndentedLine(() { | |
| _writeDirectiveUri(e.uri); | |
| _sink.writeIf(e.isSynthetic, ' synthetic'); | |
| _writeImportElementPrefix(e.prefix); | |
| }); | |
| _sink.withIndent(() { | |
| _writeMetadata(e.metadata); | |
| _writeNamespaceCombinators(e.combinators); | |
| }); | |
| } | |
| void _writeList<E extends Object>( | |
| String name, | |
| List<E> elements, | |
| void Function(E) write, | |
| ) { | |
| var filtered = elements.where(configuration.filter).toList(); | |
| if (filtered.isNotEmpty) { | |
| _sink.writelnWithIndent(name); | |
| _sink.withIndent(() { | |
| for (var element in filtered) { | |
| write(element); | |
| } | |
| }); | |
| } | |
| } | |
| void _writeMetadata(Metadata metadata) { | |
| if (configuration.withMetadata) { | |
| var annotations = metadata.annotations; | |
| if (annotations.isNotEmpty) { | |
| _sink.writelnWithIndent('metadata'); | |
| _sink.withIndent(() { | |
| for (var annotation in annotations) { | |
| annotation as ElementAnnotationImpl; | |
| _writeNode(annotation.annotationAst); | |
| } | |
| }); | |
| } | |
| } | |
| } | |
| void _writeMethodElement(MethodElementImpl e) { | |
| _sink.writeIndentedLine(() { | |
| _sink.writeHeaderFlags(e.flagsForTesting); | |
| _assertHasExactlyOneTrue([e.isOriginDeclaration, e.isOriginInterface]); | |
| _writeElementName(e); | |
| }); | |
| _sink.withIndent(() { | |
| _writeReference(e); | |
| _writeFragmentReference('firstFragment', e.firstFragment); | |
| _writeFragmentReference( | |
| 'previousFragmentOfDifferentKind', | |
| e.previousFragmentOfDifferentKind, | |
| ); | |
| // _writeElementReference(e.enclosingElement, label: 'enclosingElement'); | |
| _writeDocumentation(e.documentationComment); | |
| _writeMetadata(e.metadata); | |
| _writeSinceSdkVersion(e); | |
| _writeTypeInferenceError(e.typeInferenceError); | |
| _writeElementList( | |
| 'typeParameters', | |
| e, | |
| e.typeParameters, | |
| _writeTypeParameterElement, | |
| ); | |
| _writeElementList( | |
| 'formalParameters', | |
| e, | |
| e.formalParameters, | |
| _writeFormalParameterElement, | |
| ); | |
| _writeReturnType(e.returnType); | |
| // _writeNonSyntheticElement(e); | |
| }); | |
| // if (e.isSynthetic && e.enclosingElement is EnumElementImpl) { | |
| // expect(e.name, 'toString'); | |
| // expect(e.nonSynthetic2, same(e.enclosingElement)); | |
| // } else { | |
| // _assertNonSyntheticElementSelf(e); | |
| // } | |
| } | |
| void _writeMethodFragment(MethodFragmentImpl f) { | |
| _sink.writeIndentedLine(() { | |
| _writeObjectId(f); | |
| _sink.writeHeaderFlags(f.flagsForTesting); | |
| _assertHasExactlyOneTrue([f.isOriginDeclaration, f.isOriginInterface]); | |
| _writeFragmentName(f); | |
| _writeFragmentBodyModifiers(f); | |
| }); | |
| _sink.withIndent(() { | |
| _writeElementReference('element', f.element); | |
| _writeFragmentReference('previousFragment', f.previousFragment); | |
| _writeFragmentReference('nextFragment', f.nextFragment); | |
| _writeDocumentation(f.documentationComment); | |
| _writeMetadata(f.metadata); | |
| if (configuration.withCodeRanges) { | |
| _sink.writelnWithIndent('codeOffset: ${f.codeOffset}'); | |
| _sink.writelnWithIndent('codeLength: ${f.codeLength}'); | |
| } | |
| _writeFragmentList( | |
| 'typeParameters', | |
| f, | |
| f.typeParameters, | |
| _writeTypeParameterFragment, | |
| ); | |
| _writeFragmentList( | |
| 'formalParameters', | |
| f, | |
| f.formalParameters, | |
| _writeFormalParameterFragment, | |
| ); | |
| // _writeReturnType(f.returnType); | |
| // _writeNonSyntheticElement(f); | |
| // _writeAugmentationTarget(f); | |
| // _writeAugmentation(f); | |
| }); | |
| } | |
| void _writeNamespaceCombinator(NamespaceCombinator e) { | |
| _sink.writeIndentedLine(() { | |
| switch (e) { | |
| case ShowElementCombinator(): | |
| _sink.write('show: '); | |
| _sink.write(e.shownNames.join(', ')); | |
| case HideElementCombinator(): | |
| _sink.write('hide: '); | |
| _sink.write(e.hiddenNames.join(', ')); | |
| } | |
| }); | |
| } | |
| void _writeNamespaceCombinators(List<NamespaceCombinator> elements) { | |
| _writeList('combinators', elements, _writeNamespaceCombinator); | |
| } | |
| void _writeObjectId(Object object) { | |
| _sink.write('${_idMap[object]} '); | |
| } | |
| void _writePartInclude(PartIncludeImpl e) { | |
| _sink.writelnWithIndent(_idMap[e]); | |
| _sink.withIndent(() { | |
| var uri = e.uri; | |
| _sink.writeIndentedLine(() { | |
| _sink.write('uri: '); | |
| _writeDirectiveUri(e.uri); | |
| }); | |
| _sink.writelnWithIndent('partKeywordOffset: ${e.partKeywordOffset}'); | |
| _writeMetadata(e.metadata); | |
| if (uri is DirectiveUriWithUnitImpl) { | |
| _elementPrinter.writeNamedFragment('unit', uri.libraryFragment); | |
| } | |
| }); | |
| } | |
| void _writePrefixElement(PrefixElementImpl e) { | |
| _sink.writeIndent(); | |
| _elementPrinter.writeElement2(e); | |
| _sink.withIndent(() { | |
| _sink.writeIndentedLine(() { | |
| _sink.write('fragments: '); | |
| _sink.write( | |
| e.fragments | |
| .map((f) { | |
| expect(f.element, same(e)); | |
| expect(f.name, e.name); | |
| return '@${f.nameOffset}'; | |
| }) | |
| .join(' '), | |
| ); | |
| }); | |
| }); | |
| } | |
| void _writeReturnType(DartType type) { | |
| if (configuration.withReturnType) { | |
| _writeType('returnType', type); | |
| } | |
| } | |
| void _writeSetterElement(SetterElementImpl e) { | |
| var variable = e.variable; | |
| var variableEnclosing = variable.enclosingElement; | |
| if (variableEnclosing is LibraryElement) { | |
| expect(variableEnclosing.topLevelVariables, contains(variable)); | |
| } else if (variableEnclosing is InterfaceElement) { | |
| // TODO(augmentations): Remove the invocations of `field.baseElement`. | |
| // There shouldn't be any members in the list of fields. | |
| expect( | |
| variableEnclosing.fields.map((field) => field.baseElement), | |
| contains(variable.baseElement), | |
| ); | |
| } | |
| // if (e.isSynthetic) { | |
| // expect(e.nameOffset, -1); | |
| // } else { | |
| // expect(e.nameOffset, isPositive); | |
| // _assertNonSyntheticElementSelf(e); | |
| // } | |
| _sink.writeIndentedLine(() { | |
| _sink.writeHeaderFlags(e.flagsForTesting); | |
| _assertHasExactlyOneTrue([ | |
| e.isOriginDeclaration, | |
| e.isOriginInterface, | |
| e.isOriginVariable, | |
| ]); | |
| _writeElementName(e); | |
| }); | |
| _sink.withIndent(() { | |
| _writeReference(e); | |
| _writeFragmentReference('firstFragment', e.firstFragment); | |
| _writeFragmentReference( | |
| 'previousFragmentOfDifferentKind', | |
| e.previousFragmentOfDifferentKind, | |
| ); | |
| _writeDocumentation(e.documentationComment); | |
| _writeMetadata(e.metadata); | |
| _writeSinceSdkVersion(e); | |
| expect(e.typeParameters, isEmpty); | |
| _writeElementList( | |
| 'formalParameters', | |
| e, | |
| e.formalParameters, | |
| _writeFormalParameterElement, | |
| ); | |
| _writeReturnType(e.returnType); | |
| _writeElementReference('variable', e.variable); | |
| // _writeNonSyntheticElement(e); | |
| }); | |
| } | |
| void _writeSetterFragment(SetterFragmentImpl f) { | |
| // if (f.isSynthetic) { | |
| // expect(f.nameOffset, -1); | |
| // } else { | |
| // expect(f.nameOffset, isPositive); | |
| // _assertNonSyntheticElementSelf(f); | |
| // } | |
| _sink.writeIndentedLine(() { | |
| _writeObjectId(f); | |
| _sink.writeHeaderFlags(f.flagsForTesting); | |
| _assertHasExactlyOneTrue([ | |
| f.isOriginDeclaration, | |
| f.isOriginInterface, | |
| f.isOriginVariable, | |
| ]); | |
| _writeFragmentName(f); | |
| // _writeBodyModifiers(f); | |
| }); | |
| _sink.withIndent(() { | |
| _writeElementReference('element', f.element); | |
| _writeDocumentation(f.documentationComment); | |
| _writeMetadata(f.metadata); | |
| // _writeCodeRange(f); | |
| _writeFragmentReference('inducingVariable', f.inducingVariable); | |
| expect(f.typeParameters, isEmpty); | |
| _writeFragmentList( | |
| 'formalParameters', | |
| f, | |
| f.formalParameters, | |
| _writeFormalParameterFragment, | |
| ); | |
| // _writeReturnType(f.returnType); | |
| // _writeNonSyntheticElement(f); | |
| _writeFragmentReference('previousFragment', f.previousFragment); | |
| _writeFragmentReference('nextFragment', f.nextFragment); | |
| }); | |
| } | |
| void _writeSinceSdkVersion(Element element) { | |
| if (element.sinceSdkVersion case var sinceSdkVersion?) { | |
| _sink.writelnWithIndent('sinceSdkVersion: $sinceSdkVersion'); | |
| } | |
| } | |
| void _writeTopLevelFunctionElement(TopLevelFunctionElementImpl e) { | |
| expect(e.isStatic, isTrue); | |
| _sink.writeIndentedLine(() { | |
| // _sink.writeIf(e.isAugmentation, 'augment '); | |
| _sink.writeHeaderFlags(e.flagsForTesting); | |
| _assertHasExactlyOneTrue([e.isOriginDeclaration, e.isOriginLoadLibrary]); | |
| _writeElementName(e); | |
| // _writeBodyModifiers(e); | |
| }); | |
| _sink.withIndent(() { | |
| _writeReference(e); | |
| _writeFragmentReference('firstFragment', e.firstFragment); | |
| _writeFragmentReference( | |
| 'previousFragmentOfDifferentKind', | |
| e.previousFragmentOfDifferentKind, | |
| ); | |
| _writeDocumentation(e.documentationComment); | |
| _writeMetadata(e.metadata); | |
| _writeSinceSdkVersion(e); | |
| // _writeCodeRange(e); | |
| _writeElementList( | |
| 'typeParameters', | |
| e, | |
| e.typeParameters, | |
| _writeTypeParameterElement, | |
| ); | |
| _writeElementList( | |
| 'formalParameters', | |
| e, | |
| e.formalParameters, | |
| _writeFormalParameterElement, | |
| ); | |
| _writeType('returnType', e.returnType); | |
| // _writeAugmentationTarget(e); | |
| // _writeAugmentation(e); | |
| }); | |
| } | |
| void _writeTopLevelFunctionFragment(TopLevelFunctionFragmentImpl f) { | |
| // expect(e.isStatic, isTrue); | |
| _sink.writeIndentedLine(() { | |
| _writeObjectId(f); | |
| // _sink.writeIf(e.isAugmentation, 'augment '); | |
| // _sink.writeIf(e.isExternal, 'external '); | |
| _sink.writeHeaderFlags(f.flagsForTesting); | |
| _assertHasExactlyOneTrue([f.isOriginDeclaration, f.isOriginLoadLibrary]); | |
| _writeFragmentName(f); | |
| // _writeBodyModifiers(e); | |
| }); | |
| _sink.withIndent(() { | |
| _writeElementReference('element', f.element); | |
| _writeDocumentation(f.documentationComment); | |
| _writeMetadata(f.metadata); | |
| _writeFragmentReference('previousFragment', f.previousFragment); | |
| _writeFragmentReference('nextFragment', f.nextFragment); | |
| // _writeCodeRange(e); | |
| _writeFragmentList( | |
| 'typeParameters', | |
| f, | |
| f.typeParameters, | |
| _writeTypeParameterFragment, | |
| ); | |
| _writeFragmentList( | |
| 'formalParameters', | |
| f, | |
| f.formalParameters, | |
| _writeFormalParameterFragment, | |
| ); | |
| // _writeType('returnType', e.returnType); | |
| // _writeAugmentationTarget(e); | |
| // _writeAugmentation(e); | |
| }); | |
| // _assertNonSyntheticElementSelf(f); | |
| } | |
| void _writeTopLevelVariableElement(TopLevelVariableElementImpl e) { | |
| DartType type = e.type; | |
| expect(type, isNotNull); | |
| _sink.writeIndentedLine(() { | |
| _sink.writeHeaderFlags(e.flagsForTesting); | |
| _assertHasExactlyOneTrue([e.isOriginDeclaration, e.isOriginGetterSetter]); | |
| _writeElementName(e); | |
| }); | |
| _sink.withIndent(() { | |
| _writeReference(e); | |
| _writeFragmentReference('firstFragment', e.firstFragment); | |
| _writeFragmentReference( | |
| 'previousFragmentOfDifferentKind', | |
| e.previousFragmentOfDifferentKind, | |
| ); | |
| _writeDocumentation(e.documentationComment); | |
| _writeMetadata(e.metadata); | |
| _writeSinceSdkVersion(e); | |
| _writeTypeInferenceError(e.typeInferenceError); | |
| _writeType('type', e.type); | |
| // _writeShouldUseTypeForInitializerInference(e); | |
| _writeVariableElementConstantInitializer(e); | |
| // _writeNonSyntheticElement(e); | |
| _writeElementReference('getter', e.getter); | |
| _writeElementReference('setter', e.setter); | |
| }); | |
| } | |
| void _writeTopLevelVariableFragment(TopLevelVariableFragmentImpl f) { | |
| // DartType type = f.type; | |
| // expect(type, isNotNull); | |
| // if (f.isSynthetic) { | |
| // expect(f.nameOffset, -1); | |
| // } else { | |
| // if (!f.isAugmentation) { | |
| // expect(f.getter, isNotNull); | |
| // } | |
| // expect(f.nameOffset, isPositive); | |
| // _assertNonSyntheticElementSelf(f); | |
| // } | |
| _sink.writeIndentedLine(() { | |
| _writeObjectId(f); | |
| _sink.writeHeaderFlags(f.flagsForTesting); | |
| _assertHasExactlyOneTrue([f.isOriginDeclaration, f.isOriginGetterSetter]); | |
| _writeFragmentName(f); | |
| }); | |
| _sink.withIndent(() { | |
| _writeElementReference('element', f.element); | |
| _writeDocumentation(f.documentationComment); | |
| _writeMetadata(f.metadata); | |
| // _writeCodeRange(f); | |
| // _writeType('type', f.type); | |
| // _writeShouldUseTypeForInitializerInference(f); | |
| _writeVariableFragmentInitializer(f); | |
| // _writeNonSyntheticElement(f); | |
| _writeFragmentReference('inducedGetter', f.inducedGetter); | |
| _writeFragmentReference('inducedSetter', f.inducedSetter); | |
| _writeFragmentReference('previousFragment', f.previousFragment); | |
| _writeFragmentReference('nextFragment', f.nextFragment); | |
| }); | |
| } | |
| void _writeType(String name, DartType type) { | |
| _elementPrinter.writeNamedType(name, type); | |
| // if (configuration.withFunctionTypeParameters) { | |
| // if (type is FunctionType) { | |
| // _sink.withIndent(() { | |
| // // TODO(brianwilkerson): We need to define `parameters2` to return | |
| // // `List<ParmaeterElement2>`. | |
| // _writeElements('parameters', type, type.parameters2, _writeFormalParameterFragment); | |
| // }); | |
| // } | |
| // } | |
| } | |
| void _writeTypeAliasElement(TypeAliasElementImpl e) { | |
| _sink.writeIndentedLine(() { | |
| _sink.writeHeaderFlags(e.flagsForTesting); | |
| _writeElementName(e); | |
| }); | |
| _sink.withIndent(() { | |
| _writeReference(e); | |
| _writeFragmentReference('firstFragment', e.firstFragment); | |
| _writeDocumentation(e.documentationComment); | |
| _writeMetadata(e.metadata); | |
| _writeSinceSdkVersion(e); | |
| // _writeCodeRange(e); | |
| _writeElementList( | |
| 'typeParameters', | |
| e, | |
| e.typeParameters, | |
| _writeTypeParameterElement, | |
| ); | |
| var aliasedType = e.aliasedType; | |
| _writeType('aliasedType', aliasedType); | |
| // var aliasedElement = e.aliasedElement2; | |
| // if (aliasedElement is GenericFunctionTypeElementImpl) { | |
| // _sink.writelnWithIndent('aliasedElement: GenericFunctionTypeElement'); | |
| // _sink.withIndent(() { | |
| // _writeElementList('typeParameters', aliasedElement, aliasedElement.typeParameters2, _writeTypeParameterElement); | |
| // _writeElementList('', aliasedElement, aliasedElement.parameters2, _writeFormalParameterElement); | |
| // _writeType('returnType', aliasedElement.returnType); | |
| // }); | |
| // } | |
| // _writeAugmentationTarget(e); | |
| // _writeAugmentation(e); | |
| }); | |
| } | |
| void _writeTypeAliasFragment(TypeAliasFragmentImpl f) { | |
| _sink.writeIndentedLine(() { | |
| _writeObjectId(f); | |
| // _sink.writeIf(e.isAugmentation, 'augment '); | |
| // _sink.writeIf(e.isFunctionTypeAliasBased, 'functionTypeAliasBased '); | |
| // _sink.writeIf(!e.isSimplyBounded, 'notSimplyBounded '); | |
| _sink.writeHeaderFlags(f.flagsForTesting); | |
| _writeFragmentName(f); | |
| }); | |
| _sink.withIndent(() { | |
| _writeElementReference('element', f.element); | |
| _writeDocumentation(f.documentationComment); | |
| _writeMetadata(f.metadata); | |
| // _writeCodeRange(e); | |
| _writeFragmentList( | |
| 'typeParameters', | |
| f, | |
| f.typeParameters, | |
| _writeTypeParameterFragment, | |
| ); | |
| // var aliasedType = e.aliasedType; | |
| // _writeType('aliasedType', aliasedType); | |
| // var aliasedElement = e.aliasedElement2; | |
| // if (aliasedElement is GenericFunctionTypeElementImpl) { | |
| // _sink.writelnWithIndent('aliasedElement: GenericFunctionTypeElement'); | |
| // _sink.withIndent(() { | |
| // _writeElementList('typeParameters', aliasedElement, aliasedElement.typeParameters2, _writeTypeParameterElement); | |
| // _writeElementList('', aliasedElement, aliasedElement.parameters2, _writeFormalParameterElement); | |
| // _writeType('returnType', aliasedElement.returnType); | |
| // }); | |
| // } | |
| // _writeAugmentationTarget(e); | |
| // _writeAugmentation(e); | |
| }); | |
| // _assertNonSyntheticElementSelf(e); | |
| } | |
| void _writeTypeInferenceError(TopLevelInferenceError? error) { | |
| switch (error) { | |
| case null: | |
| break; | |
| case TopLevelInferenceErrorDependencyCycle(:var cycle): | |
| _sink.writelnWithIndent('typeInferenceError: dependencyCycle'); | |
| _sink.withIndent(() { | |
| _sink.writelnWithIndent('arguments: $cycle'); | |
| }); | |
| case TopLevelInferenceErrorDifferentGetterAndSetterTypes( | |
| :var getterType, | |
| :var setterType, | |
| ): | |
| _sink.writelnWithIndent( | |
| 'typeInferenceError: differentGetterAndSetterTypes', | |
| ); | |
| _sink.withIndent(() { | |
| _sink.writelnWithIndent('getterType: $getterType'); | |
| _sink.writelnWithIndent('setterType: $setterType'); | |
| }); | |
| case TopLevelInferenceErrorNoCombinedSuperSignature(): | |
| _sink.writelnWithIndent( | |
| 'typeInferenceError: overrideNoCombinedSuperSignature', | |
| ); | |
| } | |
| } | |
| void _writeTypeParameterElement(TypeParameterElement e) { | |
| _sink.writeIndentedLine(() { | |
| _writeObjectId(e); | |
| // _sink.write('${e.variance.name} '); | |
| _writeElementName(e); | |
| }); | |
| _sink.withIndent(() { | |
| _writeFragmentReference('firstFragment', e.firstFragment); | |
| var bound = e.bound; | |
| if (bound != null) { | |
| _writeType('bound', bound); | |
| } | |
| if (configuration.withDefaultType) { | |
| var defaultType = (e as TypeParameterElementImpl).defaultType; | |
| if (defaultType != null) { | |
| _writeType('defaultType', defaultType); | |
| } | |
| } | |
| _writeMetadata(e.metadata); | |
| }); | |
| } | |
| void _writeTypeParameterFragment(TypeParameterFragmentImpl f) { | |
| _sink.writeIndentedLine(() { | |
| _writeObjectId(f); | |
| // _sink.write('${e.variance.name} '); | |
| _sink.writeHeaderFlags(f.flagsForTesting); | |
| _writeFragmentName(f); | |
| }); | |
| _sink.withIndent(() { | |
| _writeElementReference('element', f.element); | |
| _writeFragmentReference('previousFragment', f.previousFragment); | |
| _writeFragmentReference('nextFragment', f.nextFragment); | |
| // var bound = e.bound; | |
| // if (bound != null) { | |
| // _writeType('bound', bound); | |
| // } | |
| // var defaultType = e.defaultType; | |
| // if (defaultType != null) { | |
| // _writeType('defaultType', defaultType); | |
| // } | |
| _writeMetadata(f.metadata); | |
| }); | |
| // _assertNonSyntheticElementSelf(f); | |
| } | |
| void _writeVariableElementConstantInitializer(VariableElementImpl e) { | |
| if (e.constantInitializerData case var initializer?) { | |
| _sink.writelnWithIndent('constantInitializer'); | |
| _sink.withIndent(() { | |
| _writeFragmentReference('fragment', initializer.fragment); | |
| _writeConstantInitializerExpression( | |
| 'expression', | |
| initializer.expression, | |
| ); | |
| }); | |
| } | |
| } | |
| void _writeVariableFragmentInitializer(VariableFragment f) { | |
| f as VariableFragmentImpl; | |
| if (f.initializer case var initializer?) { | |
| _writeConstantInitializerExpression('initializer', initializer); | |
| } | |
| } | |
| } |