| // 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/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/ast/extensions.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'; |
| |
| Uint8List writeUnitInformative(CompilationUnit unit) { |
| var info = _InfoBuilder().build(unit); |
| var writer = BinaryWriter(); |
| info.write(writer); |
| return writer.takeBytes(); |
| } |
| |
| class InformativeDataApplier { |
| bool _shouldDeferApplyMembersOffsets = true; |
| |
| void applyFromNode(LibraryFragmentImpl fragment, CompilationUnit node) { |
| _shouldDeferApplyMembersOffsets = false; |
| var unitInfo = _InfoBuilder().build(node); |
| _applyFromInfo(fragment, unitInfo); |
| } |
| |
| 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.withOriginDeclaration, |
| unitInfo.topLevelGetters, |
| ); |
| _applyToAccessors( |
| libraryFragment.setters.withOriginDeclaration, |
| unitInfo.topLevelSetters, |
| ); |
| |
| forCorrespondingPairs( |
| libraryFragment.classes |
| .where((fragment) => !fragment.isMixinApplication) |
| .toList(), |
| unitInfo.classDeclarations, |
| _applyToClassDeclaration, |
| ); |
| |
| forCorrespondingPairs( |
| libraryFragment.classes |
| .where((fragment) => fragment.isMixinApplication) |
| .toList(), |
| 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.cast<TypeAliasFragmentImpl>().toList(), |
| 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, 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.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, |
| ) { |
| parameters = parameters.where((p) => p.isOriginDeclaration).toList(); |
| forCorrespondingPairs(parameters, infoList, (fragment, info) { |
| fragment.setCodeRange(info.codeOffset, info.codeLength); |
| fragment.firstTokenOffset = info.firstTokenOffset; |
| fragment.nameOffset = info.nameOffset; |
| _applyToTypeParameters(fragment.typeParameters, info.typeParameters); |
| _applyToFormalParameters(fragment.formalParameters, info.parameters); |
| }); |
| } |
| |
| 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) { |
| return _InfoUnit( |
| codeOffset: unit.offset, |
| codeLength: unit.length, |
| lineStarts: unit.lineInfo.lineStarts, |
| libraryName: _buildLibraryName(unit), |
| libraryConstantOffsets: _buildLibraryConstantOffsets(unit), |
| docComment: _getDocumentationComment(unit.directives.firstOrNull), |
| imports: _buildImports(unit), |
| exports: _buildExports(unit), |
| parts: _buildParts(unit), |
| classDeclarations: _buildClasses(unit), |
| classTypeAliases: _buildClassTypeAliases(unit), |
| enums: _buildEnums(unit), |
| extensions: _buildExtensions(unit), |
| extensionTypes: _buildExtensionTypes(unit), |
| mixinDeclarations: _buildMixins(unit), |
| topLevelFunctions: _buildTopLevelFunctions(unit), |
| topLevelGetters: _buildTopLevelGetters(unit), |
| topLevelSetters: _buildTopLevelSetters(unit), |
| topLevelVariable: _buildTopLevelVariables(unit), |
| typeAliases: _buildTypeAliases(unit), |
| ); |
| } |
| |
| _InfoClassDeclaration _buildClass(ClassDeclaration node) { |
| return _InfoClassDeclaration( |
| data: _buildInterfaceData( |
| node, |
| name: node.namePart.typeName, |
| typeParameters: node.namePart.typeParameters, |
| primaryConstructor: node.namePart.ifTypeOrNull(), |
| members: node.body.ifTypeOrNull<BlockClassBody>()?.members ?? [], |
| ), |
| ); |
| } |
| |
| List<_InfoClassDeclaration> _buildClasses(CompilationUnit unit) { |
| return unit.declarations |
| .whereType<ClassDeclaration>() |
| .map(_buildClass) |
| .toList(); |
| } |
| |
| _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, |
| ), |
| ); |
| } |
| |
| List<_InfoClassTypeAlias> _buildClassTypeAliases(CompilationUnit unit) { |
| return unit.declarations |
| .whereType<ClassTypeAlias>() |
| .map(_buildClassTypeAlias) |
| .toList(); |
| } |
| |
| _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.accept(collector); |
| } |
| } |
| } |
| |
| void addTypeParameters(TypeParameterList? typeParameters) { |
| if (typeParameters != null) { |
| for (var typeParameter in typeParameters.typeParameters) { |
| typeParameter.metadata.accept(collector); |
| } |
| } |
| } |
| |
| void addFormalParameters(FormalParameterList? formalParameters) { |
| if (formalParameters != null) { |
| for (var parameter in formalParameters.parameters) { |
| parameter.metadata.accept(collector); |
| addFormalParameters( |
| parameter is FunctionTypedFormalParameter |
| ? parameter.parameters |
| : null, |
| ); |
| if (parameter is DefaultFormalParameter) { |
| parameter.defaultValue?.accept(collector); |
| } |
| } |
| } |
| } |
| |
| metadata?.accept(collector); |
| addDirectives(importDirectives); |
| addDirectives(exportDirectives); |
| addDirectives(partDirectives); |
| addTypeParameters(typeParameters); |
| addFormalParameters(formalParameters); |
| constantInitializer?.accept(collector); |
| constructorInitializers?.accept(collector); |
| if (enumConstants != null) { |
| for (var enumConstant in enumConstants) { |
| enumConstant.metadata.accept(collector); |
| } |
| } |
| if (aliasedType is GenericFunctionType) { |
| addTypeParameters(aliasedType.typeParameters); |
| addFormalParameters(aliasedType.parameters); |
| } |
| enumConstantArguments?.typeArguments?.accept(collector); |
| enumConstantArguments?.argumentList.accept(collector); |
| return Uint32List.fromList(collector.offsets); |
| } |
| |
| _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.typeName?.offset, |
| periodOffset: node.period?.offset, |
| nameEnd: (node.name ?? node.typeName)?.end, |
| ); |
| } |
| |
| _InfoEnumDeclaration _buildEnum(EnumDeclaration node) { |
| return _InfoEnumDeclaration( |
| data: _buildInterfaceData( |
| node, |
| name: node.namePart.typeName, |
| typeParameters: node.namePart.typeParameters, |
| primaryConstructor: node.namePart.ifTypeOrNull(), |
| 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, |
| ), |
| ); |
| } |
| |
| List<_InfoEnumDeclaration> _buildEnums(CompilationUnit unit) { |
| return unit.declarations |
| .whereType<EnumDeclaration>() |
| .map(_buildEnum) |
| .toList(); |
| } |
| |
| _InfoExport _buildExport(ExportDirective node) { |
| return _InfoExport( |
| exportKeywordOffset: node.exportKeyword.offset, |
| combinators: _buildCombinators(node.combinators), |
| ); |
| } |
| |
| List<_InfoExport> _buildExports(CompilationUnit unit) { |
| return unit.directives |
| .whereType<ExportDirective>() |
| .map(_buildExport) |
| .toList(); |
| } |
| |
| _InfoExtensionDeclaration _buildExtension(ExtensionDeclaration node) { |
| return _InfoExtensionDeclaration( |
| data: _buildInstanceData( |
| node, |
| name: node.name, |
| typeParameters: node.typeParameters, |
| members: node.body.members, |
| ), |
| ); |
| } |
| |
| List<_InfoExtensionDeclaration> _buildExtensions(CompilationUnit unit) { |
| return unit.declarations |
| .whereType<ExtensionDeclaration>() |
| .map(_buildExtension) |
| .toList(); |
| } |
| |
| _InfoExtensionTypeDeclaration _buildExtensionType( |
| ExtensionTypeDeclaration node, |
| ) { |
| return _InfoExtensionTypeDeclaration( |
| data: _buildInterfaceData( |
| node, |
| name: node.primaryConstructor.typeName, |
| typeParameters: node.primaryConstructor.typeParameters, |
| primaryConstructor: node.primaryConstructor, |
| members: node.body.ifTypeOrNull<BlockClassBody>()?.members ?? [], |
| ), |
| ); |
| } |
| |
| List<_InfoExtensionTypeDeclaration> _buildExtensionTypes( |
| CompilationUnit unit, |
| ) { |
| return unit.declarations |
| .whereType<ExtensionTypeDeclaration>() |
| .map(_buildExtensionType) |
| .toList(); |
| } |
| |
| _InfoFieldDeclaration _buildField(VariableDeclaration node) { |
| var codeOffset = _codeOffsetForVariable(node); |
| var declaration = node.parent!.parent 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.initializer, |
| ), |
| ); |
| } |
| |
| _InfoFormalParameter _buildFormalParameter(FormalParameter node) { |
| var notDefault = node.notDefault; |
| |
| var (typeParameters, parameters) = switch (notDefault) { |
| FunctionTypedFormalParameter p => (p.typeParameters, p.parameters), |
| FieldFormalParameter p => (p.typeParameters, p.parameters), |
| SuperFormalParameter p => (p.typeParameters, p.parameters), |
| _ => (null, null), |
| }; |
| |
| return _InfoFormalParameter( |
| firstTokenOffset: node.offset, |
| codeOffset: node.offset, |
| codeLength: node.length, |
| nameOffset: node.name?.offsetIfNotEmpty, |
| typeParameters: _buildTypeParameters(typeParameters), |
| parameters: _buildFormalParameters(parameters), |
| ); |
| } |
| |
| List<_InfoFormalParameter> _buildFormalParameters(FormalParameterList? node) { |
| if (node == null) { |
| return []; |
| } |
| var parameters = node.parameters; |
| 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.prefix?.token.offsetIfNotEmpty, |
| combinators: _buildCombinators(node.combinators), |
| ); |
| } |
| |
| List<_InfoImport> _buildImports(CompilationUnit unit) { |
| return unit.directives |
| .whereType<ImportDirective>() |
| .map(_buildImport) |
| .toList(); |
| } |
| |
| _InstanceData _buildInstanceData( |
| Declaration node, { |
| required Token? name, |
| required TypeParameterList? typeParameters, |
| required List<ClassMember> members, |
| List<_InfoFieldDeclaration>? fields, |
| }) { |
| 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 ?? |
| members |
| .whereType<FieldDeclaration>() |
| .expand((declaration) => declaration.fields.variables) |
| .map((node) => _buildField(node)) |
| .toList(), |
| getters: members |
| .whereType<MethodDeclaration>() |
| .where((node) => node.isGetter) |
| .map(_buildMethodDeclaration) |
| .toList(), |
| setters: members |
| .whereType<MethodDeclaration>() |
| .where((node) => node.isSetter) |
| .map(_buildMethodDeclaration) |
| .toList(), |
| methods: members |
| .whereType<MethodDeclaration>() |
| .where((node) => !node.isGetter && !node.isSetter) |
| .map(_buildMethodDeclaration) |
| .toList(), |
| 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, |
| ); |
| return _InterfaceData( |
| instanceData: instanceData, |
| constructors: [ |
| if (primaryConstructor != null) |
| _buildPrimaryConstructor(primaryConstructor), |
| ...members.whereType<ConstructorDeclaration>().map(_buildConstructor), |
| ], |
| ); |
| } |
| |
| Uint32List _buildLibraryConstantOffsets(CompilationUnit unit) { |
| Directive? firstDirective; |
| for (var directive in unit.directives) { |
| firstDirective ??= directive; |
| if (directive is LibraryDirective) { |
| break; |
| } |
| } |
| return _buildConstantOffsets( |
| metadata: firstDirective?.metadata, |
| importDirectives: unit.directives.whereType<ImportDirective>(), |
| exportDirectives: unit.directives.whereType<ExportDirective>(), |
| partDirectives: unit.directives.whereType<PartDirective>(), |
| ); |
| } |
| |
| _InfoLibraryName _buildLibraryName(CompilationUnit unit) { |
| var nameOffset = -1; |
| var nameLength = 0; |
| for (var directive in unit.directives) { |
| if (directive is LibraryDirective) { |
| var libraryName = directive.name; |
| if (libraryName != null) { |
| nameOffset = libraryName.offset; |
| nameLength = libraryName.length; |
| } |
| break; |
| } |
| } |
| 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(MixinDeclaration node) { |
| return _InfoMixinDeclaration( |
| data: _buildInterfaceData( |
| node, |
| name: node.name, |
| typeParameters: node.typeParameters, |
| members: node.body.members, |
| ), |
| ); |
| } |
| |
| List<_InfoMixinDeclaration> _buildMixins(CompilationUnit unit) { |
| return unit.declarations |
| .whereType<MixinDeclaration>() |
| .map(_buildMixin) |
| .toList(); |
| } |
| |
| _InfoPart _buildPart(PartDirective node) { |
| return _InfoPart(partKeywordOffset: node.partKeyword.offset); |
| } |
| |
| List<_InfoPart> _buildParts(CompilationUnit unit) { |
| return unit.directives.whereType<PartDirective>().map(_buildPart).toList(); |
| } |
| |
| _InfoConstructorDeclaration _buildPrimaryConstructor( |
| PrimaryConstructorDeclaration node, |
| ) { |
| return _InfoConstructorDeclaration( |
| firstTokenOffset: node.offset, |
| codeOffset: node.offset, |
| codeLength: node.length, |
| nameOffset: node.constructorName?.name.offsetIfNotEmpty, |
| documentationComment: null, |
| typeParameters: const [], |
| parameters: _buildFormalParameters(node.formalParameters), |
| constantOffsets: _buildConstantOffsets( |
| formalParameters: node.formalParameters, |
| ), |
| newKeywordOffset: null, |
| factoryKeywordOffset: null, |
| typeNameOffset: node.typeName.offset, |
| periodOffset: node.constructorName?.period.offset, |
| nameEnd: (node.constructorName?.name ?? node.typeName).end, |
| ); |
| } |
| |
| _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, |
| ), |
| ); |
| } |
| |
| List<_InfoExecutableDeclaration> _buildTopLevelFunctions( |
| CompilationUnit unit, |
| ) { |
| return unit.declarations |
| .whereType<FunctionDeclaration>() |
| .where((node) => !(node.isGetter || node.isSetter)) |
| .map(_buildTopLevelFunction) |
| .toList(); |
| } |
| |
| List<_InfoExecutableDeclaration> _buildTopLevelGetters(CompilationUnit unit) { |
| return unit.declarations |
| .whereType<FunctionDeclaration>() |
| .where((node) => node.isGetter) |
| .map(_buildTopLevelFunction) |
| .toList(); |
| } |
| |
| List<_InfoExecutableDeclaration> _buildTopLevelSetters(CompilationUnit unit) { |
| return unit.declarations |
| .whereType<FunctionDeclaration>() |
| .where((node) => node.isSetter) |
| .map(_buildTopLevelFunction) |
| .toList(); |
| } |
| |
| _InfoTopLevelVariable _buildTopLevelVariable(VariableDeclaration node) { |
| var codeOffset = _codeOffsetForVariable(node); |
| var declaration = node.parent!.parent 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.initializer, |
| ), |
| ); |
| } |
| |
| List<_InfoTopLevelVariable> _buildTopLevelVariables(CompilationUnit unit) { |
| return unit.declarations |
| .whereType<TopLevelVariableDeclaration>() |
| .expand((declaration) => declaration.variables.variables) |
| .map(_buildTopLevelVariable) |
| .toList(); |
| } |
| |
| List<_InfoTypeAlias> _buildTypeAliases(CompilationUnit unit) { |
| return unit.declarations |
| .map((declaration) { |
| switch (declaration) { |
| case FunctionTypeAlias(): |
| return _buildFunctionTypeAlias(declaration); |
| case GenericTypeAlias(): |
| return _buildGenericTypeAlias(declaration); |
| default: |
| return null; |
| } |
| }) |
| .nonNulls |
| .toList(); |
| } |
| |
| _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.parent as VariableDeclarationList; |
| if (variableList.variables[0] == node) { |
| codeOffset = variableList.parent!.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; |
| |
| _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, |
| }); |
| |
| _InfoConstructorDeclaration.read(super.reader) |
| : newKeywordOffset = reader.readOptionalUint30(), |
| factoryKeywordOffset = reader.readOptionalUint30(), |
| typeNameOffset = reader.readOptionalUint30(), |
| periodOffset = reader.readOptionalUint30(), |
| nameEnd = reader.readOptionalUint30(), |
| super.read(); |
| |
| @override |
| void write(BinaryWriter writer) { |
| writer.writeOptionalUint30(newKeywordOffset); |
| writer.writeOptionalUint30(factoryKeywordOffset); |
| writer.writeOptionalUint30(typeNameOffset); |
| writer.writeOptionalUint30(periodOffset); |
| writer.writeOptionalUint30(nameEnd); |
| 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 this.typeParameters, |
| required this.parameters, |
| }) : super(documentationComment: null); |
| |
| _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.constantInitializer?.accept(this); |
| } |
| } |
| |
| void applyToConstructorInitializers(ConstructorFragmentImpl fragment) { |
| for (var initializer in fragment.constantInitializers) { |
| initializer.accept(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); |
| applyToFormalParameters(formalParameters.formalParameters); |
| 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.accept(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 visitSimpleFormalParameter(SimpleFormalParameter node) { |
| super.visitSimpleFormalParameter(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 visitSimpleIdentifier(SimpleIdentifier node) { |
| if (isNotSerializableMarker(node)) { |
| return; |
| } |
| |
| super.visitSimpleIdentifier(node); |
| } |
| |
| void _applyToEnumConstantInitializer(FieldFragmentImpl fragment) { |
| var initializer = fragment.constantInitializer; |
| if (initializer is InstanceCreationExpressionImpl) { |
| initializer.constructorName.type.typeArguments?.accept(this); |
| initializer.argumentList.accept(this); |
| } |
| } |
| } |
| |
| abstract class _OffsetsAstVisitor extends RecursiveAstVisitor<void> { |
| void handleToken(Token token); |
| |
| @override |
| void visitAnnotation(Annotation node) { |
| _tokenOrNull(node.atSign); |
| _tokenOrNull(node.period); |
| 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 visitAssignmentExpression(AssignmentExpression node) { |
| _tokenOrNull(node.operator); |
| super.visitAssignmentExpression(node); |
| } |
| |
| @override |
| void visitBinaryExpression(BinaryExpression node) { |
| _tokenOrNull(node.operator); |
| super.visitBinaryExpression(node); |
| } |
| |
| @override |
| void visitBooleanLiteral(BooleanLiteral node) { |
| _tokenOrNull(node.literal); |
| } |
| |
| @override |
| void visitConditionalExpression(ConditionalExpression node) { |
| _tokenOrNull(node.question); |
| _tokenOrNull(node.colon); |
| super.visitConditionalExpression(node); |
| } |
| |
| @override |
| void visitConstructorFieldInitializer(ConstructorFieldInitializer node) { |
| _tokenOrNull(node.thisKeyword); |
| _tokenOrNull(node.equals); |
| super.visitConstructorFieldInitializer(node); |
| } |
| |
| @override |
| void visitConstructorName(ConstructorName node) { |
| node.type.accept(this); |
| _tokenOrNull(node.period); |
| node.name?.accept(this); |
| } |
| |
| @override |
| void visitDotShorthandConstructorInvocation( |
| DotShorthandConstructorInvocation node, |
| ) { |
| _tokenOrNull(node.constKeyword); |
| _tokenOrNull(node.period); |
| node.constructorName.accept(this); |
| node.argumentList.accept(this); |
| } |
| |
| /// When we read from bytes, [DotShorthandInvocation]s are not rewritten to |
| /// [DotShorthandConstructorInvocation]s when they're resolved to be |
| /// constructor invocations. However, since the tokens happen to be the same |
| /// between the two in this case, we have the same offsets. |
| @override |
| void visitDotShorthandInvocation(DotShorthandInvocation node) { |
| _tokenOrNull(node.period); |
| node.memberName.accept(this); |
| node.typeArguments?.accept(this); |
| node.argumentList.accept(this); |
| } |
| |
| @override |
| void visitDotShorthandPropertyAccess(DotShorthandPropertyAccess node) { |
| _tokenOrNull(node.period); |
| node.propertyName.accept(this); |
| } |
| |
| @override |
| void visitDoubleLiteral(DoubleLiteral node) { |
| _tokenOrNull(node.literal); |
| } |
| |
| @override |
| void visitFormalParameterList(FormalParameterList node) { |
| _tokenOrNull(node.leftParenthesis); |
| _tokenOrNull(node.leftDelimiter); |
| _tokenOrNull(node.rightDelimiter); |
| _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 visitImportPrefixReference(ImportPrefixReference node) { |
| _tokenOrNull(node.name); |
| _tokenOrNull(node.period); |
| } |
| |
| @override |
| void visitIndexExpression(IndexExpression node) { |
| _tokenOrNull(node.leftBracket); |
| _tokenOrNull(node.rightBracket); |
| super.visitIndexExpression(node); |
| } |
| |
| @override |
| void visitInstanceCreationExpression(InstanceCreationExpression node) { |
| _tokenOrNull(node.keyword); |
| node.constructorName.accept(this); |
| node.argumentList.accept(this); |
| } |
| |
| @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 visitMapLiteralEntry(MapLiteralEntry node) { |
| _tokenOrNull(node.separator); |
| super.visitMapLiteralEntry(node); |
| } |
| |
| @override |
| void visitMethodInvocation(MethodInvocation node) { |
| node.target?.accept(this); |
| _tokenOrNull(node.operator); |
| node.methodName.accept(this); |
| node.typeArguments?.accept(this); |
| node.argumentList.accept(this); |
| } |
| |
| @override |
| void visitNamedType(NamedType node) { |
| node.importPrefix?.accept(this); |
| _tokenOrNull(node.name); |
| node.typeArguments?.accept(this); |
| _tokenOrNull(node.question); |
| } |
| |
| @override |
| void visitNullLiteral(NullLiteral node) { |
| _tokenOrNull(node.literal); |
| } |
| |
| @override |
| void visitParenthesizedExpression(ParenthesizedExpression node) { |
| _tokenOrNull(node.leftParenthesis); |
| _tokenOrNull(node.rightParenthesis); |
| super.visitParenthesizedExpression(node); |
| } |
| |
| @override |
| void visitPostfixExpression(PostfixExpression node) { |
| _tokenOrNull(node.operator); |
| super.visitPostfixExpression(node); |
| } |
| |
| @override |
| void visitPrefixedIdentifier(PrefixedIdentifier node) { |
| node.prefix.accept(this); |
| _tokenOrNull(node.period); |
| node.identifier.accept(this); |
| } |
| |
| @override |
| void visitPrefixExpression(PrefixExpression node) { |
| _tokenOrNull(node.operator); |
| super.visitPrefixExpression(node); |
| } |
| |
| @override |
| void visitPropertyAccess(PropertyAccess node) { |
| node.target?.accept(this); |
| _tokenOrNull(node.operator); |
| node.propertyName.accept(this); |
| } |
| |
| @override |
| void visitRecordLiteral(RecordLiteral node) { |
| _tokenOrNull(node.constKeyword); |
| _tokenOrNull(node.leftParenthesis); |
| _tokenOrNull(node.rightParenthesis); |
| super.visitRecordLiteral(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); |
| _tokenOrNull(node.period); |
| super.visitRedirectingConstructorInvocation(node); |
| } |
| |
| @override |
| void visitSetOrMapLiteral(SetOrMapLiteral node) { |
| _tokenOrNull(node.constKeyword); |
| _tokenOrNull(node.leftBracket); |
| _tokenOrNull(node.rightBracket); |
| super.visitSetOrMapLiteral(node); |
| } |
| |
| @override |
| void visitSimpleFormalParameter(SimpleFormalParameter node) { |
| _tokenOrNull(node.requiredKeyword); |
| _tokenOrNull(node.name); |
| super.visitSimpleFormalParameter(node); |
| } |
| |
| @override |
| void visitSimpleIdentifier(SimpleIdentifier node) { |
| _tokenOrNull(node.token); |
| } |
| |
| @override |
| void visitSimpleStringLiteral(SimpleStringLiteral node) { |
| _tokenOrNull(node.literal); |
| } |
| |
| @override |
| void visitSpreadElement(SpreadElement node) { |
| _tokenOrNull(node.spreadOperator); |
| super.visitSpreadElement(node); |
| } |
| |
| @override |
| void visitSuperConstructorInvocation(SuperConstructorInvocation node) { |
| _tokenOrNull(node.superKeyword); |
| _tokenOrNull(node.period); |
| super.visitSuperConstructorInvocation(node); |
| } |
| |
| @override |
| void visitSuperExpression(SuperExpression 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); |
| } |
| |
| void _tokenOrNull(Token? token) { |
| if (token != null) { |
| handleToken(token); |
| } |
| } |
| } |
| |
| class _OffsetsCollector extends _OffsetsAstVisitor { |
| final List<int> offsets = []; |
| |
| @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 readTypedList(() => read(this)); |
| } |
| } |
| |
| 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 _ListOfPropertyAccessorFragment< |
| T extends PropertyAccessorFragmentImpl |
| > |
| on List<T> { |
| List<T> get withOriginDeclaration { |
| return where((e) => e.isOriginDeclaration).toList(); |
| } |
| } |
| |
| extension _ListOfPropertyInducingFragment< |
| T extends PropertyInducingFragmentImpl |
| > |
| on List<T> { |
| List<T> get withOriginDeclaration { |
| return where((e) => e.isOriginDeclaration).toList(); |
| } |
| } |