| // 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/element/element.dart'; |
| import 'package:analyzer/src/dart/element/field_name_non_promotability_info.dart'; |
| import 'package:analyzer/src/dart/element/member.dart'; |
| import 'package:analyzer/src/summary2/export.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 withAugmentedWithoutAugmentation = false; |
| bool withCodeRanges = false; |
| bool withConstantInitializers = true; |
| bool withConstructors = true; |
| 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 withPropertyLinking = 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 ClassElementImpl(): |
| return classNames.contains(o.name); |
| case ClassElement(): |
| return classNames.contains(o.name3); |
| 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.name3); |
| case ConstructorElement(): |
| return false; |
| case EnumElement(): |
| return enumNames.contains(o.name3); |
| case ExtensionTypeElement(): |
| return extensionTypeNames.contains(o.name3); |
| case FieldElement(): |
| return fieldNames.isEmpty || fieldNames.contains(o.name3); |
| case MixinElement(): |
| return mixinNames.contains(o.name3); |
| 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; |
| final _IdMap _idMap = _IdMap(); |
| |
| _AbstractElementWriter({ |
| required TreeStringSink sink, |
| required ElementPrinter elementPrinter, |
| required this.configuration, |
| }) : _sink = sink, |
| _elementPrinter = elementPrinter; |
| |
| 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.library2.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 _writeExportedReferences(LibraryElementImpl e) { |
| var exportedReferences = e.exportedReferences.toList(); |
| exportedReferences.sortBy((e) => e.reference.toString()); |
| |
| for (var exported in exportedReferences) { |
| _sink.writeIndentedLine(() { |
| if (exported is ExportedReferenceDeclared) { |
| _sink.write('declared '); |
| } else if (exported is ExportedReferenceExported) { |
| _sink.write('exported${exported.locations} '); |
| } |
| _elementPrinter.writeReference(exported.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(); |
| node.accept(_createAstPrinter()); |
| } |
| |
| void _writeReference(ElementImpl e) { |
| if (!configuration.withReferences) { |
| return; |
| } |
| |
| if (e.reference case var reference?) { |
| _sink.writeIndentedLine(() { |
| _sink.write('reference: '); |
| _elementPrinter.writeReference(reference); |
| }); |
| } |
| } |
| |
| void _writeReference2(ElementImpl2 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.enclosingElement2, isNull); |
| |
| _sink.writelnWithIndent('library'); |
| _sink.withIndent(() { |
| _writeReference(e as ElementImpl); |
| |
| var name = e.name; |
| if (name.isNotEmpty) { |
| _sink.writelnWithIndent('name: $name'); |
| } |
| |
| _writeDocumentation(e.documentationComment); |
| _writeMetadata(e.metadata2); |
| _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.isSynthetic) { |
| return false; |
| } |
| return true; |
| }).toList(), |
| _writeGetterElement, |
| ); |
| |
| _writeElementList('setters', e, e.setters, _writeSetterElement); |
| _writeElementList( |
| 'functions', |
| e, |
| e.topLevelFunctions, |
| _writeTopLevelFunctionElement, |
| ); |
| |
| if (configuration.withExportScope) { |
| _sink.writelnWithIndent('exportedReferences'); |
| _sink.withIndent(() { |
| _writeExportedReferences(e); |
| }); |
| _sink.writelnWithIndent('exportNamespace'); |
| _sink.withIndent(() { |
| _writeExportNamespace(e); |
| }); |
| } |
| |
| _writeFieldNameNonPromotabilityInfo(e.fieldNameNonPromotabilityInfo); |
| }); |
| } |
| |
| void _assertNonSyntheticElementSelf(Element element) { |
| expect(element.isSynthetic, isFalse); |
| expect(element.nonSynthetic2, same(element)); |
| } |
| |
| void _writeConstantInitializerExpression(String name, Expression expression) { |
| 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 ConstructorElementImpl2; |
| |
| // 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.writeIf(e.isSynthetic, 'synthetic '); |
| _sink.writeIf(e.isExternal, 'external '); |
| _sink.writeIf(e.isConst, 'const '); |
| _sink.writeIf(e.isFactory, 'factory '); |
| expect(e.isAbstract, isFalse); |
| _writeElementName(e); |
| }); |
| |
| _sink.withIndent(() { |
| _writeFragmentReference('firstFragment', e.firstFragment); |
| _writeDocumentation(e.documentationComment); |
| _writeMetadata(e.metadata2); |
| _writeSinceSdkVersion(e); |
| // _writeDisplayName(e); |
| |
| _writeElementList( |
| 'formalParameters', |
| e, |
| e.formalParameters, |
| _writeFormalParameterElement, |
| ); |
| |
| _writeList('constantInitializers', e.constantInitializers, _writeNode); |
| |
| var superConstructor = e.superConstructor2; |
| if (superConstructor != null) { |
| var enclosingElement = superConstructor.enclosingElement2; |
| if (enclosingElement is ClassElementImpl2 && |
| !enclosingElement.isDartCoreObject) { |
| _writeElementReference('superConstructor', superConstructor); |
| } |
| } |
| |
| var redirectedConstructor = e.redirectedConstructor2; |
| 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) { |
| // Check that the reference exists, and filled with the element. |
| var reference = (f as ConstructorElementImpl).reference; |
| if (reference == null) { |
| fail('Every constructor must have a reference.'); |
| } |
| |
| _sink.writeIndentedLine(() { |
| _sink.writeIf(f.isAugmentation, 'augment '); |
| _sink.writeIf(f.isSynthetic, 'synthetic '); |
| _sink.writeIf(f.isExternal, 'external '); |
| _sink.writeIf(f.isConst, 'const '); |
| _sink.writeIf(f.isFactory, 'factory '); |
| expect(f.isAbstract, isFalse); |
| _writeFragmentName(f); |
| }); |
| |
| _sink.withIndent(() { |
| _writeFragmentReference('reference', f); |
| _writeElementReference('element', f.element); |
| _writeDocumentation(f.documentationComment); |
| _writeMetadata(f.metadata2); |
| _writeFragmentCodeRange(f); |
| // _writeDisplayName(f); |
| |
| _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'); |
| } |
| |
| _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 Element>( |
| String name, |
| Element 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) { |
| if (element is LibraryImport || element is LibraryExport) { |
| // These are only accidentally subtypes of `Element2` and don't have |
| // an enclosing element. |
| } else if (element is PrefixElement) { |
| // Asking a `PrefixElement2` for it's enclosing element currently |
| // throws an exception (because it doesn't have an enclosing |
| // element, only an enclosing fragment). |
| } else { |
| if (expectedEnclosingElement is Member) { |
| expectedEnclosingElement = expectedEnclosingElement.baseElement; |
| } |
| expect(element.enclosingElement2, expectedEnclosingElement); |
| } |
| write(element); |
| } |
| }); |
| } |
| } |
| |
| void _writeElementName(Element e) { |
| var name = e.name3 ?? '<null-name>'; |
| _sink.write(name); |
| |
| switch (e) { |
| case MethodElement(): |
| if (e.name3 == '-' && e.formalParameters.isEmpty) { |
| expect(e.lookupName, 'unary-'); |
| } else { |
| expect(e.lookupName, e.name3); |
| } |
| case SetterElement(): |
| if (e.name3 case var name?) { |
| expect(e.lookupName, '$name='); |
| } else { |
| expect(e.lookupName, isNull); |
| } |
| default: |
| expect(e.lookupName, e.name3); |
| } |
| } |
| |
| 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(FieldElementImpl2 e) { |
| e as FieldElement2OrMember; |
| 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.writeIf(e.isSynthetic, 'synthetic '); |
| _sink.writeIf(e.isStatic, 'static '); |
| _sink.writeIf(e.isAbstract, 'abstract '); |
| _sink.writeIf(e.isCovariant, 'covariant '); |
| _sink.writeIf(e.isExternal, 'external '); |
| _sink.writeIf(e.isLate, 'late '); |
| _sink.writeIf(e.isFinal, 'final '); |
| _sink.writeIf(e.isConst, 'const '); |
| _sink.writeIf(e.isEnumConstant, 'enumConstant '); |
| _sink.writeIf(e.isPromotable, 'promotable '); |
| _sink.writeIf(e.hasInitializer, 'hasInitializer '); |
| |
| _writeElementName(e); |
| }); |
| |
| // void writeLinking() { |
| // if (configuration.withPropertyLinking) { |
| // _sink.writelnWithIndent('id: ${_idMap[e]}'); |
| |
| // var getter = e.getter; |
| // if (getter != null) { |
| // _sink.writelnWithIndent('getter: ${_idMap[getter]}'); |
| // } |
| |
| // var setter = e.setter; |
| // if (setter != null) { |
| // _sink.writelnWithIndent('setter: ${_idMap[setter]}'); |
| // } |
| // } |
| // } |
| |
| _sink.withIndent(() { |
| _writeFragmentReference('firstFragment', e.firstFragment); |
| if (e.hasEnclosingTypeParameterReference) { |
| _sink.writelnWithIndent('hasEnclosingTypeParameterReference: true'); |
| } |
| // _writeDocumentation(e.documentationComment); |
| // _writeMetadata(e.metadata); |
| _writeSinceSdkVersion(e); |
| // _writeCodeRange(e); |
| // _writeTypeInferenceError(e); |
| _writeType('type', e.type); |
| // _writeShouldUseTypeForInitializerInference(e); |
| _writeVariableElementConstantInitializer(e); |
| // _writeNonSyntheticElement(e); |
| // writeLinking(); |
| _writeElementReference('getter', e.getter2); |
| _writeElementReference('setter', e.setter2); |
| }); |
| } |
| |
| void _writeFieldFragment(FieldFragment 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(() { |
| _sink.writeIf(f.isAugmentation, 'augment '); |
| _sink.writeIf(f.isSynthetic, 'synthetic '); |
| _sink.writeIf(f.hasInitializer, 'hasInitializer '); |
| |
| _writeFragmentName(f); |
| }); |
| |
| // void writeLinking() { |
| // if (configuration.withPropertyLinking) { |
| // _sink.writelnWithIndent('id: ${_idMap[f]}'); |
| |
| // var getter = f.getter2; |
| // if (getter != null) { |
| // _sink.writelnWithIndent('getter: ${_idMap[getter]}'); |
| // } |
| |
| // var setter = f.setter2; |
| // if (setter != null) { |
| // _sink.writelnWithIndent('setter: ${_idMap[setter]}'); |
| // } |
| // } |
| // } |
| |
| _sink.withIndent(() { |
| _writeFragmentReference('reference', f); |
| _writeElementReference('element', f.element); |
| // _writeDocumentation(f.documentationComment); |
| // _writeMetadata(f.metadata); |
| // _writeSinceSdkVersion(f.sinceSdkVersion); |
| // _writeCodeRange(f); |
| // _writeTypeInferenceError(f); |
| // _writeType('type', f.type); |
| // _writeShouldUseTypeForInitializerInference(f); |
| _writeVariableFragmentInitializer(f); |
| // _writeNonSyntheticElement(f); |
| // writeLinking(); |
| _writeFragmentReference('previousFragment', f.previousFragment); |
| _writeFragmentReference('nextFragment', f.nextFragment); |
| _writeFragmentReference('getter2', f.getter2); |
| _writeFragmentReference('setter2', f.setter2); |
| }); |
| } |
| |
| void _writeFormalParameterElement(FormalParameterElement e) { |
| e as FormalParameterElementMixin; |
| // if (e.isNamed && e.enclosingElement2 is ExecutableElement) { |
| // expect(e.reference, isNotNull); |
| // } else { |
| // expect(e.reference, isNull); |
| // } |
| |
| _sink.writeIndentedLine(() { |
| 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 '); |
| } |
| |
| if (e is ConstVariableElement) { |
| _sink.write('default '); |
| } |
| |
| _sink.writeIf(e.isConst, 'const '); |
| _sink.writeIf(e.isCovariant, 'covariant '); |
| _sink.writeIf(e.isFinal, 'final '); |
| _sink.writeIf(e.hasImplicitType, 'hasImplicitType '); |
| |
| if (e is FieldFormalParameterElementImpl) { |
| _sink.write('this.'); |
| } else if (e is SuperFormalParameterElementImpl) { |
| _sink.writeIf(e.hasDefaultValue, 'hasDefaultValue '); |
| _sink.write('super.'); |
| } |
| |
| _writeElementName(e); |
| }); |
| |
| _sink.withIndent(() { |
| _writeFragmentReference('firstFragment', e.firstFragment); |
| _writeType('type', e.type); |
| _writeMetadata(e.metadata2); |
| _writeSinceSdkVersion(e); |
| // _writeCodeRange(e); |
| _writeElementList( |
| 'typeParameters', |
| e, |
| e.typeParameters2, |
| _writeTypeParameterElement, |
| ); |
| _writeElementList( |
| 'formalParameters', |
| e, |
| e.formalParameters, |
| _writeFormalParameterElement, |
| ); |
| _writeVariableElementConstantInitializer(e); |
| // _writeNonSyntheticElement(e); |
| // _writeFieldFormalParameterField(e); |
| // _writeSuperConstructorParameter(e); |
| }); |
| } |
| |
| void _writeFormalParameterFragment(FormalParameterFragment f) { |
| // if (f.isNamed && f.enclosingFragment is ExecutableFragment) { |
| // expect(f.reference, isNotNull); |
| // } else { |
| // expect(f.reference, isNull); |
| // } |
| |
| _sink.writeIndentedLine(() { |
| // 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 '); |
| // } |
| |
| if (f is ConstVariableElement) { |
| _sink.write('default '); |
| } |
| |
| // _sink.writeIf(f.isConst, 'const '); |
| // _sink.writeIf(f.isCovariant, 'covariant '); |
| // _sink.writeIf(f.isFinal, 'final '); |
| |
| if (f is FieldFormalParameterElementImpl) { |
| _sink.write('this.'); |
| } else if (f is SuperFormalParameterElementImpl) { |
| // _sink.writeIf(f.hasDefaultValue, 'hasDefaultValue '); |
| _sink.write('super.'); |
| } |
| |
| _writeFragmentName(f); |
| }); |
| |
| _sink.withIndent(() { |
| _writeFragmentReference('reference', f); |
| _writeElementReference('element', f.element); |
| // _writeType('type', f.type); |
| _writeMetadata(f.metadata2); |
| // _writeCodeRange(f); |
| // _writeTypeParameterElements(e.typeParameters); |
| // _writeFragmentList('parameters', f, f.parameters2, _writeFormalParameterFragments); |
| _writeVariableFragmentInitializer(f); |
| // _writeNonSyntheticElement(e); |
| // _writeFieldFormalParameterField(e); |
| // _writeSuperConstructorParameter(e); |
| }); |
| } |
| |
| void _writeFragentBodyModifiers(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, '*'); |
| |
| if (f is ExecutableElementImpl && f.invokesSuperSelf) { |
| _sink.write(' invokesSuperSelf'); |
| } |
| } |
| |
| void _writeFragmentBestOffset(Fragment f) { |
| // Usually the name offset is available. |
| // And then the offset must be the same. |
| if (f.nameOffset2 case var nameOffset?) { |
| expect(f.offset, nameOffset); |
| return; |
| } |
| |
| switch (f) { |
| case ConstructorFragment(): |
| if (f.isSynthetic) { |
| expect(f.offset, f.enclosingFragment!.offset); |
| return; |
| } else { |
| expect(f.offset, f.typeNameOffset); |
| return; |
| } |
| case FieldFragment(): |
| if (f.isSynthetic) { |
| // TODO(scheglov): Why not the offset of the getter/setter? |
| expect(f.offset, f.enclosingFragment!.offset); |
| return; |
| } |
| case FormalParameterFragment(): |
| if (f.enclosingFragment case SetterFragment setter) { |
| if (setter.isSynthetic) { |
| var variableOffset = setter.variable3!.offset; |
| expect(f.offset, variableOffset); |
| return; |
| } |
| } |
| case GetterFragment(): |
| expect(f.isSynthetic, isTrue); |
| if (f.isSynthetic) { |
| expect(f.offset, f.variable3!.offset); |
| return; |
| } |
| case SetterFragment(): |
| if (f.isSynthetic) { |
| var variableOffset = f.variable3!.offset; |
| expect(f.offset, variableOffset); |
| expect(f.formalParameters.single.offset, variableOffset); |
| return; |
| } |
| case LibraryFragment(): |
| if (f.element.firstFragment != f) { |
| expect(f.offset, 0); |
| return; |
| } else if (f.offset == 0) { |
| return; |
| } |
| } |
| |
| // If a non-standard case, write the offset. |
| _sink.write(' (offset=${f.offset})'); |
| } |
| |
| void _writeFragmentCodeRange(Fragment f) { |
| if (configuration.withCodeRanges) { |
| if (f is ElementImpl) { |
| var e = f as ElementImpl; |
| if (!e.isSynthetic) { |
| _sink.writelnWithIndent('codeOffset: ${e.codeOffset}'); |
| _sink.writelnWithIndent('codeLength: ${e.codeLength}'); |
| } |
| } |
| } |
| } |
| |
| 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(Fragment f) { |
| if (f.name2 == null) { |
| expect(f.nameOffset2, isNull); |
| } |
| |
| _sink.write(f.name2 ?? '<null-name>'); |
| if (f.nameOffset2 case var nameOffset?) { |
| _sink.write(' @$nameOffset'); |
| } |
| |
| _writeFragmentBestOffset(f); |
| } |
| |
| void _writeFragmentReference(String name, Fragment? f) { |
| if (!configuration.withReferences) { |
| return; |
| } |
| |
| if (f == null) { |
| return; |
| } |
| |
| if (f is CompilationUnitElementImpl) { |
| _sink.writeIndentedLine(() { |
| _sink.write(name); |
| _sink.write(': '); |
| _elementPrinter.writeReference(f.reference!); |
| }); |
| return; |
| } |
| |
| var element = f as ElementImpl; |
| if (element.reference case var reference?) { |
| _sink.writeIndentedLine(() { |
| _sink.write(name); |
| _sink.write(': '); |
| _elementPrinter.writeReference(reference); |
| }); |
| } |
| } |
| |
| void _writeGetterElement(GetterElementImpl e) { |
| var variable = e.variable3; |
| if (variable != null) { |
| var variableEnclosing = variable.enclosingElement2; |
| 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.fields2.map((field) => field.baseElement), |
| contains(variable.baseElement), |
| ); |
| } |
| } |
| |
| // if (e.isSynthetic) { |
| // expect(e.nameOffset, -1); |
| // } else { |
| // expect(e.nameOffset, isPositive); |
| // _assertNonSyntheticElementSelf(e); |
| // } |
| |
| _sink.writeIndentedLine(() { |
| _sink.writeIf(e.isSynthetic, 'synthetic '); |
| _sink.writeIf(e.isStatic, 'static '); |
| _sink.writeIf(e.isAbstract, 'abstract '); |
| _sink.writeIf(e.isExternal, 'external '); |
| |
| _sink.write('get '); |
| _writeElementName(e); |
| }); |
| |
| // void writeLinking() { |
| // if (configuration.withPropertyLinking) { |
| // _sink.writelnWithIndent('id: ${_idMap[e]}'); |
| // if (e.variable2 case var variable?) { |
| // _sink.writelnWithIndent('variable: ${_idMap[variable]}'); |
| // } else { |
| // _sink.writelnWithIndent('variable: <null>'); |
| // } |
| // } |
| // } |
| |
| _sink.withIndent(() { |
| _writeFragmentReference('firstFragment', e.firstFragment); |
| if (e.hasEnclosingTypeParameterReference) { |
| _sink.writelnWithIndent('hasEnclosingTypeParameterReference: true'); |
| } |
| _writeDocumentation(e.documentationComment); |
| _writeMetadata(e.metadata2); |
| _writeSinceSdkVersion(e); |
| |
| expect(e.typeParameters2, isEmpty); |
| _writeElementList( |
| 'formalParameters', |
| e, |
| e.formalParameters, |
| _writeFormalParameterElement, |
| ); |
| _writeReturnType(e.returnType); |
| // _writeNonSyntheticElement(e); |
| // writeLinking(); |
| }); |
| } |
| |
| void _writeGetterFragment(GetterFragment f) { |
| var variable = f.variable3; |
| if (f.isAugmentation) { |
| expect(variable, isNull); |
| } else { |
| var enclosing = variable!.enclosingFragment; |
| switch (enclosing) { |
| case LibraryFragment(): |
| expect(enclosing.topLevelVariables2, contains(variable)); |
| case InterfaceFragment(): |
| expect(enclosing.fields2, contains(variable)); |
| } |
| } |
| |
| // if (f.isSynthetic) { |
| // expect(f.nameOffset, -1); |
| // } else { |
| // expect(f.nameOffset, isPositive); |
| // _assertNonSyntheticElementSelf(f); |
| // } |
| |
| _sink.writeIndentedLine(() { |
| _sink.writeIf(f.isAugmentation, 'augment '); |
| _sink.writeIf(f.isSynthetic, 'synthetic '); |
| |
| _sink.write('get '); |
| _writeFragmentName(f); |
| // _writeBodyModifiers(e); |
| }); |
| |
| // void writeLinking() { |
| // if (configuration.withPropertyLinking) { |
| // _sink.writelnWithIndent('id: ${_idMap[e]}'); |
| // if (e.variable2 case var variable?) { |
| // _sink.writelnWithIndent('variable: ${_idMap[variable]}'); |
| // } else { |
| // _sink.writelnWithIndent('variable: <null>'); |
| // } |
| // } |
| // } |
| |
| _sink.withIndent(() { |
| _writeFragmentReference('reference', f); |
| _writeElementReference('element', f.element); |
| _writeDocumentation(f.documentationComment); |
| _writeMetadata(f.metadata2); |
| // _writeCodeRange(f); |
| |
| // expect(f.typeParameters2, isEmpty); |
| _writeFragmentList( |
| 'formalParameters', |
| f, |
| f.formalParameters, |
| _writeFormalParameterFragment, |
| ); |
| // _writeReturnType(f.returnType); |
| // _writeNonSyntheticElement(f); |
| // writeLinking(); |
| _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(InstanceElementImpl2 e) { |
| expect(e.thisOrAncestorOfType2<InstanceElement>(), same(e)); |
| expect(e.thisOrAncestorOfType2<GetterElement>(), isNull); |
| expect(e.thisOrAncestorMatching2((_) => true), same(e)); |
| expect(e.thisOrAncestorMatching2((_) => false), isNull); |
| |
| _sink.writeIndentedLine(() { |
| switch (e) { |
| case ClassElementImpl2(): |
| _sink.writeIf(e.isAbstract, 'abstract '); |
| _sink.writeIf(e.isSealed, 'sealed '); |
| _sink.writeIf(e.isBase, 'base '); |
| _sink.writeIf(e.isInterface, 'interface '); |
| _sink.writeIf(e.isFinal, 'final '); |
| _writeNotSimplyBounded(e); |
| _sink.writeIf(e.isMixinClass, 'mixin '); |
| _sink.write('class '); |
| _sink.writeIf(e.isMixinApplication, 'alias '); |
| case EnumElementImpl2(): |
| _writeNotSimplyBounded(e); |
| _sink.write('enum '); |
| case ExtensionElementImpl2(): |
| _sink.write('extension '); |
| case ExtensionTypeElementImpl2(): |
| _sink.writeIf( |
| e.hasRepresentationSelfReference, |
| 'hasRepresentationSelfReference ', |
| ); |
| _sink.writeIf( |
| e.hasImplementsSelfReference, |
| 'hasImplementsSelfReference ', |
| ); |
| _writeNotSimplyBounded(e); |
| _sink.write('extension type '); |
| case MixinElementImpl2(): |
| _sink.writeIf(e.isBase, 'base '); |
| _writeNotSimplyBounded(e); |
| _sink.write('mixin '); |
| } |
| |
| _writeElementName(e); |
| }); |
| |
| _sink.withIndent(() { |
| _writeReference2(e); |
| _writeFragmentReference('firstFragment', e.firstFragment); |
| _writeDocumentation(e.documentationComment); |
| // _writeMetadata(e.metadata); |
| _writeSinceSdkVersion(e); |
| _writeElementList( |
| 'typeParameters', |
| e, |
| e.typeParameters2, |
| _writeTypeParameterElement, |
| ); |
| |
| void writeSupertype(InterfaceElement e) { |
| if (e.supertype case var supertype?) { |
| if (supertype.element3.name3 != 'Object' || e.mixins.isNotEmpty) { |
| _writeType('supertype', supertype); |
| } |
| } |
| } |
| |
| switch (e) { |
| case ClassElementImpl2(): |
| writeSupertype(e); |
| _elementPrinter.writeTypeList('mixins', e.mixins); |
| _elementPrinter.writeTypeList('interfaces', e.interfaces); |
| case EnumElementImpl2(): |
| writeSupertype(e); |
| _elementPrinter.writeTypeList('mixins', e.mixins); |
| _elementPrinter.writeTypeList('interfaces', e.interfaces); |
| case ExtensionElementImpl2(): |
| break; |
| case ExtensionTypeElementImpl2(): |
| expect(e.supertype, isNull); |
| _elementPrinter.writeNamedElement2( |
| 'representation', |
| e.representation2, |
| ); |
| _elementPrinter.writeNamedElement2( |
| 'primaryConstructor', |
| e.primaryConstructor2, |
| ); |
| _elementPrinter.writeNamedType('typeErasure', e.typeErasure); |
| _elementPrinter.writeTypeList('interfaces', e.interfaces); |
| case MixinElementImpl2(): |
| expect(e.supertype, isNull); |
| _elementPrinter.writeTypeList( |
| 'superclassConstraints', |
| e.superclassConstraints, |
| ); |
| expect(e.mixins, isEmpty); |
| _elementPrinter.writeTypeList('interfaces', e.interfaces); |
| default: |
| throw UnimplementedError('${e.runtimeType}'); |
| } |
| |
| if (configuration.withAllSupertypes && e is InterfaceElementImpl2) { |
| var sorted = e.allSupertypes.sortedBy((t) => t.element3.name3!); |
| _elementPrinter.writeTypeList('allSupertypes', sorted); |
| } |
| |
| _writeElementList('fields', e, e.fields2, _writeFieldElement); |
| if (e is InterfaceElementImpl2) { |
| var constructors = e.constructors2; |
| if (e is MixinElementImpl2) { |
| expect(constructors, isEmpty); |
| } else if (configuration.withConstructors) { |
| _writeElementList( |
| 'constructors', |
| e, |
| constructors, |
| _writeConstructorElement, |
| ); |
| } |
| } |
| _writeElementList('getters', e, e.getters2, _writeGetterElement); |
| _writeElementList('setters', e, e.setters2, _writeSetterElement); |
| _writeElementList('methods', e, e.methods2, _writeMethodElement); |
| }); |
| |
| _assertNonSyntheticElementSelf(e); |
| } |
| |
| void _writeInstanceFragment(InstanceFragment f) { |
| _sink.writeIndentedLine(() { |
| switch (f) { |
| case ClassFragment(): |
| // TODO(brianwilkerson): Figure out why we can't ask the fragments |
| // these questions. |
| // _sink.writeIf(f.isAbstract, 'abstract '); |
| // _sink.writeIf(f.isSealed, 'sealed '); |
| // _sink.writeIf(f.isBase, 'base '); |
| // _sink.writeIf(f.isInterface, 'interface '); |
| // _sink.writeIf(f.isFinal, 'final '); |
| // _writeNotSimplyBounded(f); |
| // _sink.writeIf(f.isMixinClass, 'mixin '); |
| _sink.write('class '); |
| // _sink.writeIf(f.isMixinApplication, 'alias '); |
| case EnumFragment(): |
| // _writeNotSimplyBounded(f); |
| _sink.write('enum '); |
| case ExtensionFragment(): |
| _sink.write('extension '); |
| case ExtensionTypeFragment(): |
| // _sink.writeIf( |
| // e.hasRepresentationSelfReference, |
| // 'hasRepresentationSelfReference ', |
| // ); |
| // _sink.writeIf( |
| // e.hasImplementsSelfReference, |
| // 'hasImplementsSelfReference ', |
| // ); |
| // // _writeNotSimplyBounded(e); |
| _sink.write('extension type '); |
| case MixinFragment(): |
| // _sink.writeIf(f.isBase, 'base '); |
| // _writeNotSimplyBounded(f); |
| _sink.write('mixin '); |
| } |
| _writeFragmentName(f); |
| }); |
| _sink.withIndent(() { |
| _writeFragmentReference('reference', f); |
| _writeElementReference('element', f.element); |
| _writeFragmentReference('previousFragment', f.previousFragment); |
| _writeFragmentReference('nextFragment', f.nextFragment); |
| |
| _writeFragmentList( |
| 'typeParameters', |
| f, |
| f.typeParameters2, |
| _writeTypeParameterFragment, |
| ); |
| _writeFragmentList('fields', f, f.fields2, _writeFieldFragment); |
| if (f is InterfaceFragment) { |
| var constructors = f.constructors2; |
| 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.methods2, _writeMethodFragment); |
| }); |
| } |
| |
| void _writeLibraryFragment(CompilationUnitElementImpl f) { |
| var reference = f.reference!; |
| _sink.writeIndentedLine(() { |
| _elementPrinter.writeReference(reference); |
| _writeFragmentBestOffset(f); |
| }); |
| |
| _sink.withIndent(() { |
| _writeElementReference('element', f.element); |
| _writeFragmentReference('enclosingFragment', f.enclosingFragment); |
| _writeFragmentReference('previousFragment', f.previousFragment); |
| _writeFragmentReference('nextFragment', f.nextFragment); |
| |
| _writeMetadata(f.metadata2); |
| |
| if (configuration.withImports) { |
| var imports = |
| f.libraryImports2.where((import) { |
| return configuration.withSyntheticDartCoreImport || |
| !import.isSynthetic; |
| }).toList(); |
| _writeList('libraryImports', imports, _writeLibraryImport); |
| } |
| _writeElementList('prefixes', f.element, f.prefixes, _writePrefixElement); |
| // _writeList( |
| // 'libraryExports', f.libraryExports, _writeLibraryExportElement); |
| // _writeList('parts', f.parts, _writePartElement); |
| |
| _writeFragmentList('classes', f, f.classes2, _writeInstanceFragment); |
| _writeFragmentList('enums', f, f.enums2, _writeInstanceFragment); |
| _writeFragmentList( |
| 'extensions', |
| f, |
| f.extensions2, |
| _writeInstanceFragment, |
| ); |
| _writeFragmentList( |
| 'extensionTypes', |
| f, |
| f.extensionTypes2, |
| _writeInstanceFragment, |
| ); |
| _writeFragmentList('mixins', f, f.mixins2, _writeInstanceFragment); |
| _writeFragmentList( |
| 'typeAliases', |
| f, |
| f.typeAliases, |
| _writeTypeAliasFragment, |
| ); |
| _writeFragmentList( |
| 'topLevelVariables', |
| f, |
| f.topLevelVariables2, |
| _writeTopLevelVariableFragment, |
| ); |
| _writeFragmentList('getters', f, f.getters, _writeGetterFragment); |
| _writeFragmentList('setters', f, f.setters, _writeSetterFragment); |
| _writeFragmentList( |
| 'functions', |
| f, |
| f.functions, |
| _writeTopLevelFunctionFragment, |
| ); |
| }); |
| } |
| |
| void _writeLibraryImport(LibraryImportElementImpl e) { |
| _sink.writeIndentedLine(() { |
| _writeDirectiveUri(e.uri); |
| _sink.writeIf(e.isSynthetic, ' synthetic'); |
| _writeImportElementPrefix(e.prefix2); |
| }); |
| |
| _sink.withIndent(() { |
| _writeMetadata(e.metadata2); |
| // _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(MethodElementImpl2 e) { |
| _sink.writeIndentedLine(() { |
| _sink.writeIf(e.isSynthetic, 'synthetic '); |
| _sink.writeIf(e.isStatic, 'static '); |
| _sink.writeIf(e.isAbstract, 'abstract '); |
| _sink.writeIf(e.isExternal, 'external '); |
| |
| _writeElementName(e); |
| }); |
| |
| _sink.withIndent(() { |
| _writeReference2(e); |
| _writeFragmentReference('firstFragment', e.firstFragment); |
| // _writeElementReference(e.enclosingElement2, label: 'enclosingElement2'); |
| if (e.hasEnclosingTypeParameterReference) { |
| _sink.writelnWithIndent('hasEnclosingTypeParameterReference: true'); |
| } |
| _writeDocumentation(e.documentationComment); |
| _writeMetadata(e.metadata2); |
| _writeSinceSdkVersion(e); |
| // _writeTypeInferenceError(e); |
| |
| _writeElementList( |
| 'typeParameters', |
| e, |
| e.typeParameters2, |
| _writeTypeParameterElement, |
| ); |
| _writeElementList( |
| 'formalParameters', |
| e, |
| e.formalParameters, |
| _writeFormalParameterElement, |
| ); |
| _writeReturnType(e.returnType); |
| // _writeNonSyntheticElement(e); |
| }); |
| |
| // if (e.isSynthetic && e.enclosingElement2 is EnumElementImpl) { |
| // expect(e.name, 'toString'); |
| // expect(e.nonSynthetic2, same(e.enclosingElement2)); |
| // } else { |
| // _assertNonSyntheticElementSelf(e); |
| // } |
| } |
| |
| void _writeMethodFragment(MethodFragment f) { |
| _sink.writeIndentedLine(() { |
| _sink.writeIf(f.isAugmentation, 'augment '); |
| // _sink.writeIf(f.isSynthetic, 'synthetic '); |
| // _sink.writeIf(f.isStatic, 'static '); |
| // _sink.writeIf(f.isAbstract, 'abstract '); |
| // _sink.writeIf(f.isExternal, 'external '); |
| |
| _writeFragmentName(f); |
| _writeFragentBodyModifiers(f); |
| }); |
| |
| _sink.withIndent(() { |
| _writeFragmentReference('reference', f); |
| _writeElementReference('element', f.element); |
| _writeFragmentReference('previousFragment', f.previousFragment); |
| _writeFragmentReference('nextFragment', f.nextFragment); |
| _writeDocumentation(f.documentationComment); |
| _writeMetadata(f.metadata2); |
| _writeFragmentCodeRange(f); |
| // _writeTypeInferenceError(f); |
| |
| _writeFragmentList( |
| 'typeParameters', |
| f, |
| f.typeParameters2, |
| _writeTypeParameterFragment, |
| ); |
| _writeFragmentList( |
| 'formalParameters', |
| f, |
| f.formalParameters, |
| _writeFormalParameterFragment, |
| ); |
| // _writeReturnType(f.returnType); |
| // _writeNonSyntheticElement(f); |
| // _writeAugmentationTarget(f); |
| // _writeAugmentation(f); |
| }); |
| } |
| |
| void _writeNotSimplyBounded(InterfaceElementImpl2 e) { |
| _sink.writeIf(!e.isSimplyBounded, 'notSimplyBounded '); |
| } |
| |
| void _writePrefixElement(PrefixElementImpl2 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.name2, e.name3); |
| return '@${f.nameOffset2}'; |
| }) |
| .join(' '), |
| ); |
| }); |
| }); |
| } |
| |
| void _writeReturnType(DartType type) { |
| if (configuration.withReturnType) { |
| _writeType('returnType', type); |
| } |
| } |
| |
| void _writeSetterElement(SetterElementImpl e) { |
| var variable = e.variable3; |
| if (variable != null) { |
| var variableEnclosing = variable.enclosingElement2; |
| 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.fields2.map((field) => field.baseElement), |
| contains(variable.baseElement), |
| ); |
| } |
| } |
| |
| // if (e.isSynthetic) { |
| // expect(e.nameOffset, -1); |
| // } else { |
| // expect(e.nameOffset, isPositive); |
| // _assertNonSyntheticElementSelf(e); |
| // } |
| |
| _sink.writeIndentedLine(() { |
| _sink.writeIf(e.isSynthetic, 'synthetic '); |
| _sink.writeIf(e.isStatic, 'static '); |
| _sink.writeIf(e.isAbstract, 'abstract '); |
| _sink.writeIf(e.isExternal, 'external '); |
| |
| _sink.write('set '); |
| _writeElementName(e); |
| }); |
| |
| // void writeLinking() { |
| // if (configuration.withPropertyLinking) { |
| // _sink.writelnWithIndent('id: ${_idMap[e]}'); |
| // if (e.variable2 case var variable?) { |
| // _sink.writelnWithIndent('variable: ${_idMap[variable]}'); |
| // } else { |
| // _sink.writelnWithIndent('variable: <null>'); |
| // } |
| // } |
| // } |
| |
| _sink.withIndent(() { |
| _writeFragmentReference('firstFragment', e.firstFragment); |
| if (e.hasEnclosingTypeParameterReference) { |
| _sink.writelnWithIndent('hasEnclosingTypeParameterReference: true'); |
| } |
| _writeDocumentation(e.documentationComment); |
| _writeMetadata(e.metadata2); |
| _writeSinceSdkVersion(e); |
| |
| expect(e.typeParameters2, isEmpty); |
| _writeElementList( |
| 'formalParameters', |
| e, |
| e.formalParameters, |
| _writeFormalParameterElement, |
| ); |
| _writeReturnType(e.returnType); |
| // _writeNonSyntheticElement(e); |
| // writeLinking(); |
| }); |
| } |
| |
| void _writeSetterFragment(SetterFragment f) { |
| var variable = f.variable3; |
| if (f.isAugmentation) { |
| expect(variable, isNull); |
| } else { |
| var enclosing = variable!.enclosingFragment; |
| switch (enclosing) { |
| case LibraryFragment(): |
| expect(enclosing.topLevelVariables2, contains(variable)); |
| case InterfaceFragment(): |
| expect(enclosing.fields2, contains(variable)); |
| } |
| } |
| |
| // if (f.isSynthetic) { |
| // expect(f.nameOffset, -1); |
| // } else { |
| // expect(f.nameOffset, isPositive); |
| // _assertNonSyntheticElementSelf(f); |
| // } |
| |
| _sink.writeIndentedLine(() { |
| _sink.writeIf(f.isAugmentation, 'augment '); |
| _sink.writeIf(f.isSynthetic, 'synthetic '); |
| |
| _sink.write('set '); |
| _writeFragmentName(f); |
| // _writeBodyModifiers(f); |
| }); |
| |
| // void writeLinking() { |
| // if (configuration.withPropertyLinking) { |
| // _sink.writelnWithIndent('id: ${_idMap[e]}'); |
| // if (e.variable2 case var variable?) { |
| // _sink.writelnWithIndent('variable: ${_idMap[variable]}'); |
| // } else { |
| // _sink.writelnWithIndent('variable: <null>'); |
| // } |
| // } |
| // } |
| |
| _sink.withIndent(() { |
| _writeFragmentReference('reference', f); |
| _writeElementReference('element', f.element); |
| _writeDocumentation(f.documentationComment); |
| _writeMetadata(f.metadata2); |
| // _writeCodeRange(f); |
| |
| expect(f.typeParameters2, isEmpty); |
| _writeFragmentList( |
| 'formalParameters', |
| f, |
| f.formalParameters, |
| _writeFormalParameterFragment, |
| ); |
| // _writeReturnType(f.returnType); |
| // _writeNonSyntheticElement(f); |
| // writeLinking(); |
| _writeFragmentReference('previousFragment', f.previousFragment); |
| _writeFragmentReference('nextFragment', f.nextFragment); |
| }); |
| } |
| |
| void _writeSinceSdkVersion(Element element) { |
| if (element case HasSinceSdkVersion hasSince) { |
| var version = hasSince.sinceSdkVersion; |
| if (version != null) { |
| _sink.writelnWithIndent('sinceSdkVersion: $version'); |
| } |
| } |
| } |
| |
| void _writeTopLevelFunctionElement(TopLevelFunctionElementImpl e) { |
| expect(e.isStatic, isTrue); |
| |
| _sink.writeIndentedLine(() { |
| // _sink.writeIf(e.isAugmentation, 'augment '); |
| _sink.writeIf(e.isExternal, 'external '); |
| _writeElementName(e); |
| // _writeBodyModifiers(e); |
| }); |
| |
| _sink.withIndent(() { |
| _writeReference2(e); |
| _writeFragmentReference('firstFragment', e.firstFragment); |
| _writeDocumentation(e.documentationComment); |
| _writeMetadata(e.metadata2); |
| _writeSinceSdkVersion(e); |
| // _writeCodeRange(e); |
| _writeElementList( |
| 'typeParameters', |
| e, |
| e.typeParameters2, |
| _writeTypeParameterElement, |
| ); |
| _writeElementList( |
| 'formalParameters', |
| e, |
| e.formalParameters, |
| _writeFormalParameterElement, |
| ); |
| _writeType('returnType', e.returnType); |
| // _writeAugmentationTarget(e); |
| // _writeAugmentation(e); |
| }); |
| |
| _assertNonSyntheticElementSelf(e); |
| } |
| |
| void _writeTopLevelFunctionFragment(TopLevelFunctionFragment f) { |
| // expect(e.isStatic, isTrue); |
| |
| _sink.writeIndentedLine(() { |
| // _sink.writeIf(e.isAugmentation, 'augment '); |
| // _sink.writeIf(e.isExternal, 'external '); |
| _writeFragmentName(f); |
| // _writeBodyModifiers(e); |
| }); |
| |
| _sink.withIndent(() { |
| _writeFragmentReference('reference', f); |
| _writeElementReference('element', f.element); |
| _writeDocumentation(f.documentationComment); |
| _writeMetadata(f.metadata2); |
| // _writeCodeRange(e); |
| _writeFragmentList( |
| 'typeParameters', |
| f, |
| f.typeParameters2, |
| _writeTypeParameterFragment, |
| ); |
| _writeFragmentList( |
| 'formalParameters', |
| f, |
| f.formalParameters, |
| _writeFormalParameterFragment, |
| ); |
| // _writeType('returnType', e.returnType); |
| // _writeAugmentationTarget(e); |
| // _writeAugmentation(e); |
| }); |
| |
| // _assertNonSyntheticElementSelf(f); |
| } |
| |
| void _writeTopLevelVariableElement(TopLevelVariableElementImpl2 e) { |
| DartType type = e.type; |
| expect(type, isNotNull); |
| |
| if (!e.isSynthetic) { |
| // expect(e.getter2, isNotNull); |
| _assertNonSyntheticElementSelf(e); |
| } |
| |
| _sink.writeIndentedLine(() { |
| _sink.writeIf(e.isSynthetic, 'synthetic '); |
| _sink.writeIf(e.isLate, 'late '); |
| _sink.writeIf(e.isFinal, 'final '); |
| _sink.writeIf(e.isConst, 'const '); |
| _sink.writeIf(e.hasInitializer, 'hasInitializer '); |
| |
| _writeElementName(e); |
| }); |
| |
| // void writeLinking() { |
| // if (configuration.withPropertyLinking) { |
| // _sink.writelnWithIndent('id: ${_idMap[e]}'); |
| |
| // var getter = e.getter; |
| // if (getter != null) { |
| // _sink.writelnWithIndent('getter: ${_idMap[getter]}'); |
| // } |
| |
| // var setter = e.setter; |
| // if (setter != null) { |
| // _sink.writelnWithIndent('setter: ${_idMap[setter]}'); |
| // } |
| // } |
| // } |
| |
| _sink.withIndent(() { |
| _writeReference2(e); |
| _writeFragmentReference('firstFragment', e.firstFragment); |
| _writeDocumentation(e.documentationComment); |
| _writeMetadata(e.metadata2); |
| _writeSinceSdkVersion(e); |
| // _writeTypeInferenceError(e); |
| _writeType('type', e.type); |
| // _writeShouldUseTypeForInitializerInference(e); |
| _writeVariableElementConstantInitializer(e); |
| // _writeNonSyntheticElement(e); |
| // writeLinking(); |
| _writeElementReference('getter', e.getter2); |
| _writeElementReference('setter', e.setter2); |
| }); |
| } |
| |
| void _writeTopLevelVariableFragment(TopLevelVariableFragment 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(() { |
| _sink.writeIf(f.isAugmentation, 'augment '); |
| _sink.writeIf(f.isSynthetic, 'synthetic '); |
| _sink.writeIf(f.hasInitializer, 'hasInitializer '); |
| |
| _writeFragmentName(f); |
| }); |
| |
| // void writeLinking() { |
| // if (configuration.withPropertyLinking) { |
| // _sink.writelnWithIndent('id: ${_idMap[e]}'); |
| |
| // var getter = e.getter; |
| // if (getter != null) { |
| // _sink.writelnWithIndent('getter: ${_idMap[getter]}'); |
| // } |
| |
| // var setter = e.setter; |
| // if (setter != null) { |
| // _sink.writelnWithIndent('setter: ${_idMap[setter]}'); |
| // } |
| // } |
| // } |
| |
| _sink.withIndent(() { |
| _writeFragmentReference('reference', f); |
| _writeElementReference('element', f.element); |
| _writeDocumentation(f.documentationComment); |
| _writeMetadata(f.metadata2); |
| // _writeCodeRange(f); |
| // _writeTypeInferenceError(f); |
| // _writeType('type', f.type); |
| // _writeShouldUseTypeForInitializerInference(f); |
| _writeVariableFragmentInitializer(f); |
| // _writeNonSyntheticElement(f); |
| // writeLinking(); |
| _writeFragmentReference('previousFragment', f.previousFragment); |
| _writeFragmentReference('nextFragment', f.nextFragment); |
| _writeFragmentReference('getter2', f.getter2); |
| _writeFragmentReference('setter2', f.setter2); |
| }); |
| } |
| |
| 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(TypeAliasElement e) { |
| _sink.writeIndentedLine(() { |
| // _sink.writeIf(e.isAugmentation, 'augment '); |
| // _sink.writeIf(e.isFunctionTypeAliasBased, 'functionTypeAliasBased '); |
| _sink.writeIf(!e.isSimplyBounded, 'notSimplyBounded '); |
| _writeElementName(e); |
| }); |
| |
| _sink.withIndent(() { |
| _writeFragmentReference('firstFragment', e.firstFragment); |
| _writeDocumentation(e.documentationComment); |
| _writeMetadata(e.metadata2); |
| _writeSinceSdkVersion(e); |
| // _writeCodeRange(e); |
| _writeElementList( |
| 'typeParameters', |
| e, |
| e.typeParameters2, |
| _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); |
| }); |
| |
| _assertNonSyntheticElementSelf(e); |
| } |
| |
| void _writeTypeAliasFragment(TypeAliasFragment f) { |
| _sink.writeIndentedLine(() { |
| // _sink.writeIf(e.isAugmentation, 'augment '); |
| // _sink.writeIf(e.isFunctionTypeAliasBased, 'functionTypeAliasBased '); |
| // _sink.writeIf(!e.isSimplyBounded, 'notSimplyBounded '); |
| _writeFragmentName(f); |
| }); |
| |
| _sink.withIndent(() { |
| _writeFragmentReference('reference', f); |
| _writeElementReference('element', f.element); |
| _writeDocumentation(f.documentationComment); |
| _writeMetadata(f.metadata2); |
| // _writeCodeRange(e); |
| _writeFragmentList( |
| 'typeParameters', |
| f, |
| f.typeParameters2, |
| _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 _writeTypeParameterElement(TypeParameterElement e) { |
| _sink.writeIndentedLine(() { |
| // _sink.write('${e.variance.name} '); |
| _writeElementName(e); |
| }); |
| |
| _sink.withIndent(() { |
| var bound = e.bound; |
| if (bound != null) { |
| _writeType('bound', bound); |
| } |
| |
| // var defaultType = e.defaultType; |
| // if (defaultType != null) { |
| // _writeType('defaultType', defaultType); |
| // } |
| |
| _writeMetadata(e.metadata2); |
| }); |
| |
| _assertNonSyntheticElementSelf(e); |
| } |
| |
| void _writeTypeParameterFragment(TypeParameterFragment f) { |
| _sink.writeIndentedLine(() { |
| // _sink.write('${e.variance.name} '); |
| _writeFragmentName(f); |
| }); |
| |
| _sink.withIndent(() { |
| _writeElementReference('element', f.element); |
| // _writeCodeRange(e); |
| |
| // var bound = e.bound; |
| // if (bound != null) { |
| // _writeType('bound', bound); |
| // } |
| |
| // var defaultType = e.defaultType; |
| // if (defaultType != null) { |
| // _writeType('defaultType', defaultType); |
| // } |
| |
| _writeMetadata(f.metadata2); |
| }); |
| |
| // _assertNonSyntheticElementSelf(f); |
| } |
| |
| void _writeVariableElementConstantInitializer(VariableElement2OrMember e) { |
| if (e.constantInitializer2 case var initializer?) { |
| _sink.writelnWithIndent('constantInitializer'); |
| _sink.withIndent(() { |
| _writeFragmentReference('fragment', initializer.fragment); |
| _writeConstantInitializerExpression( |
| 'expression', |
| initializer.expression, |
| ); |
| }); |
| } |
| } |
| |
| void _writeVariableFragmentInitializer(VariableFragment f) { |
| if (f.initializer case var initializer?) { |
| _writeConstantInitializerExpression('initializer', initializer); |
| } |
| } |
| } |
| |
| class _IdMap { |
| final Map<Expression, String> expressionMap = Map.identity(); |
| final Map<ElementImpl, String> fieldMap = Map.identity(); |
| final Map<ElementImpl, String> getterMap = Map.identity(); |
| final Map<ElementImpl, String> partMap = Map.identity(); |
| final Map<ElementImpl, String> setterMap = Map.identity(); |
| |
| String operator [](Object object) { |
| if (object is Expression) { |
| return expressionMap[object] ??= 'expression_${expressionMap.length}'; |
| } else if (object is FieldElementImpl) { |
| return fieldMap[object] ??= 'field_${fieldMap.length}'; |
| } else if (object is TopLevelVariableElementImpl) { |
| return fieldMap[object] ??= 'variable_${fieldMap.length}'; |
| } else if (object is PropertyAccessorElementImpl && object.isGetter) { |
| return getterMap[object] ??= 'getter_${getterMap.length}'; |
| } else if (object is PartElementImpl) { |
| return partMap[object] ??= 'part_${partMap.length}'; |
| } else if (object is PropertyAccessorElementImpl && object.isSetter) { |
| return setterMap[object] ??= 'setter_${setterMap.length}'; |
| } else { |
| return '???'; |
| } |
| } |
| |
| String? existingExpressionId(Expression object) { |
| return expressionMap[object]; |
| } |
| } |