| // Copyright (c) 2021, 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 'dart:typed_data'; | |
| import 'package:analyzer/dart/ast/token.dart'; | |
| import 'package:analyzer/dart/ast/visitor.dart'; | |
| import 'package:analyzer/dart/element/element.dart'; | |
| import 'package:analyzer/source/line_info.dart'; | |
| import 'package:analyzer/source/source_range.dart'; | |
| import 'package:analyzer/src/binary/binary_reader.dart'; | |
| import 'package:analyzer/src/binary/binary_writer.dart'; | |
| import 'package:analyzer/src/dart/ast/ast.dart'; | |
| import 'package:analyzer/src/dart/element/element.dart'; | |
| import 'package:analyzer/src/summary2/linked_element_factory.dart'; | |
| import 'package:analyzer/src/summary2/not_serializable_nodes.dart'; | |
| import 'package:analyzer/src/util/collection.dart'; | |
| import 'package:analyzer/src/util/comment.dart'; | |
| import 'package:analyzer/src/utilities/extensions/object.dart'; | |
| import 'package:analyzer/src/utilities/growable_type_data.dart'; | |
| Uint8List writeUnitInformative(CompilationUnit unit) { | |
| var info = _InfoBuilder().build(unit); | |
| var writer = BinaryWriter(); | |
| info.write(writer); | |
| return writer.takeBytes(); | |
| } | |
| class InformativeDataApplier { | |
| bool _shouldDeferApplyMembersOffsets = true; | |
| void applyFromBytes( | |
| LibraryFragmentImpl fragment, | |
| Uint8List informativeBytes, | |
| ) { | |
| _shouldDeferApplyMembersOffsets = false; | |
| _applyFromBytes(fragment, informativeBytes); | |
| } | |
| void applyToLibrary( | |
| LinkedElementFactory elementFactory, | |
| LibraryElementImpl libraryElement, | |
| Map<Uri, Uint8List> unitsInformativeBytes, | |
| ) { | |
| if (elementFactory.isApplyingInformativeData) { | |
| throw StateError('Unexpected recursion.'); | |
| } | |
| elementFactory.isApplyingInformativeData = true; | |
| for (var libraryFragment in libraryElement.internal.fragments) { | |
| var uri = libraryFragment.source.uri; | |
| if (unitsInformativeBytes[uri] case var infoBytes?) { | |
| _applyFromBytes(libraryFragment, infoBytes); | |
| } | |
| } | |
| elementFactory.isApplyingInformativeData = false; | |
| } | |
| void _applyFromBytes( | |
| LibraryFragmentImpl libraryFragment, | |
| Uint8List infoBytes, | |
| ) { | |
| var unitReader = BinaryReader(infoBytes); | |
| var unitInfo = _InfoUnit.read(unitReader); | |
| _applyFromInfo(libraryFragment, unitInfo); | |
| } | |
| void _applyFromInfo(LibraryFragmentImpl libraryFragment, _InfoUnit unitInfo) { | |
| var libraryElement = libraryFragment.library; | |
| if (identical(libraryElement.internal.firstFragment, libraryFragment)) { | |
| _applyToLibrary(libraryElement, unitInfo); | |
| } | |
| libraryFragment.setCodeRange(unitInfo.codeOffset, unitInfo.codeLength); | |
| libraryFragment.lineInfo = LineInfo(unitInfo.lineStarts); | |
| DeferredResolutionReadingHelper.withoutLoadingResolution(() { | |
| _applyToImports(libraryFragment.libraryImports, unitInfo); | |
| _applyToExports(libraryFragment.libraryExports, unitInfo); | |
| _applyToPartIncludes(libraryFragment.parts, unitInfo); | |
| }); | |
| libraryFragment.deferConstantOffsets(unitInfo.libraryConstantOffsets, ( | |
| applier, | |
| ) { | |
| applier.applyToImports(libraryFragment.libraryImports); | |
| applier.applyToExports(libraryFragment.libraryExports); | |
| applier.applyToParts(libraryFragment.parts); | |
| }); | |
| _applyToAccessors(libraryFragment.getters, unitInfo.topLevelGetters); | |
| _applyToAccessors(libraryFragment.setters, unitInfo.topLevelSetters); | |
| forCorrespondingPairs( | |
| libraryFragment.classes.where((fragment) => !fragment.isMixinApplication), | |
| unitInfo.classDeclarations, | |
| _applyToClassDeclaration, | |
| ); | |
| forCorrespondingPairs( | |
| libraryFragment.classes.where((fragment) => fragment.isMixinApplication), | |
| unitInfo.classTypeAliases, | |
| _applyToClassTypeAlias, | |
| ); | |
| forCorrespondingPairs( | |
| libraryFragment.enums, | |
| unitInfo.enums, | |
| _applyToEnumDeclaration, | |
| ); | |
| forCorrespondingPairs( | |
| libraryFragment.extensions, | |
| unitInfo.extensions, | |
| _applyToExtensionDeclaration, | |
| ); | |
| forCorrespondingPairs( | |
| libraryFragment.extensionTypes, | |
| unitInfo.extensionTypes, | |
| _applyToExtensionTypeDeclaration, | |
| ); | |
| forCorrespondingPairs( | |
| libraryFragment.functions, | |
| unitInfo.topLevelFunctions, | |
| _applyToFunctionDeclaration, | |
| ); | |
| forCorrespondingPairs( | |
| libraryFragment.mixins, | |
| unitInfo.mixinDeclarations, | |
| _applyToMixinDeclaration, | |
| ); | |
| forCorrespondingPairs( | |
| libraryFragment.topLevelVariables.withOriginDeclaration, | |
| unitInfo.topLevelVariable, | |
| _applyToTopLevelVariable, | |
| ); | |
| forCorrespondingPairs( | |
| libraryFragment.typeAliases, | |
| unitInfo.typeAliases, | |
| _applyToTypeAlias, | |
| ); | |
| } | |
| void _applyToAccessors( | |
| List<PropertyAccessorFragmentImpl> fragmentList, | |
| List<_InfoExecutableDeclaration> infoList, | |
| ) { | |
| forCorrespondingPairs(fragmentList.withOriginDeclaration, infoList, ( | |
| fragment, | |
| info, | |
| ) { | |
| fragment.setCodeRange(info.codeOffset, info.codeLength); | |
| fragment.firstTokenOffset = info.firstTokenOffset; | |
| fragment.nameOffset = info.nameOffset; | |
| fragment.documentationComment = info.documentationComment; | |
| DeferredResolutionReadingHelper.withoutLoadingResolution(() { | |
| _applyToFormalParameters(fragment.formalParameters, info.parameters); | |
| }); | |
| fragment.deferConstantOffsets(info.constantOffsets, (applier) { | |
| applier.applyToMetadata(fragment.metadata); | |
| applier.applyToTypeParameters(fragment.typeParameters); | |
| applier.applyToFormalParameters(fragment.formalParameters); | |
| }); | |
| }); | |
| } | |
| void _applyToClassDeclaration( | |
| ClassFragmentImpl fragment, | |
| _InfoClassDeclaration info, | |
| ) { | |
| fragment.setCodeRange(info.codeOffset, info.codeLength); | |
| fragment.firstTokenOffset = info.firstTokenOffset; | |
| fragment.nameOffset = info.nameOffset; | |
| fragment.documentationComment = info.documentationComment; | |
| DeferredResolutionReadingHelper.withoutLoadingResolution(() { | |
| _applyToTypeParameters(fragment.typeParameters, info.typeParameters); | |
| }); | |
| fragment.deferConstantOffsets(info.constantOffsets, (applier) { | |
| applier.applyToMetadata(fragment.metadata); | |
| applier.applyToTypeParameters(fragment.typeParameters); | |
| }); | |
| _scheduleApplyMembersOffsets(fragment, () { | |
| DeferredResolutionReadingHelper.withoutLoadingResolution(() { | |
| _applyToConstructors(fragment.constructors, info.constructors); | |
| _applyToFields(fragment.fields, info.fields); | |
| _applyToAccessors(fragment.getters, info.getters); | |
| _applyToAccessors(fragment.setters, info.setters); | |
| _applyToMethods(fragment.methods, info.methods); | |
| }); | |
| }); | |
| } | |
| void _applyToClassTypeAlias( | |
| ClassFragmentImpl fragment, | |
| _InfoClassTypeAlias info, | |
| ) { | |
| fragment.setCodeRange(info.codeOffset, info.codeLength); | |
| fragment.firstTokenOffset = info.firstTokenOffset; | |
| fragment.nameOffset = info.nameOffset; | |
| fragment.documentationComment = info.documentationComment; | |
| DeferredResolutionReadingHelper.withoutLoadingResolution(() { | |
| _applyToTypeParameters(fragment.typeParameters, info.typeParameters); | |
| }); | |
| fragment.deferConstantOffsets(info.constantOffsets, (applier) { | |
| applier.applyToMetadata(fragment.metadata); | |
| applier.applyToTypeParameters(fragment.typeParameters); | |
| }); | |
| } | |
| void _applyToCombinators( | |
| List<NamespaceCombinator> elementList, | |
| List<_InfoCombinator> infoList, | |
| ) { | |
| forCorrespondingPairs<NamespaceCombinator, _InfoCombinator>( | |
| elementList, | |
| infoList, | |
| (element, info) { | |
| if (element is ShowElementCombinatorImpl) { | |
| element.offset = info.offset; | |
| element.end = info.end; | |
| } | |
| if (element is HideElementCombinatorImpl) { | |
| element.offset = info.offset; | |
| element.end = info.end; | |
| } | |
| }, | |
| ); | |
| } | |
| void _applyToConstructors( | |
| List<ConstructorFragmentImpl> fragmentList, | |
| List<_InfoConstructorDeclaration> infoList, | |
| ) { | |
| forCorrespondingPairs(fragmentList.withOriginDeclaration, infoList, ( | |
| fragment, | |
| info, | |
| ) { | |
| fragment.setCodeRange(info.codeOffset, info.codeLength); | |
| fragment.newKeywordOffset = info.newKeywordOffset; | |
| fragment.factoryKeywordOffset = info.factoryKeywordOffset; | |
| fragment.typeNameOffset = info.typeNameOffset; | |
| fragment.periodOffset = info.periodOffset; | |
| fragment.firstTokenOffset = info.firstTokenOffset; | |
| fragment.nameEnd = info.nameEnd; | |
| fragment.nameOffset = info.nameOffset; | |
| fragment.thisKeywordOffset = info.thisKeywordOffset; | |
| fragment.primaryHeaderCodeRange = info.primaryHeaderCodeRange; | |
| fragment.primaryBodyCodeRange = info.primaryBodyCodeRange; | |
| fragment.documentationComment = info.documentationComment; | |
| DeferredResolutionReadingHelper.withoutLoadingResolution(() { | |
| _applyToFormalParameters(fragment.formalParameters, info.parameters); | |
| }); | |
| fragment.deferConstantOffsets(info.constantOffsets, (applier) { | |
| applier.applyToMetadata(fragment.metadata); | |
| applier.applyToFormalParameters(fragment.formalParameters); | |
| applier.applyToConstructorInitializers(fragment); | |
| }); | |
| }); | |
| } | |
| void _applyToEnumDeclaration( | |
| EnumFragmentImpl fragment, | |
| _InfoEnumDeclaration info, | |
| ) { | |
| fragment.setCodeRange(info.codeOffset, info.codeLength); | |
| fragment.firstTokenOffset = info.firstTokenOffset; | |
| fragment.nameOffset = info.nameOffset; | |
| fragment.documentationComment = info.documentationComment; | |
| DeferredResolutionReadingHelper.withoutLoadingResolution(() { | |
| _applyToTypeParameters(fragment.typeParameters, info.typeParameters); | |
| }); | |
| _scheduleApplyMembersOffsets(fragment, () { | |
| DeferredResolutionReadingHelper.withoutLoadingResolution(() { | |
| _applyToConstructors(fragment.constructors, info.constructors); | |
| _applyToFields(fragment.fields, info.fields); | |
| _applyToAccessors(fragment.getters, info.getters); | |
| _applyToAccessors(fragment.setters, info.setters); | |
| _applyToMethods(fragment.methods, info.methods); | |
| }); | |
| }); | |
| fragment.deferConstantOffsets(info.constantOffsets, (applier) { | |
| applier.applyToMetadata(fragment.metadata); | |
| applier.applyToTypeParameters(fragment.typeParameters); | |
| }); | |
| } | |
| void _applyToExports(List<LibraryExportImpl> exports, _InfoUnit info) { | |
| forCorrespondingPairs(exports, info.exports, (element, info) { | |
| element.exportKeywordOffset = info.exportKeywordOffset; | |
| _applyToCombinators(element.combinators, info.combinators); | |
| }); | |
| } | |
| void _applyToExtensionDeclaration( | |
| ExtensionFragmentImpl fragment, | |
| _InfoExtensionDeclaration info, | |
| ) { | |
| fragment.setCodeRange(info.codeOffset, info.codeLength); | |
| fragment.firstTokenOffset = info.firstTokenOffset; | |
| fragment.nameOffset = info.nameOffset; | |
| fragment.documentationComment = info.documentationComment; | |
| DeferredResolutionReadingHelper.withoutLoadingResolution(() { | |
| _applyToTypeParameters(fragment.typeParameters, info.typeParameters); | |
| }); | |
| _scheduleApplyMembersOffsets(fragment, () { | |
| DeferredResolutionReadingHelper.withoutLoadingResolution(() { | |
| _applyToFields(fragment.fields, info.fields); | |
| _applyToAccessors(fragment.getters, info.getters); | |
| _applyToAccessors(fragment.setters, info.setters); | |
| _applyToMethods(fragment.methods, info.methods); | |
| }); | |
| }); | |
| fragment.deferConstantOffsets(info.constantOffsets, (applier) { | |
| applier.applyToMetadata(fragment.metadata); | |
| applier.applyToTypeParameters(fragment.typeParameters); | |
| }); | |
| } | |
| void _applyToExtensionTypeDeclaration( | |
| ExtensionTypeFragmentImpl fragment, | |
| _InfoExtensionTypeDeclaration info, | |
| ) { | |
| fragment.setCodeRange(info.codeOffset, info.codeLength); | |
| fragment.firstTokenOffset = info.firstTokenOffset; | |
| fragment.nameOffset = info.nameOffset; | |
| fragment.documentationComment = info.documentationComment; | |
| DeferredResolutionReadingHelper.withoutLoadingResolution(() { | |
| _applyToTypeParameters(fragment.typeParameters, info.typeParameters); | |
| }); | |
| _scheduleApplyMembersOffsets(fragment, () { | |
| DeferredResolutionReadingHelper.withoutLoadingResolution(() { | |
| _applyToFields(fragment.fields, info.fields); | |
| _applyToConstructors(fragment.constructors, info.constructors); | |
| _applyToAccessors(fragment.getters, info.getters); | |
| _applyToAccessors(fragment.setters, info.setters); | |
| _applyToMethods(fragment.methods, info.methods); | |
| }); | |
| }); | |
| fragment.deferConstantOffsets(info.constantOffsets, (applier) { | |
| applier.applyToMetadata(fragment.metadata); | |
| applier.applyToTypeParameters(fragment.typeParameters); | |
| }); | |
| } | |
| void _applyToFields( | |
| List<FieldFragmentImpl> fragmentList, | |
| List<_InfoFieldDeclaration> infoList, | |
| ) { | |
| forCorrespondingPairs(fragmentList.withOriginDeclaration, infoList, ( | |
| fragment, | |
| info, | |
| ) { | |
| fragment.setCodeRange(info.codeOffset, info.codeLength); | |
| fragment.firstTokenOffset = info.firstTokenOffset; | |
| fragment.nameOffset = info.nameOffset; | |
| fragment.documentationComment = info.documentationComment; | |
| fragment.deferConstantOffsets(info.constantOffsets, (applier) { | |
| applier.applyToMetadata(fragment.metadata); | |
| applier.applyToConstantInitializer(fragment); | |
| }); | |
| }); | |
| } | |
| void _applyToFormalParameters( | |
| List<FormalParameterFragmentImpl> parameters, | |
| List<_InfoFormalParameter> infoList, | |
| ) { | |
| forCorrespondingPairs( | |
| parameters.where((p) => p.isOriginDeclaration), | |
| infoList, | |
| (fragment, info) { | |
| fragment.setCodeRange(info.codeOffset, info.codeLength); | |
| fragment.firstTokenOffset = info.firstTokenOffset; | |
| fragment.nameOffset = info.nameOffset; | |
| fragment.documentationComment = info.documentationComment; | |
| }, | |
| ); | |
| } | |
| void _applyToFunctionDeclaration( | |
| TopLevelFunctionFragmentImpl fragment, | |
| _InfoExecutableDeclaration info, | |
| ) { | |
| fragment.setCodeRange(info.codeOffset, info.codeLength); | |
| fragment.firstTokenOffset = info.firstTokenOffset; | |
| fragment.nameOffset = info.nameOffset; | |
| fragment.documentationComment = info.documentationComment; | |
| DeferredResolutionReadingHelper.withoutLoadingResolution(() { | |
| _applyToTypeParameters(fragment.typeParameters, info.typeParameters); | |
| _applyToFormalParameters(fragment.formalParameters, info.parameters); | |
| }); | |
| fragment.deferConstantOffsets(info.constantOffsets, (applier) { | |
| applier.applyToMetadata(fragment.metadata); | |
| applier.applyToTypeParameters(fragment.typeParameters); | |
| applier.applyToFormalParameters(fragment.formalParameters); | |
| }); | |
| } | |
| void _applyToImports(List<LibraryImportImpl> imports, _InfoUnit info) { | |
| forCorrespondingPairs(imports, info.imports, (element, info) { | |
| element.importKeywordOffset = info.importKeywordOffset; | |
| if (element.prefix case var prefixFragment?) { | |
| prefixFragment.nameOffset = info.prefixOffset; | |
| prefixFragment.offset = info.prefixOffset ?? info.importKeywordOffset; | |
| } | |
| _applyToCombinators(element.combinators, info.combinators); | |
| }); | |
| } | |
| void _applyToLibrary(LibraryElementImpl element, _InfoUnit info) { | |
| element.nameOffset = info.libraryName.offset; | |
| element.nameLength = info.libraryName.length; | |
| element.documentationComment = info.docComment; | |
| element.deferConstantOffsets(info.libraryConstantOffsets, (applier) { | |
| applier.applyToMetadata(element.metadata); | |
| }); | |
| } | |
| void _applyToMethods( | |
| List<MethodFragmentImpl> fragmentList, | |
| List<_InfoExecutableDeclaration> infoList, | |
| ) { | |
| forCorrespondingPairs(fragmentList, infoList, (fragment, info) { | |
| fragment.setCodeRange(info.codeOffset, info.codeLength); | |
| fragment.firstTokenOffset = info.firstTokenOffset; | |
| fragment.nameOffset = info.nameOffset; | |
| fragment.documentationComment = info.documentationComment; | |
| DeferredResolutionReadingHelper.withoutLoadingResolution(() { | |
| _applyToTypeParameters(fragment.typeParameters, info.typeParameters); | |
| _applyToFormalParameters(fragment.formalParameters, info.parameters); | |
| }); | |
| fragment.deferConstantOffsets(info.constantOffsets, (applier) { | |
| applier.applyToMetadata(fragment.metadata); | |
| applier.applyToTypeParameters(fragment.typeParameters); | |
| applier.applyToFormalParameters(fragment.formalParameters); | |
| }); | |
| }); | |
| } | |
| void _applyToMixinDeclaration( | |
| MixinFragmentImpl fragment, | |
| _InfoMixinDeclaration info, | |
| ) { | |
| fragment.setCodeRange(info.codeOffset, info.codeLength); | |
| fragment.firstTokenOffset = info.firstTokenOffset; | |
| fragment.nameOffset = info.nameOffset; | |
| fragment.documentationComment = info.documentationComment; | |
| DeferredResolutionReadingHelper.withoutLoadingResolution(() { | |
| _applyToTypeParameters(fragment.typeParameters, info.typeParameters); | |
| }); | |
| _scheduleApplyMembersOffsets(fragment, () { | |
| DeferredResolutionReadingHelper.withoutLoadingResolution(() { | |
| _applyToConstructors(fragment.constructors, info.constructors); | |
| _applyToFields(fragment.fields, info.fields); | |
| _applyToAccessors(fragment.getters, info.getters); | |
| _applyToAccessors(fragment.setters, info.setters); | |
| _applyToMethods(fragment.methods, info.methods); | |
| }); | |
| }); | |
| fragment.deferConstantOffsets(info.constantOffsets, (applier) { | |
| applier.applyToMetadata(fragment.metadata); | |
| applier.applyToTypeParameters(fragment.typeParameters); | |
| }); | |
| } | |
| void _applyToPartIncludes(List<PartIncludeImpl> imports, _InfoUnit info) { | |
| forCorrespondingPairs(imports, info.parts, (element, info) { | |
| element.partKeywordOffset = info.partKeywordOffset; | |
| }); | |
| } | |
| void _applyToTopLevelVariable( | |
| TopLevelVariableFragmentImpl fragment, | |
| _InfoTopLevelVariable info, | |
| ) { | |
| fragment.setCodeRange(info.codeOffset, info.codeLength); | |
| fragment.firstTokenOffset = info.firstTokenOffset; | |
| fragment.nameOffset = info.nameOffset; | |
| fragment.documentationComment = info.documentationComment; | |
| fragment.deferConstantOffsets(info.constantOffsets, (applier) { | |
| applier.applyToMetadata(fragment.metadata); | |
| applier.applyToConstantInitializer(fragment); | |
| }); | |
| } | |
| void _applyToTypeAlias(TypeAliasFragmentImpl fragment, _InfoTypeAlias info) { | |
| fragment.setCodeRange(info.codeOffset, info.codeLength); | |
| fragment.firstTokenOffset = info.firstTokenOffset; | |
| fragment.nameOffset = info.nameOffset; | |
| fragment.documentationComment = info.documentationComment; | |
| DeferredResolutionReadingHelper.withoutLoadingResolution(() { | |
| _applyToTypeParameters(fragment.typeParameters, info.typeParameters); | |
| }); | |
| _setupApplyConstantOffsetsForTypeAlias(fragment, info.constantOffsets); | |
| } | |
| void _applyToTypeParameters( | |
| List<TypeParameterFragmentImpl> fragmentList, | |
| List<_InfoTypeParameter> infoList, | |
| ) { | |
| forCorrespondingPairs(fragmentList, infoList, (fragment, info) { | |
| fragment.setCodeRange(info.codeOffset, info.codeLength); | |
| fragment.firstTokenOffset = info.firstTokenOffset; | |
| fragment.nameOffset = info.nameOffset; | |
| }); | |
| } | |
| /// Either defer, or eagerly invoke [callback]. | |
| void _scheduleApplyMembersOffsets( | |
| InstanceFragmentImpl fragment, | |
| void Function() callback, | |
| ) { | |
| if (_shouldDeferApplyMembersOffsets) { | |
| fragment.deferApplyMembersOffsets(callback); | |
| } else { | |
| callback(); | |
| } | |
| } | |
| void _setupApplyConstantOffsetsForTypeAlias( | |
| TypeAliasFragmentImpl fragment, | |
| Uint32List constantOffsets, | |
| ) { | |
| fragment.deferConstantOffsets(constantOffsets, (applier) { | |
| applier.applyToMetadata(fragment.metadata); | |
| applier.applyToTypeParameters(fragment.typeParameters); | |
| }); | |
| } | |
| } | |
| class _InfoBuilder { | |
| _InfoUnit build(CompilationUnit unit) { | |
| // Build all needed lists from `unit.declarations2` with a single iteration | |
| // the list. | |
| var classDeclarations = <_InfoClassDeclaration>[]; | |
| var classTypeAliases = <_InfoClassTypeAlias>[]; | |
| var enums = <_InfoEnumDeclaration>[]; | |
| var extensions = <_InfoExtensionDeclaration>[]; | |
| var extensionTypes = <_InfoExtensionTypeDeclaration>[]; | |
| var mixinDeclarations = <_InfoMixinDeclaration>[]; | |
| var topLevelFunctions = <_InfoExecutableDeclaration>[]; | |
| var topLevelGetters = <_InfoExecutableDeclaration>[]; | |
| var topLevelSetters = <_InfoExecutableDeclaration>[]; | |
| var topLevelVariable = <_InfoTopLevelVariable>[]; | |
| var typeAliases = <_InfoTypeAlias>[]; | |
| for (var declaration in unit.declarations2) { | |
| if (declaration is ClassDeclaration) { | |
| classDeclarations.add(_buildClass(declaration)); | |
| } else if (declaration is ClassTypeAlias) { | |
| classTypeAliases.add(_buildClassTypeAlias(declaration)); | |
| } else if (declaration is EnumDeclarationImpl) { | |
| enums.add(_buildEnum(declaration)); | |
| } else if (declaration is ExtensionDeclaration) { | |
| extensions.add(_buildExtension(declaration)); | |
| } else if (declaration is ExtensionTypeDeclaration) { | |
| extensionTypes.add(_buildExtensionType(declaration)); | |
| } else if (declaration is MixinDeclarationImpl) { | |
| mixinDeclarations.add(_buildMixin(declaration)); | |
| } else if (declaration is TopLevelGetterDeclarationImpl) { | |
| topLevelGetters.add(_buildTopLevelGetter(declaration)); | |
| } else if (declaration is FunctionDeclaration) { | |
| if (declaration.isGetter) { | |
| topLevelGetters.add(_buildTopLevelFunction(declaration)); | |
| } else if (declaration.isSetter) { | |
| topLevelSetters.add(_buildTopLevelFunction(declaration)); | |
| } else { | |
| topLevelFunctions.add(_buildTopLevelFunction(declaration)); | |
| } | |
| } else if (declaration is TopLevelVariableDeclaration) { | |
| for (var variable in declaration.variables.variables) { | |
| topLevelVariable.add(_buildTopLevelVariable(variable)); | |
| } | |
| } else if (declaration is FunctionTypeAlias) { | |
| typeAliases.add(_buildFunctionTypeAlias(declaration)); | |
| } else if (declaration is GenericTypeAlias) { | |
| typeAliases.add(_buildGenericTypeAlias(declaration)); | |
| } | |
| } | |
| // Build all needed lists from `unit.directives` with a single iteration | |
| // the list. | |
| var imports = <_InfoImport>[]; | |
| var exports = <_InfoExport>[]; | |
| var parts = <_InfoPart>[]; | |
| var rawImports = <ImportDirective>[]; | |
| var rawExports = <ExportDirective>[]; | |
| var rawParts = <PartDirective>[]; | |
| LibraryDirective? firstLibraryDirective; | |
| for (var directive in unit.directives) { | |
| if (directive is ImportDirective) { | |
| rawImports.add(directive); | |
| imports.add(_buildImport(directive)); | |
| } else if (directive is ExportDirective) { | |
| rawExports.add(directive); | |
| exports.add(_buildExport(directive)); | |
| } else if (directive is PartDirective) { | |
| rawParts.add(directive); | |
| parts.add(_buildPart(directive)); | |
| } else if (directive is LibraryDirective) { | |
| firstLibraryDirective ??= directive; | |
| } | |
| } | |
| return _InfoUnit( | |
| codeOffset: unit.offset, | |
| codeLength: unit.length, | |
| lineStarts: unit.lineInfo.lineStarts, | |
| libraryName: _buildLibraryName(firstLibraryDirective), | |
| libraryConstantOffsets: _buildLibraryConstantOffsets( | |
| unit.directives.firstOrNull, | |
| rawImports, | |
| rawExports, | |
| rawParts, | |
| ), | |
| docComment: _getDocumentationComment(unit.directives.firstOrNull), | |
| imports: imports, | |
| exports: exports, | |
| parts: parts, | |
| classDeclarations: classDeclarations, | |
| classTypeAliases: classTypeAliases, | |
| enums: enums, | |
| extensions: extensions, | |
| extensionTypes: extensionTypes, | |
| mixinDeclarations: mixinDeclarations, | |
| topLevelFunctions: topLevelFunctions, | |
| topLevelGetters: topLevelGetters, | |
| topLevelSetters: topLevelSetters, | |
| topLevelVariable: topLevelVariable, | |
| typeAliases: typeAliases, | |
| ); | |
| } | |
| _InfoClassDeclaration _buildClass(ClassDeclaration node) { | |
| return _InfoClassDeclaration( | |
| data: _buildInterfaceData( | |
| node, | |
| name: node.namePart.typeName, | |
| typeParameters: node.namePart.typeParameters, | |
| primaryConstructor: node.namePart.tryCast(), | |
| members: node.body.members, | |
| ), | |
| ); | |
| } | |
| _InfoClassTypeAlias _buildClassTypeAlias(ClassTypeAlias node) { | |
| return _InfoClassTypeAlias( | |
| firstTokenOffset: node.offset, | |
| codeOffset: node.offset, | |
| codeLength: node.length, | |
| nameOffset: node.name.offsetIfNotEmpty, | |
| documentationComment: _getDocumentationComment(node), | |
| typeParameters: _buildTypeParameters(node.typeParameters), | |
| constantOffsets: _buildConstantOffsets( | |
| metadata: node.metadata, | |
| typeParameters: node.typeParameters, | |
| ), | |
| ); | |
| } | |
| _InfoCombinator _buildCombinator(Combinator node) { | |
| return _InfoCombinator(offset: node.offset, end: node.end); | |
| } | |
| List<_InfoCombinator> _buildCombinators(List<Combinator> combinators) { | |
| return combinators.map(_buildCombinator).toList(); | |
| } | |
| Uint32List _buildConstantOffsets({ | |
| NodeList<Annotation>? metadata, | |
| Iterable<ImportDirective>? importDirectives, | |
| Iterable<ExportDirective>? exportDirectives, | |
| Iterable<PartDirective>? partDirectives, | |
| TypeParameterList? typeParameters, | |
| FormalParameterList? formalParameters, | |
| Expression? constantInitializer, | |
| NodeList<ConstructorInitializer>? constructorInitializers, | |
| NodeList<EnumConstantDeclaration>? enumConstants, | |
| TypeAnnotation? aliasedType, | |
| EnumConstantArguments? enumConstantArguments, | |
| }) { | |
| var collector = _OffsetsCollector(); | |
| void addDirectives(Iterable<Directive>? directives) { | |
| if (directives != null) { | |
| for (var directive in directives) { | |
| directive.metadata.accept2(collector); | |
| } | |
| } | |
| } | |
| void addTypeParameters(TypeParameterList? typeParameters) { | |
| if (typeParameters != null) { | |
| for (var typeParameter in typeParameters.typeParameters) { | |
| typeParameter.metadata.accept2(collector); | |
| } | |
| } | |
| } | |
| void addFormalParameters(FormalParameterList? formalParameters) { | |
| if (formalParameters != null) { | |
| for (var parameter in formalParameters.allFormalParameters) { | |
| parameter.metadata.accept2(collector); | |
| addFormalParameters(parameter.functionTypedSuffix?.formalParameters); | |
| if (parameter.defaultClause case var defaultClause?) { | |
| defaultClause.value2.accept2(collector); | |
| } | |
| } | |
| } | |
| } | |
| metadata?.accept2(collector); | |
| addDirectives(importDirectives); | |
| addDirectives(exportDirectives); | |
| addDirectives(partDirectives); | |
| addTypeParameters(typeParameters); | |
| addFormalParameters(formalParameters); | |
| constantInitializer?.accept2(collector); | |
| constructorInitializers?.accept2(collector); | |
| if (enumConstants != null) { | |
| for (var enumConstant in enumConstants) { | |
| enumConstant.metadata.accept2(collector); | |
| } | |
| } | |
| if (aliasedType is GenericFunctionType) { | |
| addTypeParameters(aliasedType.typeParameters); | |
| addFormalParameters(aliasedType.parameters); | |
| } | |
| enumConstantArguments?.typeArguments?.accept2(collector); | |
| enumConstantArguments?.argumentList.accept2(collector); | |
| return collector.offsets.takeAndReset(); | |
| } | |
| _InfoConstructorDeclaration _buildConstructor(ConstructorDeclaration node) { | |
| return _InfoConstructorDeclaration( | |
| firstTokenOffset: node.offset, | |
| codeOffset: node.offset, | |
| codeLength: node.length, | |
| nameOffset: node.name?.offsetIfNotEmpty, | |
| documentationComment: _getDocumentationComment(node), | |
| typeParameters: const [], | |
| parameters: _buildFormalParameters(node.parameters), | |
| constantOffsets: _buildConstantOffsets( | |
| metadata: node.metadata, | |
| formalParameters: node.parameters, | |
| constructorInitializers: node.initializers, | |
| ), | |
| newKeywordOffset: node.newKeyword?.offset, | |
| factoryKeywordOffset: node.factoryKeyword?.offset, | |
| typeNameOffset: node.typeName2?.offset, | |
| periodOffset: node.period?.offset, | |
| nameEnd: (node.name ?? node.typeName2)?.end, | |
| thisKeywordOffset: null, | |
| primaryHeaderCodeRange: null, | |
| primaryBodyCodeRange: null, | |
| ); | |
| } | |
| _InfoEnumDeclaration _buildEnum(EnumDeclarationImpl node) { | |
| return _InfoEnumDeclaration( | |
| data: _buildInterfaceData( | |
| node, | |
| name: node.namePart.typeName, | |
| typeParameters: node.namePart.typeParameters, | |
| primaryConstructor: node.namePart.tryCast(), | |
| members: node.body.members, | |
| fields: [ | |
| ...node.body.constants.map(_buildEnumConstant), | |
| ...node.body.members | |
| .whereType<FieldDeclaration>() | |
| .expand((node) => node.fields.variables) | |
| .map((node) => _buildField(node)), | |
| ], | |
| ), | |
| ); | |
| } | |
| _InfoFieldDeclaration _buildEnumConstant(EnumConstantDeclaration node) { | |
| var codeOffset = node.offset; | |
| return _InfoFieldDeclaration( | |
| firstTokenOffset: node.offset, | |
| codeOffset: codeOffset, | |
| codeLength: node.end - codeOffset, | |
| nameOffset: node.name.offsetIfNotEmpty, | |
| documentationComment: _getDocumentationComment(node), | |
| constantOffsets: _buildConstantOffsets( | |
| metadata: node.metadata, | |
| enumConstantArguments: node.arguments, | |
| ), | |
| ); | |
| } | |
| _InfoExport _buildExport(ExportDirective node) { | |
| return _InfoExport( | |
| exportKeywordOffset: node.exportKeyword.offset, | |
| combinators: _buildCombinators(node.combinators), | |
| ); | |
| } | |
| _InfoExtensionDeclaration _buildExtension(ExtensionDeclaration node) { | |
| return _InfoExtensionDeclaration( | |
| data: _buildInstanceData( | |
| node, | |
| name: node.name, | |
| typeParameters: node.typeParameters, | |
| members: node.body.members, | |
| ), | |
| ); | |
| } | |
| _InfoExtensionTypeDeclaration _buildExtensionType( | |
| ExtensionTypeDeclaration node, | |
| ) { | |
| return _InfoExtensionTypeDeclaration( | |
| data: _buildInterfaceData( | |
| node, | |
| name: node.namePart.typeName, | |
| typeParameters: node.namePart.typeParameters, | |
| primaryConstructor: node.namePart.tryCast(), | |
| members: node.body.members, | |
| ), | |
| ); | |
| } | |
| _InfoFieldDeclaration _buildField(VariableDeclaration node) { | |
| var codeOffset = _codeOffsetForVariable(node); | |
| var declaration = node.parent2!.parent2 as FieldDeclaration; | |
| return _InfoFieldDeclaration( | |
| firstTokenOffset: node.offset, | |
| codeOffset: codeOffset, | |
| codeLength: node.end - codeOffset, | |
| nameOffset: node.name.offsetIfNotEmpty, | |
| documentationComment: _getDocumentationComment(node), | |
| constantOffsets: _buildConstantOffsets( | |
| metadata: declaration.metadata, | |
| constantInitializer: node.initializer2, | |
| ), | |
| ); | |
| } | |
| _InfoFormalParameter _buildFormalParameter(FormalParameter node) { | |
| var functionTypedSuffix = node.functionTypedSuffix; | |
| return _InfoFormalParameter( | |
| firstTokenOffset: node.offset, | |
| codeOffset: node.offset, | |
| codeLength: node.length, | |
| nameOffset: node.name?.offsetIfNotEmpty, | |
| documentationComment: _getDocumentationComment(node), | |
| typeParameters: _buildTypeParameters(functionTypedSuffix?.typeParameters), | |
| parameters: _buildFormalParameters(functionTypedSuffix?.formalParameters), | |
| ); | |
| } | |
| List<_InfoFormalParameter> _buildFormalParameters(FormalParameterList? node) { | |
| if (node == null) { | |
| return []; | |
| } | |
| var parameters = node.allFormalParameters; | |
| return List.generate( | |
| parameters.length, | |
| (index) => _buildFormalParameter(parameters[index]), | |
| ); | |
| } | |
| _InfoTypeAlias _buildFunctionTypeAlias(FunctionTypeAlias node) { | |
| return _InfoTypeAlias( | |
| firstTokenOffset: node.offset, | |
| codeOffset: node.offset, | |
| codeLength: node.length, | |
| nameOffset: node.name.offsetIfNotEmpty, | |
| documentationComment: _getDocumentationComment(node), | |
| typeParameters: _buildTypeParameters(node.typeParameters), | |
| constantOffsets: _buildConstantOffsets( | |
| metadata: node.metadata, | |
| typeParameters: node.typeParameters, | |
| aliasedType: node.returnType, | |
| ), | |
| ); | |
| } | |
| _InfoTypeAlias _buildGenericTypeAlias(GenericTypeAlias node) { | |
| return _InfoTypeAlias( | |
| firstTokenOffset: node.offset, | |
| codeOffset: node.offset, | |
| codeLength: node.length, | |
| nameOffset: node.name.offsetIfNotEmpty, | |
| documentationComment: _getDocumentationComment(node), | |
| typeParameters: _buildTypeParameters(node.typeParameters), | |
| constantOffsets: _buildConstantOffsets( | |
| metadata: node.metadata, | |
| typeParameters: node.typeParameters, | |
| aliasedType: node.type, | |
| ), | |
| ); | |
| } | |
| _InfoImport _buildImport(ImportDirective node) { | |
| return _InfoImport( | |
| importKeywordOffset: node.importKeyword.offset, | |
| prefixOffset: node.prefixName?.offsetIfNotEmpty, | |
| combinators: _buildCombinators(node.combinators), | |
| ); | |
| } | |
| _InstanceData _buildInstanceData( | |
| Declaration node, { | |
| required Token? name, | |
| required TypeParameterList? typeParameters, | |
| required List<ClassMember> members, | |
| List<_InfoFieldDeclaration>? fields, | |
| }) { | |
| // Build all needed lists based on `members` with a single iteration the list. | |
| var getters = <_InfoExecutableDeclaration>[]; | |
| var setters = <_InfoExecutableDeclaration>[]; | |
| var methods = <_InfoExecutableDeclaration>[]; | |
| bool processFields = fields == null; | |
| fields ??= <_InfoFieldDeclaration>[]; | |
| for (var member in members) { | |
| if (member is MethodDeclaration) { | |
| if (member.isGetter) { | |
| getters.add(_buildMethodDeclaration(member)); | |
| } else if (member.isSetter) { | |
| setters.add(_buildMethodDeclaration(member)); | |
| } else { | |
| methods.add(_buildMethodDeclaration(member)); | |
| } | |
| } else if (processFields && member is FieldDeclaration) { | |
| for (var variable in member.fields.variables) { | |
| fields.add(_buildField(variable)); | |
| } | |
| } | |
| } | |
| var annotatedNode = node as AnnotatedNode; | |
| return _InstanceData( | |
| firstTokenOffset: node.offset, | |
| codeOffset: node.offset, | |
| codeLength: node.length, | |
| nameOffset: name?.offsetIfNotEmpty, | |
| documentationComment: _getDocumentationComment(annotatedNode), | |
| typeParameters: _buildTypeParameters(typeParameters), | |
| fields: fields, | |
| getters: getters, | |
| setters: setters, | |
| methods: methods, | |
| constantOffsets: _buildConstantOffsets( | |
| metadata: annotatedNode.metadata, | |
| typeParameters: typeParameters, | |
| ), | |
| ); | |
| } | |
| _InterfaceData _buildInterfaceData( | |
| Declaration node, { | |
| required Token? name, | |
| required TypeParameterList? typeParameters, | |
| PrimaryConstructorDeclaration? primaryConstructor, | |
| required List<ClassMember> members, | |
| List<_InfoFieldDeclaration>? fields, | |
| }) { | |
| var instanceData = _buildInstanceData( | |
| node, | |
| name: name, | |
| typeParameters: typeParameters, | |
| members: members, | |
| fields: fields, | |
| ); | |
| var primaryConstructorBody = members | |
| .whereType<PrimaryConstructorBody>() | |
| .firstOrNull; | |
| return _InterfaceData( | |
| instanceData: instanceData, | |
| constructors: [ | |
| if (primaryConstructor != null) | |
| _buildPrimaryConstructor( | |
| primaryConstructor, | |
| body: primaryConstructorBody, | |
| ), | |
| ...members.whereType<ConstructorDeclaration>().map(_buildConstructor), | |
| ], | |
| ); | |
| } | |
| Uint32List _buildLibraryConstantOffsets( | |
| Directive? firstDirective, | |
| List<ImportDirective> imports, | |
| List<ExportDirective> exports, | |
| List<PartDirective> parts, | |
| ) { | |
| return _buildConstantOffsets( | |
| metadata: firstDirective?.metadata, | |
| importDirectives: imports, | |
| exportDirectives: exports, | |
| partDirectives: parts, | |
| ); | |
| } | |
| _InfoLibraryName _buildLibraryName(LibraryDirective? firstLibraryDirective) { | |
| var nameOffset = -1; | |
| var nameLength = 0; | |
| var libraryName = firstLibraryDirective?.name; | |
| if (libraryName != null) { | |
| nameOffset = libraryName.offset; | |
| nameLength = libraryName.length; | |
| } | |
| return _InfoLibraryName(offset: nameOffset, length: nameLength); | |
| } | |
| _InfoExecutableDeclaration _buildMethodDeclaration(MethodDeclaration node) { | |
| return _InfoExecutableDeclaration( | |
| firstTokenOffset: node.offset, | |
| codeOffset: node.offset, | |
| codeLength: node.length, | |
| nameOffset: node.name.offsetIfNotEmpty, | |
| documentationComment: _getDocumentationComment(node), | |
| typeParameters: _buildTypeParameters(node.typeParameters), | |
| parameters: _buildFormalParameters(node.parameters), | |
| constantOffsets: _buildConstantOffsets( | |
| metadata: node.metadata, | |
| typeParameters: node.typeParameters, | |
| formalParameters: node.parameters, | |
| ), | |
| ); | |
| } | |
| _InfoMixinDeclaration _buildMixin(MixinDeclarationImpl node) { | |
| return _InfoMixinDeclaration( | |
| data: _buildInterfaceData( | |
| node, | |
| name: node.name, | |
| typeParameters: node.typeParameters, | |
| members: node.body.members, | |
| ), | |
| ); | |
| } | |
| _InfoPart _buildPart(PartDirective node) { | |
| return _InfoPart(partKeywordOffset: node.partKeyword.offset); | |
| } | |
| _InfoConstructorDeclaration _buildPrimaryConstructor( | |
| PrimaryConstructorDeclaration node, { | |
| required PrimaryConstructorBody? body, | |
| }) { | |
| var headerOffset = (node.constructorName ?? node.formalParameters).offset; | |
| return _InfoConstructorDeclaration( | |
| firstTokenOffset: node.offset, | |
| codeOffset: node.offset, | |
| codeLength: node.length, | |
| nameOffset: node.constructorName?.name.offsetIfNotEmpty, | |
| documentationComment: _getDocumentationComment(body), | |
| typeParameters: const [], | |
| parameters: _buildFormalParameters(node.formalParameters), | |
| constantOffsets: _buildConstantOffsets( | |
| metadata: body?.metadata, | |
| formalParameters: node.formalParameters, | |
| constructorInitializers: body?.initializers, | |
| ), | |
| newKeywordOffset: null, | |
| factoryKeywordOffset: null, | |
| typeNameOffset: node.typeName.offset, | |
| periodOffset: node.constructorName?.period.offset, | |
| nameEnd: (node.constructorName?.name ?? node.typeName).end, | |
| thisKeywordOffset: body?.thisKeyword.offset, | |
| primaryHeaderCodeRange: SourceRange( | |
| headerOffset, | |
| node.end - headerOffset, | |
| ), | |
| primaryBodyCodeRange: body != null | |
| ? SourceRange(body.offset, body.length) | |
| : null, | |
| ); | |
| } | |
| _InfoExecutableDeclaration _buildTopLevelFunction(FunctionDeclaration node) { | |
| return _InfoExecutableDeclaration( | |
| firstTokenOffset: node.offset, | |
| codeOffset: node.offset, | |
| codeLength: node.length, | |
| nameOffset: node.name.offsetIfNotEmpty, | |
| documentationComment: _getDocumentationComment(node), | |
| typeParameters: _buildTypeParameters( | |
| node.functionExpression.typeParameters, | |
| ), | |
| parameters: _buildFormalParameters(node.functionExpression.parameters), | |
| constantOffsets: _buildConstantOffsets( | |
| metadata: node.metadata, | |
| typeParameters: node.functionExpression.typeParameters, | |
| formalParameters: node.functionExpression.parameters, | |
| ), | |
| ); | |
| } | |
| _InfoExecutableDeclaration _buildTopLevelGetter( | |
| TopLevelGetterDeclarationImpl node, | |
| ) { | |
| return _InfoExecutableDeclaration( | |
| firstTokenOffset: node.offset, | |
| codeOffset: node.offset, | |
| codeLength: node.length, | |
| nameOffset: node.name.offsetIfNotEmpty, | |
| documentationComment: _getDocumentationComment(node), | |
| typeParameters: _buildTypeParameters(node.recoveryTypeParameters), | |
| parameters: _buildFormalParameters(node.recoveryFormalParameters), | |
| constantOffsets: _buildConstantOffsets( | |
| metadata: node.metadata, | |
| typeParameters: node.recoveryTypeParameters, | |
| formalParameters: node.recoveryFormalParameters, | |
| ), | |
| ); | |
| } | |
| _InfoTopLevelVariable _buildTopLevelVariable(VariableDeclaration node) { | |
| var codeOffset = _codeOffsetForVariable(node); | |
| var declaration = node.parent2!.parent2 as TopLevelVariableDeclaration; | |
| return _InfoTopLevelVariable( | |
| firstTokenOffset: node.offset, | |
| codeOffset: codeOffset, | |
| codeLength: node.end - codeOffset, | |
| nameOffset: node.name.offsetIfNotEmpty, | |
| documentationComment: _getDocumentationComment(node), | |
| constantOffsets: _buildConstantOffsets( | |
| metadata: declaration.metadata, | |
| constantInitializer: node.initializer2, | |
| ), | |
| ); | |
| } | |
| _InfoTypeParameter _buildTypeParameter(TypeParameter node) { | |
| return _InfoTypeParameter( | |
| firstTokenOffset: node.offset, | |
| codeOffset: node.offset, | |
| codeLength: node.length, | |
| nameOffset: node.name.offsetIfNotEmpty, | |
| ); | |
| } | |
| List<_InfoTypeParameter> _buildTypeParameters(TypeParameterList? node) { | |
| if (node == null) { | |
| return []; | |
| } | |
| var typeParameters = node.typeParameters; | |
| return List.generate( | |
| typeParameters.length, | |
| (index) => _buildTypeParameter(typeParameters[index]), | |
| ); | |
| } | |
| int _codeOffsetForVariable(VariableDeclaration node) { | |
| var codeOffset = node.offset; | |
| var variableList = node.parent2 as VariableDeclarationList; | |
| if (variableList.variables[0] == node) { | |
| codeOffset = variableList.parent2!.offset; | |
| } | |
| return codeOffset; | |
| } | |
| String? _getDocumentationComment(AnnotatedNode? node) { | |
| var comment = node?.documentationComment; | |
| return getCommentNodeRawText(comment); | |
| } | |
| } | |
| class _InfoClassDeclaration extends _InfoInterfaceDeclaration { | |
| _InfoClassDeclaration({required super.data}); | |
| _InfoClassDeclaration.read(super.reader) : super.read(); | |
| } | |
| class _InfoClassTypeAlias extends _InfoNode { | |
| final List<_InfoTypeParameter> typeParameters; | |
| final Uint32List constantOffsets; | |
| _InfoClassTypeAlias({ | |
| required super.firstTokenOffset, | |
| required super.codeOffset, | |
| required super.codeLength, | |
| required super.nameOffset, | |
| required super.documentationComment, | |
| required this.typeParameters, | |
| required this.constantOffsets, | |
| }) : super(); | |
| _InfoClassTypeAlias.read(super.reader) | |
| : typeParameters = reader.readList(_InfoTypeParameter.read), | |
| constantOffsets = reader.readUint30List(), | |
| super.read(); | |
| @override | |
| void write(BinaryWriter writer) { | |
| writer.writeList(typeParameters, (v) => v.write(writer)); | |
| writer.writeUint30List(constantOffsets); | |
| super.write(writer); | |
| } | |
| } | |
| class _InfoCombinator { | |
| final int offset; | |
| final int end; | |
| _InfoCombinator({required this.offset, required this.end}); | |
| factory _InfoCombinator.read(BinaryReader reader) { | |
| return _InfoCombinator( | |
| offset: reader.readUint30(), | |
| end: reader.readUint30(), | |
| ); | |
| } | |
| void write(BinaryWriter writer) { | |
| writer.writeUint30(offset); | |
| writer.writeUint30(end); | |
| } | |
| } | |
| class _InfoConstructorDeclaration extends _InfoExecutableDeclaration { | |
| final int? newKeywordOffset; | |
| final int? factoryKeywordOffset; | |
| final int? typeNameOffset; | |
| final int? periodOffset; | |
| final int? nameEnd; | |
| final int? thisKeywordOffset; | |
| final SourceRange? primaryHeaderCodeRange; | |
| final SourceRange? primaryBodyCodeRange; | |
| _InfoConstructorDeclaration({ | |
| required super.firstTokenOffset, | |
| required super.codeOffset, | |
| required super.codeLength, | |
| required super.nameOffset, | |
| required super.documentationComment, | |
| required super.typeParameters, | |
| required super.parameters, | |
| required super.constantOffsets, | |
| required this.newKeywordOffset, | |
| required this.factoryKeywordOffset, | |
| required this.typeNameOffset, | |
| required this.periodOffset, | |
| required this.nameEnd, | |
| required this.thisKeywordOffset, | |
| required this.primaryHeaderCodeRange, | |
| required this.primaryBodyCodeRange, | |
| }); | |
| _InfoConstructorDeclaration.read(super.reader) | |
| : newKeywordOffset = reader.readOptionalUint30(), | |
| factoryKeywordOffset = reader.readOptionalUint30(), | |
| typeNameOffset = reader.readOptionalUint30(), | |
| periodOffset = reader.readOptionalUint30(), | |
| nameEnd = reader.readOptionalUint30(), | |
| thisKeywordOffset = reader.readOptionalUint30(), | |
| primaryHeaderCodeRange = reader.readOptionalSourceRange(), | |
| primaryBodyCodeRange = reader.readOptionalSourceRange(), | |
| super.read(); | |
| @override | |
| void write(BinaryWriter writer) { | |
| writer.writeOptionalUint30(newKeywordOffset); | |
| writer.writeOptionalUint30(factoryKeywordOffset); | |
| writer.writeOptionalUint30(typeNameOffset); | |
| writer.writeOptionalUint30(periodOffset); | |
| writer.writeOptionalUint30(nameEnd); | |
| writer.writeOptionalUint30(thisKeywordOffset); | |
| writer.writeOptionalSourceRange(primaryHeaderCodeRange); | |
| writer.writeOptionalSourceRange(primaryBodyCodeRange); | |
| super.write(writer); | |
| } | |
| } | |
| class _InfoEnumDeclaration extends _InfoInterfaceDeclaration { | |
| _InfoEnumDeclaration({required super.data}); | |
| _InfoEnumDeclaration.read(super.reader) : super.read(); | |
| } | |
| class _InfoExecutableDeclaration extends _InfoNode { | |
| final List<_InfoTypeParameter> typeParameters; | |
| final List<_InfoFormalParameter> parameters; | |
| final Uint32List constantOffsets; | |
| _InfoExecutableDeclaration({ | |
| required super.firstTokenOffset, | |
| required super.codeOffset, | |
| required super.codeLength, | |
| required super.nameOffset, | |
| required super.documentationComment, | |
| required this.typeParameters, | |
| required this.parameters, | |
| required this.constantOffsets, | |
| }) : super(); | |
| _InfoExecutableDeclaration.read(super.reader) | |
| : typeParameters = reader.readList(_InfoTypeParameter.read), | |
| parameters = reader.readList(_InfoFormalParameter.read), | |
| constantOffsets = reader.readUint30List(), | |
| super.read(); | |
| @override | |
| void write(BinaryWriter writer) { | |
| writer.writeList(typeParameters, (v) => v.write(writer)); | |
| writer.writeList(parameters, (v) => v.write(writer)); | |
| writer.writeUint30List(constantOffsets); | |
| super.write(writer); | |
| } | |
| } | |
| class _InfoExport { | |
| final int exportKeywordOffset; | |
| final List<_InfoCombinator> combinators; | |
| _InfoExport({required this.exportKeywordOffset, required this.combinators}); | |
| factory _InfoExport.read(BinaryReader reader) { | |
| return _InfoExport( | |
| exportKeywordOffset: reader.readUint30(), | |
| combinators: reader.readList(_InfoCombinator.read), | |
| ); | |
| } | |
| void write(BinaryWriter writer) { | |
| writer.writeUint30(exportKeywordOffset); | |
| writer.writeList(combinators, (v) => v.write(writer)); | |
| } | |
| } | |
| class _InfoExtensionDeclaration extends _InfoInstanceDeclaration { | |
| _InfoExtensionDeclaration({required super.data}); | |
| _InfoExtensionDeclaration.read(super.reader) : super.read(); | |
| } | |
| class _InfoExtensionTypeDeclaration extends _InfoInterfaceDeclaration { | |
| _InfoExtensionTypeDeclaration({required super.data}); | |
| _InfoExtensionTypeDeclaration.read(super.reader) : super.read(); | |
| } | |
| class _InfoFieldDeclaration extends _InfoNode { | |
| final Uint32List constantOffsets; | |
| _InfoFieldDeclaration({ | |
| required super.firstTokenOffset, | |
| required super.codeOffset, | |
| required super.codeLength, | |
| required super.nameOffset, | |
| required super.documentationComment, | |
| required this.constantOffsets, | |
| }) : super(); | |
| _InfoFieldDeclaration.read(super.reader) | |
| : constantOffsets = reader.readUint30List(), | |
| super.read(); | |
| @override | |
| void write(BinaryWriter writer) { | |
| writer.writeUint30List(constantOffsets); | |
| super.write(writer); | |
| } | |
| } | |
| class _InfoFormalParameter extends _InfoNode { | |
| final List<_InfoTypeParameter> typeParameters; | |
| final List<_InfoFormalParameter> parameters; | |
| _InfoFormalParameter({ | |
| required super.firstTokenOffset, | |
| required super.codeOffset, | |
| required super.codeLength, | |
| required super.nameOffset, | |
| required super.documentationComment, | |
| required this.typeParameters, | |
| required this.parameters, | |
| }); | |
| _InfoFormalParameter.read(super.reader) | |
| : typeParameters = reader.readList(_InfoTypeParameter.read), | |
| parameters = reader.readList(_InfoFormalParameter.read), | |
| super.read(); | |
| @override | |
| void write(BinaryWriter writer) { | |
| writer.writeList(typeParameters, (v) => v.write(writer)); | |
| writer.writeList(parameters, (v) => v.write(writer)); | |
| super.write(writer); | |
| } | |
| } | |
| class _InfoImport { | |
| final int importKeywordOffset; | |
| final int? prefixOffset; | |
| final List<_InfoCombinator> combinators; | |
| _InfoImport({ | |
| required this.importKeywordOffset, | |
| required this.prefixOffset, | |
| required this.combinators, | |
| }); | |
| factory _InfoImport.read(BinaryReader reader) { | |
| return _InfoImport( | |
| importKeywordOffset: reader.readUint30(), | |
| prefixOffset: reader.readOptionalUint30(), | |
| combinators: reader.readList(_InfoCombinator.read), | |
| ); | |
| } | |
| void write(BinaryWriter writer) { | |
| writer.writeUint30(importKeywordOffset); | |
| writer.writeOptionalUint30(prefixOffset); | |
| writer.writeList(combinators, (v) => v.write(writer)); | |
| } | |
| } | |
| abstract class _InfoInstanceDeclaration extends _InfoNode { | |
| final List<_InfoTypeParameter> typeParameters; | |
| final List<_InfoFieldDeclaration> fields; | |
| final List<_InfoExecutableDeclaration> getters; | |
| final List<_InfoExecutableDeclaration> setters; | |
| final List<_InfoExecutableDeclaration> methods; | |
| final Uint32List constantOffsets; | |
| _InfoInstanceDeclaration({required _InstanceData data}) | |
| : typeParameters = data.typeParameters, | |
| fields = data.fields, | |
| getters = data.getters, | |
| setters = data.setters, | |
| methods = data.methods, | |
| constantOffsets = data.constantOffsets, | |
| super( | |
| codeOffset: data.codeOffset, | |
| codeLength: data.codeLength, | |
| firstTokenOffset: data.firstTokenOffset, | |
| nameOffset: data.nameOffset, | |
| documentationComment: data.documentationComment, | |
| ); | |
| _InfoInstanceDeclaration.read(super.reader) | |
| : typeParameters = reader.readList(_InfoTypeParameter.read), | |
| fields = reader.readList(_InfoFieldDeclaration.read), | |
| getters = reader.readList(_InfoExecutableDeclaration.read), | |
| setters = reader.readList(_InfoExecutableDeclaration.read), | |
| methods = reader.readList(_InfoExecutableDeclaration.read), | |
| constantOffsets = reader.readUint30List(), | |
| super.read(); | |
| @override | |
| void write(BinaryWriter writer) { | |
| writer.writeList(typeParameters, (v) => v.write(writer)); | |
| writer.writeList(fields, (v) => v.write(writer)); | |
| writer.writeList(getters, (v) => v.write(writer)); | |
| writer.writeList(setters, (v) => v.write(writer)); | |
| writer.writeList(methods, (v) => v.write(writer)); | |
| writer.writeUint30List(constantOffsets); | |
| super.write(writer); | |
| } | |
| } | |
| abstract class _InfoInterfaceDeclaration extends _InfoInstanceDeclaration { | |
| final List<_InfoConstructorDeclaration> constructors; | |
| _InfoInterfaceDeclaration({required _InterfaceData data}) | |
| : constructors = data.constructors, | |
| super(data: data.instanceData); | |
| _InfoInterfaceDeclaration.read(super.reader) | |
| : constructors = reader.readList(_InfoConstructorDeclaration.read), | |
| super.read(); | |
| @override | |
| void write(BinaryWriter writer) { | |
| writer.writeList(constructors, (v) => v.write(writer)); | |
| super.write(writer); | |
| } | |
| } | |
| class _InfoLibraryName { | |
| final int offset; | |
| final int length; | |
| _InfoLibraryName({required this.offset, required this.length}); | |
| factory _InfoLibraryName.read(BinaryReader reader) { | |
| return _InfoLibraryName( | |
| offset: reader.readUint30() - 1, | |
| length: reader.readUint30(), | |
| ); | |
| } | |
| void write(BinaryWriter writer) { | |
| writer.writeUint30(offset + 1); | |
| writer.writeUint30(length); | |
| } | |
| } | |
| class _InfoMixinDeclaration extends _InfoInterfaceDeclaration { | |
| _InfoMixinDeclaration({required super.data}); | |
| _InfoMixinDeclaration.read(super.reader) : super.read(); | |
| } | |
| abstract class _InfoNode { | |
| final int firstTokenOffset; | |
| final int codeOffset; | |
| final int codeLength; | |
| final int? nameOffset; | |
| final String? documentationComment; | |
| _InfoNode({ | |
| required this.firstTokenOffset, | |
| required this.codeOffset, | |
| required this.codeLength, | |
| required this.nameOffset, | |
| required this.documentationComment, | |
| }); | |
| _InfoNode.read(BinaryReader reader) | |
| : firstTokenOffset = reader.readUint30(), | |
| codeOffset = reader.readUint30(), | |
| codeLength = reader.readUint30(), | |
| nameOffset = reader.readOptionalUint30(), | |
| documentationComment = reader.readStringUtf8().nullIfEmpty; | |
| void write(BinaryWriter writer) { | |
| writer.writeUint30(firstTokenOffset); | |
| writer.writeUint30(codeOffset); | |
| writer.writeUint30(codeLength); | |
| writer.writeOptionalUint30(nameOffset); | |
| writer.writeStringUtf8(documentationComment ?? ''); | |
| } | |
| } | |
| class _InfoPart { | |
| final int partKeywordOffset; | |
| _InfoPart({required this.partKeywordOffset}); | |
| factory _InfoPart.read(BinaryReader reader) { | |
| return _InfoPart(partKeywordOffset: reader.readUint30()); | |
| } | |
| void write(BinaryWriter writer) { | |
| writer.writeUint30(partKeywordOffset); | |
| } | |
| } | |
| class _InfoTopLevelVariable extends _InfoNode { | |
| final Uint32List constantOffsets; | |
| _InfoTopLevelVariable({ | |
| required super.firstTokenOffset, | |
| required super.codeOffset, | |
| required super.codeLength, | |
| required super.nameOffset, | |
| required super.documentationComment, | |
| required this.constantOffsets, | |
| }) : super(); | |
| _InfoTopLevelVariable.read(super.reader) | |
| : constantOffsets = reader.readUint30List(), | |
| super.read(); | |
| @override | |
| void write(BinaryWriter writer) { | |
| writer.writeUint30List(constantOffsets); | |
| super.write(writer); | |
| } | |
| } | |
| class _InfoTypeAlias extends _InfoNode { | |
| final List<_InfoTypeParameter> typeParameters; | |
| final Uint32List constantOffsets; | |
| _InfoTypeAlias({ | |
| required super.firstTokenOffset, | |
| required super.codeOffset, | |
| required super.codeLength, | |
| required super.nameOffset, | |
| required super.documentationComment, | |
| required this.typeParameters, | |
| required this.constantOffsets, | |
| }) : super(); | |
| _InfoTypeAlias.read(super.reader) | |
| : typeParameters = reader.readList(_InfoTypeParameter.read), | |
| constantOffsets = reader.readUint30List(), | |
| super.read(); | |
| @override | |
| void write(BinaryWriter writer) { | |
| writer.writeList(typeParameters, (v) => v.write(writer)); | |
| writer.writeUint30List(constantOffsets); | |
| super.write(writer); | |
| } | |
| } | |
| class _InfoTypeParameter extends _InfoNode { | |
| _InfoTypeParameter({ | |
| required super.firstTokenOffset, | |
| required super.codeOffset, | |
| required super.codeLength, | |
| required super.nameOffset, | |
| }) : super(documentationComment: null); | |
| _InfoTypeParameter.read(super.reader) : super.read(); | |
| } | |
| class _InfoUnit { | |
| final int codeOffset; | |
| final int codeLength; | |
| final List<int> lineStarts; | |
| final _InfoLibraryName libraryName; | |
| final Uint32List libraryConstantOffsets; | |
| final String? docComment; | |
| final List<_InfoImport> imports; | |
| final List<_InfoExport> exports; | |
| final List<_InfoPart> parts; | |
| final List<_InfoClassDeclaration> classDeclarations; | |
| final List<_InfoClassTypeAlias> classTypeAliases; | |
| final List<_InfoEnumDeclaration> enums; | |
| final List<_InfoExtensionDeclaration> extensions; | |
| final List<_InfoExtensionTypeDeclaration> extensionTypes; | |
| final List<_InfoMixinDeclaration> mixinDeclarations; | |
| final List<_InfoExecutableDeclaration> topLevelFunctions; | |
| final List<_InfoExecutableDeclaration> topLevelGetters; | |
| final List<_InfoExecutableDeclaration> topLevelSetters; | |
| final List<_InfoTopLevelVariable> topLevelVariable; | |
| final List<_InfoTypeAlias> typeAliases; | |
| _InfoUnit({ | |
| required this.codeOffset, | |
| required this.codeLength, | |
| required this.lineStarts, | |
| required this.libraryName, | |
| required this.libraryConstantOffsets, | |
| required this.docComment, | |
| required this.imports, | |
| required this.exports, | |
| required this.parts, | |
| required this.classDeclarations, | |
| required this.classTypeAliases, | |
| required this.enums, | |
| required this.extensions, | |
| required this.extensionTypes, | |
| required this.mixinDeclarations, | |
| required this.topLevelFunctions, | |
| required this.topLevelGetters, | |
| required this.topLevelSetters, | |
| required this.topLevelVariable, | |
| required this.typeAliases, | |
| }); | |
| _InfoUnit.read(BinaryReader reader) | |
| : codeOffset = reader.readUint30(), | |
| codeLength = reader.readUint30(), | |
| lineStarts = reader.readUint30List(), | |
| libraryName = _InfoLibraryName.read(reader), | |
| libraryConstantOffsets = reader.readUint30List(), | |
| docComment = reader.readOptionalStringUtf8(), | |
| imports = reader.readList(_InfoImport.read), | |
| exports = reader.readList(_InfoExport.read), | |
| parts = reader.readList(_InfoPart.read), | |
| classDeclarations = reader.readList(_InfoClassDeclaration.read), | |
| classTypeAliases = reader.readList(_InfoClassTypeAlias.read), | |
| enums = reader.readList(_InfoEnumDeclaration.read), | |
| extensions = reader.readList(_InfoExtensionDeclaration.read), | |
| extensionTypes = reader.readList(_InfoExtensionTypeDeclaration.read), | |
| mixinDeclarations = reader.readList(_InfoMixinDeclaration.read), | |
| topLevelFunctions = reader.readList(_InfoExecutableDeclaration.read), | |
| topLevelGetters = reader.readList(_InfoExecutableDeclaration.read), | |
| topLevelSetters = reader.readList(_InfoExecutableDeclaration.read), | |
| topLevelVariable = reader.readList(_InfoTopLevelVariable.read), | |
| typeAliases = reader.readList(_InfoTypeAlias.read); | |
| void write(BinaryWriter writer) { | |
| writer.writeUint30(codeOffset); | |
| writer.writeUint30(codeLength); | |
| writer.writeUint30List(lineStarts); | |
| libraryName.write(writer); | |
| writer.writeUint30List(libraryConstantOffsets); | |
| writer.writeOptionalStringUtf8(docComment); | |
| writer.writeList(imports, (v) => v.write(writer)); | |
| writer.writeList(exports, (v) => v.write(writer)); | |
| writer.writeList(parts, (v) => v.write(writer)); | |
| writer.writeList(classDeclarations, (v) => v.write(writer)); | |
| writer.writeList(classTypeAliases, (v) => v.write(writer)); | |
| writer.writeList(enums, (v) => v.write(writer)); | |
| writer.writeList(extensions, (v) => v.write(writer)); | |
| writer.writeList(extensionTypes, (v) => v.write(writer)); | |
| writer.writeList(mixinDeclarations, (v) => v.write(writer)); | |
| writer.writeList(topLevelFunctions, (v) => v.write(writer)); | |
| writer.writeList(topLevelGetters, (v) => v.write(writer)); | |
| writer.writeList(topLevelSetters, (v) => v.write(writer)); | |
| writer.writeList(topLevelVariable, (v) => v.write(writer)); | |
| writer.writeList(typeAliases, (v) => v.write(writer)); | |
| } | |
| } | |
| class _InstanceData { | |
| final int firstTokenOffset; | |
| final int codeOffset; | |
| final int codeLength; | |
| final int? nameOffset; | |
| final String? documentationComment; | |
| final List<_InfoTypeParameter> typeParameters; | |
| final List<_InfoFieldDeclaration> fields; | |
| final List<_InfoExecutableDeclaration> getters; | |
| final List<_InfoExecutableDeclaration> setters; | |
| final List<_InfoExecutableDeclaration> methods; | |
| final Uint32List constantOffsets; | |
| _InstanceData({ | |
| required this.firstTokenOffset, | |
| required this.codeOffset, | |
| required this.codeLength, | |
| required this.nameOffset, | |
| required this.documentationComment, | |
| required this.typeParameters, | |
| required this.fields, | |
| required this.getters, | |
| required this.setters, | |
| required this.methods, | |
| required this.constantOffsets, | |
| }); | |
| } | |
| class _InterfaceData { | |
| final _InstanceData instanceData; | |
| final List<_InfoConstructorDeclaration> constructors; | |
| _InterfaceData({required this.instanceData, required this.constructors}); | |
| } | |
| class _OffsetsApplier extends _OffsetsAstVisitor { | |
| final _SafeListIterator<int> _iterator; | |
| _OffsetsApplier(this._iterator); | |
| void applyToConstantInitializer(FragmentImpl fragment) { | |
| if (fragment is FieldFragmentImpl && fragment.isEnumConstant) { | |
| _applyToEnumConstantInitializer(fragment); | |
| } else if (fragment is VariableFragmentImpl) { | |
| fragment.constantInitializer2?.accept2(this); | |
| } | |
| } | |
| void applyToConstructorInitializers(ConstructorFragmentImpl fragment) { | |
| for (var initializer in fragment.constantInitializers) { | |
| initializer.accept2(this); | |
| } | |
| } | |
| void applyToEnumConstants(List<FieldFragmentImpl> constants) { | |
| for (var constant in constants) { | |
| applyToMetadata(constant.metadata); | |
| } | |
| } | |
| void applyToExports(List<LibraryExportImpl> elements) { | |
| for (var element in elements) { | |
| applyToMetadata(element.metadata); | |
| } | |
| } | |
| void applyToFormalParameters( | |
| List<FormalParameterFragmentImpl> formalParameters, | |
| ) { | |
| for (var formalParameters in formalParameters) { | |
| applyToMetadata(formalParameters.metadata); | |
| applyToConstantInitializer(formalParameters); | |
| } | |
| } | |
| void applyToImports(List<LibraryImportImpl> elements) { | |
| for (var element in elements) { | |
| applyToMetadata(element.metadata); | |
| } | |
| } | |
| void applyToMetadata(MetadataImpl metadata) { | |
| for (var annotation in metadata.annotations) { | |
| var node = annotation.annotationAst; | |
| node.accept2(this); | |
| } | |
| } | |
| void applyToParts(List<PartIncludeImpl> elements) { | |
| for (var element in elements) { | |
| applyToMetadata(element.metadata); | |
| } | |
| } | |
| void applyToTypeParameters(List<TypeParameterFragmentImpl> typeParameters) { | |
| for (var typeParameter in typeParameters) { | |
| applyToMetadata(typeParameter.metadata); | |
| } | |
| } | |
| @override | |
| void handleToken(Token token) { | |
| var offset = _iterator.take(); | |
| if (offset != null) { | |
| token.offset = offset; | |
| } | |
| } | |
| @override | |
| void visitFunctionExpression(FunctionExpression node) { | |
| // We store FunctionExpression(s) as empty stubs: `() {}`. | |
| // We just need it to have right code range, so we apply 2 offsets. | |
| node.parameters?.leftParenthesis.offset = _iterator.take() ?? 0; | |
| var body = node.body; | |
| if (body is BlockFunctionBody) { | |
| body.block.rightBracket.offset = _iterator.take() ?? 0; | |
| } | |
| } | |
| @override | |
| void visitRegularFormalParameter(RegularFormalParameter node) { | |
| super.visitRegularFormalParameter(node); | |
| var fragment = node.declaredFragment; | |
| var identifier = node.name; | |
| if (fragment is FormalParameterFragmentImpl && identifier != null) { | |
| fragment.firstTokenOffset = identifier.offset; | |
| fragment.nameOffset = identifier.offsetIfNotEmpty; | |
| } | |
| } | |
| @override | |
| void visitUnqualifiedNameExpression(UnqualifiedNameExpression node) { | |
| if (isNotSerializableMarker(node)) { | |
| return; | |
| } | |
| super.visitUnqualifiedNameExpression(node); | |
| } | |
| void _applyToEnumConstantInitializer(FieldFragmentImpl fragment) { | |
| var initializer = fragment.constantInitializer2; | |
| if (initializer is ConstructorInvocationImpl) { | |
| initializer.constructorReference.typeReference.typeArguments?.accept2( | |
| this, | |
| ); | |
| initializer.argumentList.accept2(this); | |
| } | |
| } | |
| } | |
| abstract class _OffsetsAstVisitor extends RecursiveAstVisitor2<void> { | |
| void handleToken(Token token); | |
| @override | |
| void visitAnnotation(Annotation node) { | |
| _tokenOrNull(node.atSign); | |
| super.visitAnnotation(node); | |
| } | |
| @override | |
| void visitArgumentList(ArgumentList node) { | |
| _tokenOrNull(node.leftParenthesis); | |
| _tokenOrNull(node.rightParenthesis); | |
| super.visitArgumentList(node); | |
| } | |
| @override | |
| void visitAsExpression(AsExpression node) { | |
| _tokenOrNull(node.asOperator); | |
| super.visitAsExpression(node); | |
| } | |
| @override | |
| void visitAssertInitializer(AssertInitializer node) { | |
| _tokenOrNull(node.assertKeyword); | |
| _tokenOrNull(node.leftParenthesis); | |
| _tokenOrNull(node.comma); | |
| _tokenOrNull(node.rightParenthesis); | |
| super.visitAssertInitializer(node); | |
| } | |
| @override | |
| void visitBinaryOperatorInvocation(BinaryOperatorInvocation node) { | |
| _tokenOrNull(node.operator); | |
| super.visitBinaryOperatorInvocation(node); | |
| } | |
| @override | |
| void visitBooleanLiteral(BooleanLiteral node) { | |
| _tokenOrNull(node.literal); | |
| } | |
| @override | |
| void visitCascadeIndexAssignmentTarget(CascadeIndexAssignmentTarget node) { | |
| _tokenOrNull(node.leftBracket); | |
| _tokenOrNull(node.rightBracket); | |
| super.visitCascadeIndexAssignmentTarget(node); | |
| } | |
| @override | |
| void visitCascadeIndexExpression(CascadeIndexExpression node) { | |
| _tokenOrNull(node.leftBracket); | |
| _tokenOrNull(node.rightBracket); | |
| super.visitCascadeIndexExpression(node); | |
| } | |
| @override | |
| void visitCascadeMethodInvocation(CascadeMethodInvocation node) { | |
| _tokenOrNull(node.name); | |
| node.typeArguments?.accept2(this); | |
| node.argumentList.accept2(this); | |
| } | |
| @override | |
| void visitCascadePropertyAssignmentTarget( | |
| CascadePropertyAssignmentTarget node, | |
| ) { | |
| _tokenOrNull(node.name); | |
| } | |
| @override | |
| void visitCascadePropertyExtraction(CascadePropertyExtraction node) { | |
| _tokenOrNull(node.name); | |
| } | |
| @override | |
| void visitCascadeSection(CascadeSection node) { | |
| _tokenOrNull(node.operator); | |
| super.visitCascadeSection(node); | |
| } | |
| @override | |
| void visitCompoundAssignment(CompoundAssignment node) { | |
| _tokenOrNull(node.operator); | |
| super.visitCompoundAssignment(node); | |
| } | |
| @override | |
| void visitConditionalExpression(ConditionalExpression node) { | |
| _tokenOrNull(node.question); | |
| _tokenOrNull(node.colon); | |
| super.visitConditionalExpression(node); | |
| } | |
| @override | |
| void visitConstructorFieldInitializer(ConstructorFieldInitializer node) { | |
| _tokenOrNull(node.thisKeyword); | |
| _tokenOrNull(node.fieldName2); | |
| _tokenOrNull(node.equals); | |
| super.visitConstructorFieldInitializer(node); | |
| } | |
| @override | |
| void visitConstructorInvocation(ConstructorInvocation node) { | |
| _tokenOrNull(node.keyword); | |
| node.constructorReference.accept2(this); | |
| node.argumentList.accept2(this); | |
| } | |
| @override | |
| void visitConstructorSelector(ConstructorSelector node) { | |
| _tokenOrNull(node.period); | |
| _tokenOrNull(node.name2); | |
| } | |
| @override | |
| void visitConstructorTypeReference(ConstructorTypeReference node) { | |
| node.importPrefix?.accept2(this); | |
| _tokenOrNull(node.name); | |
| node.typeArguments?.accept2(this); | |
| } | |
| @override | |
| void visitDelimitedFormalParameters(DelimitedFormalParameters node) { | |
| _tokenOrNull(node.leftDelimiter); | |
| _tokenOrNull(node.rightDelimiter); | |
| node.formalParameters.accept2(this); | |
| } | |
| @override | |
| void visitDirectAssignment(DirectAssignment node) { | |
| _tokenOrNull(node.operator); | |
| super.visitDirectAssignment(node); | |
| } | |
| @override | |
| void visitDotShorthandConstructorInvocation2( | |
| DotShorthandConstructorInvocation2 node, | |
| ) { | |
| _tokenOrNull(node.constKeyword); | |
| _tokenOrNull(node.period); | |
| _tokenOrNull(node.name); | |
| node.typeArguments?.accept2(this); | |
| node.argumentList.accept2(this); | |
| } | |
| @override | |
| void visitDotShorthandMethodInvocation(DotShorthandMethodInvocation node) { | |
| _tokenOrNull(node.period); | |
| _tokenOrNull(node.name); | |
| node.typeArguments?.accept2(this); | |
| node.argumentList.accept2(this); | |
| } | |
| @override | |
| void visitDotShorthandNameExpression(DotShorthandNameExpression node) { | |
| _tokenOrNull(node.period); | |
| _tokenOrNull(node.name); | |
| } | |
| @override | |
| void visitDoubleLiteral(DoubleLiteral node) { | |
| _tokenOrNull(node.literal); | |
| } | |
| @override | |
| void visitFormalParameterList(FormalParameterList node) { | |
| _tokenOrNull(node.leftParenthesis); | |
| _tokenOrNull(node.rightParenthesis); | |
| super.visitFormalParameterList(node); | |
| } | |
| @override | |
| void visitGenericFunctionType(GenericFunctionType node) { | |
| _tokenOrNull(node.functionKeyword); | |
| super.visitGenericFunctionType(node); | |
| } | |
| @override | |
| void visitIfElement(IfElement node) { | |
| _tokenOrNull(node.ifKeyword); | |
| _tokenOrNull(node.leftParenthesis); | |
| _tokenOrNull(node.rightParenthesis); | |
| _tokenOrNull(node.elseKeyword); | |
| super.visitIfElement(node); | |
| } | |
| @override | |
| void visitIfNull(IfNull node) { | |
| _tokenOrNull(node.operator); | |
| super.visitIfNull(node); | |
| } | |
| @override | |
| void visitIfNullAssignment(IfNullAssignment node) { | |
| _tokenOrNull(node.operator); | |
| super.visitIfNullAssignment(node); | |
| } | |
| @override | |
| void visitImportPrefixedAssignmentTarget( | |
| ImportPrefixedAssignmentTarget node, | |
| ) { | |
| node.importPrefix.accept2(this); | |
| _tokenOrNull(node.name); | |
| } | |
| @override | |
| void visitImportPrefixedFunctionInvocation( | |
| ImportPrefixedFunctionInvocation node, | |
| ) { | |
| node.importPrefix.accept2(this); | |
| _tokenOrNull(node.name); | |
| node.typeArguments?.accept2(this); | |
| node.argumentList.accept2(this); | |
| } | |
| @override | |
| void visitImportPrefixedNameExpression(ImportPrefixedNameExpression node) { | |
| node.importPrefix.accept2(this); | |
| _tokenOrNull(node.name); | |
| } | |
| @override | |
| void visitImportPrefixReference(ImportPrefixReference node) { | |
| _tokenOrNull(node.name); | |
| _tokenOrNull(node.period); | |
| } | |
| @override | |
| void visitIncrementOrDecrementExpression( | |
| IncrementOrDecrementExpression node, | |
| ) { | |
| _tokenOrNull(node.operator); | |
| super.visitIncrementOrDecrementExpression(node); | |
| } | |
| @override | |
| void visitIntegerLiteral(IntegerLiteral node) { | |
| _tokenOrNull(node.literal); | |
| } | |
| @override | |
| void visitInterpolationExpression(InterpolationExpression node) { | |
| _tokenOrNull(node.leftBracket); | |
| _tokenOrNull(node.rightBracket); | |
| super.visitInterpolationExpression(node); | |
| } | |
| @override | |
| void visitInterpolationString(InterpolationString node) { | |
| _tokenOrNull(node.contents); | |
| } | |
| @override | |
| void visitIsExpression(IsExpression node) { | |
| _tokenOrNull(node.isOperator); | |
| super.visitIsExpression(node); | |
| } | |
| @override | |
| void visitLabel(Label node) { | |
| _tokenOrNull(node.colon); | |
| super.visitLabel(node); | |
| } | |
| @override | |
| void visitListLiteral(ListLiteral node) { | |
| _tokenOrNull(node.constKeyword); | |
| _tokenOrNull(node.leftBracket); | |
| _tokenOrNull(node.rightBracket); | |
| super.visitListLiteral(node); | |
| } | |
| @override | |
| void visitLogicalAnd(LogicalAnd node) { | |
| _tokenOrNull(node.operator); | |
| super.visitLogicalAnd(node); | |
| } | |
| @override | |
| void visitLogicalNot(LogicalNot node) { | |
| _tokenOrNull(node.operator); | |
| super.visitLogicalNot(node); | |
| } | |
| @override | |
| void visitLogicalOr(LogicalOr node) { | |
| _tokenOrNull(node.operator); | |
| super.visitLogicalOr(node); | |
| } | |
| @override | |
| void visitMapLiteralEntry(MapLiteralEntry node) { | |
| _tokenOrNull(node.separator); | |
| super.visitMapLiteralEntry(node); | |
| } | |
| @override | |
| void visitNamedArgument(NamedArgument node) { | |
| _tokenOrNull(node.name); | |
| _tokenOrNull(node.colon); | |
| super.visitNamedArgument(node); | |
| } | |
| @override | |
| void visitNamedType(NamedType node) { | |
| node.importPrefix?.accept2(this); | |
| _tokenOrNull(node.name); | |
| node.typeArguments?.accept2(this); | |
| _tokenOrNull(node.question); | |
| } | |
| @override | |
| void visitNullAssertionExpression(NullAssertionExpression node) { | |
| _tokenOrNull(node.operator); | |
| super.visitNullAssertionExpression(node); | |
| } | |
| @override | |
| void visitNullLiteral(NullLiteral node) { | |
| _tokenOrNull(node.literal); | |
| } | |
| @override | |
| void visitParenthesizedExpression(ParenthesizedExpression node) { | |
| _tokenOrNull(node.leftParenthesis); | |
| _tokenOrNull(node.rightParenthesis); | |
| super.visitParenthesizedExpression(node); | |
| } | |
| @override | |
| void visitParsedCascadeName(ParsedCascadeName node) { | |
| _tokenOrNull(node.name); | |
| } | |
| @override | |
| void visitParsedDotShorthandName(ParsedDotShorthandName node) { | |
| _tokenOrNull(node.period); | |
| _tokenOrNull(node.name); | |
| } | |
| @override | |
| void visitParsedNameAccess(ParsedNameAccess node) { | |
| node.operand.accept2(this); | |
| _tokenOrNull(node.operator); | |
| _tokenOrNull(node.name); | |
| } | |
| @override | |
| void visitParsedNameAccessAssignmentTarget( | |
| ParsedNameAccessAssignmentTarget node, | |
| ) { | |
| node.operand.accept2(this); | |
| _tokenOrNull(node.operator); | |
| _tokenOrNull(node.name); | |
| } | |
| @override | |
| void visitParsedUnqualifiedName(ParsedUnqualifiedName node) { | |
| _tokenOrNull(node.name); | |
| } | |
| @override | |
| void visitParsedUnqualifiedNameAssignmentTarget( | |
| ParsedUnqualifiedNameAssignmentTarget node, | |
| ) { | |
| _tokenOrNull(node.name); | |
| } | |
| @override | |
| void visitReceiverIndexAssignmentTarget(ReceiverIndexAssignmentTarget node) { | |
| _tokenOrNull(node.leftBracket); | |
| _tokenOrNull(node.rightBracket); | |
| super.visitReceiverIndexAssignmentTarget(node); | |
| } | |
| @override | |
| void visitReceiverIndexExpression(ReceiverIndexExpression node) { | |
| _tokenOrNull(node.question); | |
| _tokenOrNull(node.leftBracket); | |
| _tokenOrNull(node.rightBracket); | |
| super.visitReceiverIndexExpression(node); | |
| } | |
| @override | |
| void visitReceiverMethodInvocation(ReceiverMethodInvocation node) { | |
| node.receiver.accept2(this); | |
| _tokenOrNull(node.operator); | |
| _tokenOrNull(node.name); | |
| node.typeArguments?.accept2(this); | |
| node.argumentList.accept2(this); | |
| } | |
| @override | |
| void visitReceiverPropertyAssignmentTarget( | |
| ReceiverPropertyAssignmentTarget node, | |
| ) { | |
| _tokenOrNull(node.operator); | |
| _tokenOrNull(node.name); | |
| super.visitReceiverPropertyAssignmentTarget(node); | |
| } | |
| @override | |
| void visitReceiverPropertyExtraction(ReceiverPropertyExtraction node) { | |
| // Parsed chains and their lowered receivers must enumerate tokens in | |
| // the same order when offsets are restored from informative data. | |
| node.receiver.accept2(this); | |
| _tokenOrNull(node.operator); | |
| _tokenOrNull(node.name); | |
| } | |
| @override | |
| void visitRecordLiteral(RecordLiteral node) { | |
| _tokenOrNull(node.constKeyword); | |
| _tokenOrNull(node.leftParenthesis); | |
| _tokenOrNull(node.rightParenthesis); | |
| super.visitRecordLiteral(node); | |
| } | |
| @override | |
| void visitRecordLiteralNamedField(RecordLiteralNamedField node) { | |
| _tokenOrNull(node.name); | |
| _tokenOrNull(node.colon); | |
| super.visitRecordLiteralNamedField(node); | |
| } | |
| @override | |
| void visitRecordTypeAnnotation(RecordTypeAnnotation node) { | |
| _tokenOrNull(node.leftParenthesis); | |
| _tokenOrNull(node.rightParenthesis); | |
| _tokenOrNull(node.question); | |
| super.visitRecordTypeAnnotation(node); | |
| } | |
| @override | |
| void visitRecordTypeAnnotationNamedField( | |
| RecordTypeAnnotationNamedField node, | |
| ) { | |
| _tokenOrNull(node.name); | |
| super.visitRecordTypeAnnotationNamedField(node); | |
| } | |
| @override | |
| void visitRecordTypeAnnotationNamedFields( | |
| RecordTypeAnnotationNamedFields node, | |
| ) { | |
| _tokenOrNull(node.leftBracket); | |
| _tokenOrNull(node.rightBracket); | |
| super.visitRecordTypeAnnotationNamedFields(node); | |
| } | |
| @override | |
| void visitRecordTypeAnnotationPositionalField( | |
| RecordTypeAnnotationPositionalField node, | |
| ) { | |
| _tokenOrNull(node.name); | |
| super.visitRecordTypeAnnotationPositionalField(node); | |
| } | |
| @override | |
| void visitRedirectingConstructorInvocation( | |
| RedirectingConstructorInvocation node, | |
| ) { | |
| _tokenOrNull(node.thisKeyword); | |
| super.visitRedirectingConstructorInvocation(node); | |
| } | |
| @override | |
| void visitRegularFormalParameter(RegularFormalParameter node) { | |
| _tokenOrNull(node.requiredKeyword); | |
| _tokenOrNull(node.name); | |
| super.visitRegularFormalParameter(node); | |
| } | |
| @override | |
| void visitSetOrMapLiteral(SetOrMapLiteral node) { | |
| _tokenOrNull(node.constKeyword); | |
| _tokenOrNull(node.leftBracket); | |
| _tokenOrNull(node.rightBracket); | |
| super.visitSetOrMapLiteral(node); | |
| } | |
| @override | |
| void visitSimpleStringLiteral(SimpleStringLiteral node) { | |
| _tokenOrNull(node.literal); | |
| } | |
| @override | |
| void visitSpreadElement(SpreadElement node) { | |
| _tokenOrNull(node.spreadOperator); | |
| super.visitSpreadElement(node); | |
| } | |
| @override | |
| void visitStaticQualifier(StaticQualifier node) { | |
| node.importPrefix?.accept2(this); | |
| _tokenOrNull(node.name); | |
| } | |
| @override | |
| void visitSuperConstructorInvocation(SuperConstructorInvocation node) { | |
| _tokenOrNull(node.superKeyword); | |
| super.visitSuperConstructorInvocation(node); | |
| } | |
| @override | |
| void visitSuperReference(SuperReference node) { | |
| _tokenOrNull(node.superKeyword); | |
| } | |
| @override | |
| void visitSymbolLiteral(SymbolLiteral node) { | |
| _tokenOrNull(node.poundSign); | |
| node.components.forEach(_tokenOrNull); | |
| } | |
| @override | |
| void visitThisExpression(ThisExpression node) { | |
| _tokenOrNull(node.thisKeyword); | |
| } | |
| @override | |
| void visitThrowExpression(ThrowExpression node) { | |
| _tokenOrNull(node.throwKeyword); | |
| super.visitThrowExpression(node); | |
| } | |
| @override | |
| void visitTypeArgumentList(TypeArgumentList node) { | |
| _tokenOrNull(node.leftBracket); | |
| _tokenOrNull(node.rightBracket); | |
| super.visitTypeArgumentList(node); | |
| } | |
| @override | |
| void visitUnaryOperatorInvocation(UnaryOperatorInvocation node) { | |
| _tokenOrNull(node.operator); | |
| super.visitUnaryOperatorInvocation(node); | |
| } | |
| @override | |
| void visitUnqualifiedFunctionInvocation(UnqualifiedFunctionInvocation node) { | |
| _tokenOrNull(node.name); | |
| node.typeArguments?.accept2(this); | |
| node.argumentList.accept2(this); | |
| } | |
| @override | |
| void visitUnqualifiedNameAssignmentTarget( | |
| UnqualifiedNameAssignmentTarget node, | |
| ) { | |
| _tokenOrNull(node.name); | |
| } | |
| @override | |
| void visitUnqualifiedNameExpression(UnqualifiedNameExpression node) { | |
| _tokenOrNull(node.name); | |
| } | |
| void _tokenOrNull(Token? token) { | |
| if (token != null) { | |
| handleToken(token); | |
| } | |
| } | |
| } | |
| class _OffsetsCollector extends _OffsetsAstVisitor { | |
| final GrowableUint32List offsets = GrowableUint32List(); | |
| @override | |
| void handleToken(Token token) { | |
| offsets.add(token.offset); | |
| } | |
| @override | |
| void visitFunctionExpression(FunctionExpression node) { | |
| offsets.add(node.offset); | |
| offsets.add(node.end - 1); | |
| } | |
| } | |
| class _SafeListIterator<T> { | |
| final List<T> _elements; | |
| int _index = 0; | |
| _SafeListIterator(this._elements); | |
| bool get hasNext { | |
| return _index < _elements.length; | |
| } | |
| T? take() { | |
| if (hasNext) { | |
| return _elements[_index++]; | |
| } else { | |
| return null; | |
| } | |
| } | |
| } | |
| extension on BinaryReader { | |
| List<T> readList<T>(T Function(BinaryReader) read) { | |
| return readTypedListFromBinaryReader(read); | |
| } | |
| } | |
| extension on Token { | |
| int? get offsetIfNotEmpty { | |
| return lexeme.isNotEmpty ? offset : null; | |
| } | |
| } | |
| extension on String { | |
| String? get nullIfEmpty { | |
| return isNotEmpty ? this : null; | |
| } | |
| } | |
| extension on DeferredResolutionReadingMixin { | |
| /// We want to have actual offsets for tokens of various constants in the | |
| /// element model, such as metadata and constant initializers. But we read | |
| /// these additional pieces of resolution data later, on demand. So, these | |
| /// offsets are different from `nameOffset` for example, which are applied | |
| /// directly after creating corresponding elements during a library loading. | |
| void deferConstantOffsets( | |
| Uint32List constantOffsets, | |
| void Function(_OffsetsApplier applier) callback, | |
| ) { | |
| deferResolutionConstantOffsets(() { | |
| var applier = _OffsetsApplier(_SafeListIterator(constantOffsets)); | |
| callback(applier); | |
| }); | |
| } | |
| } | |
| extension on List<ConstructorFragmentImpl> { | |
| Iterable<ConstructorFragmentImpl> get withOriginDeclaration { | |
| return where((e) => e.isOriginDeclaration); | |
| } | |
| } | |
| extension _ListOfPropertyAccessorFragment< | |
| T extends PropertyAccessorFragmentImpl | |
| > | |
| on List<T> { | |
| Iterable<T> get withOriginDeclaration { | |
| return where((e) => e.isOriginDeclaration); | |
| } | |
| } | |
| extension _ListOfPropertyInducingFragment< | |
| T extends PropertyInducingFragmentImpl | |
| > | |
| on List<T> { | |
| Iterable<T> get withOriginDeclaration { | |
| return where((e) => e.isOriginDeclaration); | |
| } | |
| } |