| // 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/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/data_reader.dart'; |
| import 'package:analyzer/src/summary2/data_writer.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'; |
| |
| Uint8List writeUnitInformative(CompilationUnit unit) { |
| var info = _InfoBuilder().build(unit); |
| var sink = BufferedSink(); |
| info.write(sink); |
| return sink.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 unitElement in libraryElement.units) { |
| var uri = unitElement.source.uri; |
| if (unitsInformativeBytes[uri] case var infoBytes?) { |
| _applyFromBytes(unitElement, infoBytes); |
| } |
| } |
| |
| elementFactory.isApplyingInformativeData = false; |
| } |
| |
| void _applyFromBytes(LibraryFragmentImpl unitElement, Uint8List infoBytes) { |
| var unitReader = SummaryDataReader(infoBytes); |
| var unitInfo = _InfoUnit.read(unitReader); |
| _applyFromInfo(unitElement, unitInfo); |
| } |
| |
| void _applyFromInfo(LibraryFragmentImpl unitElement, _InfoUnit unitInfo) { |
| var libraryElement = unitElement.library; |
| if (identical(libraryElement.definingCompilationUnit, unitElement)) { |
| _applyToLibrary(libraryElement, unitInfo); |
| } |
| |
| unitElement.setCodeRange(unitInfo.codeOffset, unitInfo.codeLength); |
| unitElement.lineInfo = LineInfo(unitInfo.lineStarts); |
| |
| unitElement.withoutLoadingResolution(() { |
| _applyToImports(unitElement.libraryImports, unitInfo); |
| _applyToExports(unitElement.libraryExports, unitInfo); |
| _applyToPartIncludes(unitElement.parts, unitInfo); |
| }); |
| |
| unitElement.deferConstantOffsets(unitInfo.libraryConstantOffsets, ( |
| applier, |
| ) { |
| applier.applyToImports(unitElement.libraryImports); |
| applier.applyToExports(unitElement.libraryExports); |
| applier.applyToParts(unitElement.parts); |
| }); |
| |
| _applyToAccessors( |
| unitElement.getters.notSynthetic, |
| unitInfo.topLevelGetters, |
| ); |
| _applyToAccessors( |
| unitElement.setters.notSynthetic, |
| unitInfo.topLevelSetters, |
| ); |
| |
| forCorrespondingPairs( |
| unitElement.classes |
| .where((element) => !element.isMixinApplication) |
| .toList(), |
| unitInfo.classDeclarations, |
| _applyToClassDeclaration, |
| ); |
| |
| forCorrespondingPairs( |
| unitElement.classes |
| .where((element) => element.isMixinApplication) |
| .toList(), |
| unitInfo.classTypeAliases, |
| _applyToClassTypeAlias, |
| ); |
| |
| forCorrespondingPairs( |
| unitElement.enums, |
| unitInfo.enums, |
| _applyToEnumDeclaration, |
| ); |
| |
| forCorrespondingPairs( |
| unitElement.extensions, |
| unitInfo.extensions, |
| _applyToExtensionDeclaration, |
| ); |
| |
| forCorrespondingPairs( |
| unitElement.extensionTypes, |
| unitInfo.extensionTypes, |
| _applyToExtensionTypeDeclaration, |
| ); |
| |
| forCorrespondingPairs( |
| unitElement.functions, |
| unitInfo.topLevelFunctions, |
| _applyToFunctionDeclaration, |
| ); |
| |
| forCorrespondingPairs( |
| unitElement.mixins, |
| unitInfo.mixinDeclarations, |
| _applyToMixinDeclaration, |
| ); |
| |
| forCorrespondingPairs( |
| unitElement.topLevelVariables.notSynthetic, |
| unitInfo.topLevelVariable, |
| _applyToTopLevelVariable, |
| ); |
| |
| forCorrespondingPairs( |
| unitElement.typeAliases |
| .cast<TypeAliasFragmentImpl>() |
| .where((e) => e.isFunctionTypeAliasBased) |
| .toList(), |
| unitInfo.functionTypeAliases, |
| _applyToFunctionTypeAlias, |
| ); |
| |
| forCorrespondingPairs( |
| unitElement.typeAliases |
| .cast<TypeAliasFragmentImpl>() |
| .where((e) => !e.isFunctionTypeAliasBased) |
| .toList(), |
| unitInfo.genericTypeAliases, |
| _applyToGenericTypeAlias, |
| ); |
| } |
| |
| void _applyToAccessors( |
| List<PropertyAccessorFragmentImpl> elementList, |
| List<_InfoExecutableDeclaration> infoList, |
| ) { |
| forCorrespondingPairs(elementList.notSynthetic, infoList, (element, info) { |
| element.setCodeRange(info.codeOffset, info.codeLength); |
| element.firstTokenOffset = info.firstTokenOffset; |
| element.nameOffset = info.nameOffset; |
| element.documentationComment = info.documentationComment; |
| |
| element.withoutLoadingResolution(() { |
| _applyToFormalParameters(element.formalParameters, info.parameters); |
| }); |
| |
| element.deferConstantOffsets(info.constantOffsets, (applier) { |
| applier.applyToMetadata(element.metadata); |
| applier.applyToTypeParameters(element.typeParameters); |
| applier.applyToFormalParameters(element.formalParameters); |
| }); |
| }); |
| } |
| |
| void _applyToClassDeclaration( |
| ClassFragmentImpl element, |
| _InfoClassDeclaration info, |
| ) { |
| element.setCodeRange(info.codeOffset, info.codeLength); |
| element.firstTokenOffset = info.firstTokenOffset; |
| element.nameOffset = info.nameOffset; |
| element.documentationComment = info.documentationComment; |
| |
| element.withoutLoadingResolution(() { |
| _applyToTypeParameters(element.typeParameters, info.typeParameters); |
| }); |
| |
| element.deferConstantOffsets(info.constantOffsets, (applier) { |
| applier.applyToMetadata(element.metadata); |
| applier.applyToTypeParameters(element.typeParameters); |
| }); |
| |
| _scheduleApplyMembersOffsets(element, () { |
| element.withoutLoadingResolution(() { |
| _applyToConstructors(element.constructors, info.constructors); |
| _applyToFields(element.fields, info.fields); |
| _applyToAccessors(element.getters, info.getters); |
| _applyToAccessors(element.setters, info.setters); |
| _applyToMethods(element.methods, info.methods); |
| }); |
| }); |
| } |
| |
| void _applyToClassTypeAlias( |
| ClassFragmentImpl element, |
| _InfoClassTypeAlias info, |
| ) { |
| element.setCodeRange(info.codeOffset, info.codeLength); |
| element.firstTokenOffset = info.firstTokenOffset; |
| element.nameOffset = info.nameOffset; |
| element.documentationComment = info.documentationComment; |
| |
| element.withoutLoadingResolution(() { |
| _applyToTypeParameters(element.typeParameters, info.typeParameters); |
| }); |
| |
| element.deferConstantOffsets(info.constantOffsets, (applier) { |
| applier.applyToMetadata(element.metadata); |
| applier.applyToTypeParameters(element.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> elementList, |
| List<_InfoConstructorDeclaration> infoList, |
| ) { |
| forCorrespondingPairs(elementList, infoList, (element, info) { |
| element.setCodeRange(info.codeOffset, info.codeLength); |
| element.typeNameOffset = info.typeNameOffset; |
| element.periodOffset = info.periodOffset; |
| element.firstTokenOffset = info.firstTokenOffset; |
| element.nameEnd = info.nameEnd; |
| element.nameOffset = info.nameOffset; |
| element.documentationComment = info.documentationComment; |
| |
| element.withoutLoadingResolution(() { |
| _applyToFormalParameters(element.formalParameters, info.parameters); |
| }); |
| |
| element.deferConstantOffsets(info.constantOffsets, (applier) { |
| applier.applyToMetadata(element.metadata); |
| applier.applyToFormalParameters(element.formalParameters); |
| applier.applyToConstructorInitializers(element); |
| }); |
| }); |
| } |
| |
| void _applyToEnumDeclaration( |
| EnumFragmentImpl element, |
| _InfoEnumDeclaration info, |
| ) { |
| element.setCodeRange(info.codeOffset, info.codeLength); |
| element.firstTokenOffset = info.firstTokenOffset; |
| element.nameOffset = info.nameOffset; |
| element.documentationComment = info.documentationComment; |
| |
| element.withoutLoadingResolution(() { |
| _applyToTypeParameters(element.typeParameters, info.typeParameters); |
| _applyToConstructors(element.constructors, info.constructors); |
| _applyToFields(element.fields, info.fields); |
| _applyToAccessors(element.getters, info.getters); |
| _applyToAccessors(element.setters, info.setters); |
| _applyToMethods(element.methods, info.methods); |
| }); |
| |
| element.deferConstantOffsets(info.constantOffsets, (applier) { |
| applier.applyToMetadata(element.metadata); |
| applier.applyToTypeParameters(element.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 element, |
| _InfoExtensionDeclaration info, |
| ) { |
| element.setCodeRange(info.codeOffset, info.codeLength); |
| element.firstTokenOffset = info.firstTokenOffset; |
| element.nameOffset = info.nameOffset; |
| element.documentationComment = info.documentationComment; |
| |
| element.withoutLoadingResolution(() { |
| _applyToTypeParameters(element.typeParameters, info.typeParameters); |
| }); |
| |
| _applyToFields(element.fields, info.fields); |
| _applyToAccessors(element.getters, info.getters); |
| _applyToAccessors(element.setters, info.setters); |
| _applyToMethods(element.methods, info.methods); |
| |
| element.deferConstantOffsets(info.constantOffsets, (applier) { |
| applier.applyToMetadata(element.metadata); |
| applier.applyToTypeParameters(element.typeParameters); |
| }); |
| } |
| |
| void _applyToExtensionTypeDeclaration( |
| ExtensionTypeFragmentImpl element, |
| _InfoExtensionTypeDeclaration info, |
| ) { |
| element.setCodeRange(info.codeOffset, info.codeLength); |
| element.firstTokenOffset = info.firstTokenOffset; |
| element.nameOffset = info.nameOffset; |
| element.documentationComment = info.documentationComment; |
| |
| element.withoutLoadingResolution(() { |
| _applyToTypeParameters(element.typeParameters, info.typeParameters); |
| }); |
| |
| var representationField = element.fields.first; |
| var infoRep = info.representation; |
| representationField.firstTokenOffset = infoRep.firstTokenOffset; |
| representationField.nameOffset = infoRep.fieldNameOffset; |
| representationField.setCodeRange(infoRep.codeOffset, infoRep.codeLength); |
| |
| representationField.deferConstantOffsets(infoRep.fieldConstantOffsets, ( |
| applier, |
| ) { |
| applier.applyToMetadata(representationField.metadata); |
| }); |
| |
| element.withoutLoadingResolution(() { |
| var primaryConstructor = element.constructors.first; |
| primaryConstructor.setCodeRange(infoRep.codeOffset, infoRep.codeLength); |
| primaryConstructor.typeNameOffset = info.nameOffset; |
| primaryConstructor.periodOffset = infoRep.constructorPeriodOffset; |
| primaryConstructor.firstTokenOffset = infoRep.firstTokenOffset; |
| primaryConstructor.nameOffset = infoRep.constructorNameOffset; |
| primaryConstructor.nameEnd = infoRep.constructorNameEnd; |
| |
| primaryConstructor.withoutLoadingResolution(() { |
| var representation = primaryConstructor.formalParameters.first; |
| representation.firstTokenOffset = infoRep.firstTokenOffset; |
| representation.nameOffset = infoRep.fieldNameOffset; |
| representation.setCodeRange(infoRep.codeOffset, infoRep.codeLength); |
| }); |
| |
| var restFields = element.fields.skip(1).toList(); |
| _applyToFields(restFields, info.fields); |
| |
| var restConstructors = element.constructors.skip(1).toList(); |
| _applyToConstructors(restConstructors, info.constructors); |
| |
| _applyToAccessors(element.getters, info.getters); |
| _applyToAccessors(element.setters, info.setters); |
| _applyToMethods(element.methods, info.methods); |
| }); |
| |
| element.deferConstantOffsets(info.constantOffsets, (applier) { |
| applier.applyToMetadata(element.metadata); |
| applier.applyToTypeParameters(element.typeParameters); |
| }); |
| } |
| |
| void _applyToFields( |
| List<FieldFragmentImpl> elementList, |
| List<_InfoFieldDeclaration> infoList, |
| ) { |
| forCorrespondingPairs(elementList.notSynthetic, infoList, (element, info) { |
| element.setCodeRange(info.codeOffset, info.codeLength); |
| element.firstTokenOffset = info.firstTokenOffset; |
| element.nameOffset = info.nameOffset; |
| element.documentationComment = info.documentationComment; |
| |
| element.deferConstantOffsets(info.constantOffsets, (applier) { |
| applier.applyToMetadata(element.metadata); |
| applier.applyToConstantInitializer(element); |
| }); |
| }); |
| } |
| |
| void _applyToFormalParameters( |
| List<FormalParameterFragmentImpl> parameters, |
| List<_InfoFormalParameter> infoList, |
| ) { |
| forCorrespondingPairs(parameters, infoList, (element, info) { |
| element.setCodeRange(info.codeOffset, info.codeLength); |
| element.firstTokenOffset = info.firstTokenOffset; |
| element.nameOffset = info.nameOffset; |
| _applyToTypeParameters(element.typeParameters, info.typeParameters); |
| _applyToFormalParameters(element.formalParameters, info.parameters); |
| }); |
| } |
| |
| void _applyToFunctionDeclaration( |
| TopLevelFunctionFragmentImpl element, |
| _InfoExecutableDeclaration info, |
| ) { |
| element.setCodeRange(info.codeOffset, info.codeLength); |
| element.firstTokenOffset = info.firstTokenOffset; |
| element.nameOffset = info.nameOffset; |
| element.documentationComment = info.documentationComment; |
| |
| element.withoutLoadingResolution(() { |
| _applyToTypeParameters(element.typeParameters, info.typeParameters); |
| _applyToFormalParameters(element.formalParameters, info.parameters); |
| }); |
| |
| element.deferConstantOffsets(info.constantOffsets, (applier) { |
| applier.applyToMetadata(element.metadata); |
| applier.applyToTypeParameters(element.typeParameters); |
| applier.applyToFormalParameters(element.formalParameters); |
| }); |
| } |
| |
| void _applyToFunctionTypeAlias( |
| TypeAliasFragmentImpl element, |
| _InfoFunctionTypeAlias info, |
| ) { |
| element.setCodeRange(info.codeOffset, info.codeLength); |
| element.firstTokenOffset = info.firstTokenOffset; |
| element.nameOffset = info.nameOffset; |
| element.documentationComment = info.documentationComment; |
| |
| element.withoutLoadingResolution(() { |
| _applyToTypeParameters(element.typeParameters, info.typeParameters); |
| if (element.aliasedElement case GenericFunctionTypeFragmentImpl aliased) { |
| _applyToFormalParameters(aliased.formalParameters, info.parameters); |
| } |
| }); |
| |
| _setupApplyConstantOffsetsForTypeAlias( |
| element, |
| info.constantOffsets, |
| aliasedFormalParameters: info.parameters, |
| ); |
| } |
| |
| void _applyToGenericTypeAlias( |
| TypeAliasFragmentImpl element, |
| _InfoGenericTypeAlias info, |
| ) { |
| element.setCodeRange(info.codeOffset, info.codeLength); |
| element.firstTokenOffset = info.firstTokenOffset; |
| element.nameOffset = info.nameOffset; |
| element.documentationComment = info.documentationComment; |
| |
| element.withoutLoadingResolution(() { |
| _applyToTypeParameters(element.typeParameters, info.typeParameters); |
| if (element.aliasedElement case GenericFunctionTypeFragmentImpl aliased) { |
| _applyToTypeParameters( |
| aliased.typeParameters, |
| info.aliasedTypeParameters, |
| ); |
| _applyToFormalParameters( |
| aliased.formalParameters, |
| info.aliasedFormalParameters, |
| ); |
| } |
| }); |
| |
| _setupApplyConstantOffsetsForTypeAlias( |
| element, |
| info.constantOffsets, |
| aliasedFormalParameters: info.aliasedFormalParameters, |
| aliasedTypeParameters: info.aliasedTypeParameters, |
| ); |
| } |
| |
| 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> elementList, |
| List<_InfoExecutableDeclaration> infoList, |
| ) { |
| forCorrespondingPairs(elementList, infoList, (element, info) { |
| element.setCodeRange(info.codeOffset, info.codeLength); |
| element.firstTokenOffset = info.firstTokenOffset; |
| element.nameOffset = info.nameOffset; |
| element.documentationComment = info.documentationComment; |
| |
| element.withoutLoadingResolution(() { |
| _applyToTypeParameters(element.typeParameters, info.typeParameters); |
| _applyToFormalParameters(element.formalParameters, info.parameters); |
| }); |
| |
| element.deferConstantOffsets(info.constantOffsets, (applier) { |
| applier.applyToMetadata(element.metadata); |
| applier.applyToTypeParameters(element.typeParameters); |
| applier.applyToFormalParameters(element.formalParameters); |
| }); |
| }); |
| } |
| |
| void _applyToMixinDeclaration( |
| MixinFragmentImpl element, |
| _InfoMixinDeclaration info, |
| ) { |
| element.setCodeRange(info.codeOffset, info.codeLength); |
| element.firstTokenOffset = info.firstTokenOffset; |
| element.nameOffset = info.nameOffset; |
| element.documentationComment = info.documentationComment; |
| |
| element.withoutLoadingResolution(() { |
| _applyToTypeParameters(element.typeParameters, info.typeParameters); |
| _applyToConstructors(element.constructors, info.constructors); |
| _applyToFields(element.fields, info.fields); |
| _applyToAccessors(element.getters, info.getters); |
| _applyToAccessors(element.setters, info.setters); |
| _applyToMethods(element.methods, info.methods); |
| }); |
| |
| element.deferConstantOffsets(info.constantOffsets, (applier) { |
| applier.applyToMetadata(element.metadata); |
| applier.applyToTypeParameters(element.typeParameters); |
| }); |
| } |
| |
| void _applyToPartIncludes(List<PartIncludeImpl> imports, _InfoUnit info) { |
| forCorrespondingPairs(imports, info.parts, (element, info) { |
| element.partKeywordOffset = info.partKeywordOffset; |
| }); |
| } |
| |
| void _applyToTopLevelVariable( |
| TopLevelVariableFragmentImpl element, |
| _InfoTopLevelVariable info, |
| ) { |
| element.setCodeRange(info.codeOffset, info.codeLength); |
| element.firstTokenOffset = info.firstTokenOffset; |
| element.nameOffset = info.nameOffset; |
| element.documentationComment = info.documentationComment; |
| |
| element.deferConstantOffsets(info.constantOffsets, (applier) { |
| applier.applyToMetadata(element.metadata); |
| applier.applyToConstantInitializer(element); |
| }); |
| } |
| |
| void _applyToTypeParameters( |
| List<TypeParameterFragmentImpl> elementList, |
| List<_InfoTypeParameter> infoList, |
| ) { |
| forCorrespondingPairs(elementList, infoList, (element, info) { |
| element.setCodeRange(info.codeOffset, info.codeLength); |
| element.firstTokenOffset = info.firstTokenOffset; |
| element.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 element, |
| Uint32List constantOffsets, { |
| List<_InfoFormalParameter>? aliasedFormalParameters, |
| List<_InfoTypeParameter>? aliasedTypeParameters, |
| }) { |
| element.deferConstantOffsets(constantOffsets, (applier) { |
| applier.applyToMetadata(element.metadata); |
| applier.applyToTypeParameters(element.typeParameters); |
| |
| var aliasedElement = element.aliasedElement; |
| if (aliasedElement is FunctionTypedFragmentImpl) { |
| applier.applyToTypeParameters(aliasedElement.typeParameters); |
| applier.applyToFormalParameters(aliasedElement.formalParameters); |
| if (aliasedTypeParameters != null) { |
| _applyToTypeParameters( |
| aliasedElement.typeParameters, |
| aliasedTypeParameters, |
| ); |
| } |
| if (aliasedFormalParameters != null) { |
| _applyToFormalParameters( |
| aliasedElement.formalParameters, |
| aliasedFormalParameters, |
| ); |
| } |
| } |
| }); |
| } |
| } |
| |
| 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), |
| functionTypeAliases: _buildFunctionTypeAliases(unit), |
| genericTypeAliases: _buildGenericTypeAliases(unit), |
| mixinDeclarations: _buildMixins(unit), |
| topLevelFunctions: _buildTopLevelFunctions(unit), |
| topLevelGetters: _buildTopLevelGetters(unit), |
| topLevelSetters: _buildTopLevelSetters(unit), |
| topLevelVariable: _buildTopLevelVariables(unit), |
| ); |
| } |
| |
| _InfoClassDeclaration _buildClass(ClassDeclaration node) { |
| return _InfoClassDeclaration( |
| data: _buildInterfaceData( |
| node, |
| name: node.name, |
| typeParameters: node.typeParameters, |
| members: node.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, |
| ), |
| typeNameOffset: node.returnType.offset, |
| periodOffset: node.period?.offset, |
| nameEnd: (node.name ?? node.returnType).end, |
| ); |
| } |
| |
| _InfoEnumDeclaration _buildEnum(EnumDeclaration node) { |
| return _InfoEnumDeclaration( |
| data: _buildInterfaceData( |
| node, |
| name: node.name, |
| typeParameters: node.typeParameters, |
| members: node.members, |
| fields: [ |
| ...node.constants.map(_buildEnumConstant), |
| ...node.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.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.name, |
| typeParameters: node.typeParameters, |
| members: node.members, |
| ), |
| representation: _buildRepresentation(node.representation), |
| ); |
| } |
| |
| 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 []; |
| } |
| return node.parameters.map(_buildFormalParameter).toList(); |
| } |
| |
| _InfoFunctionTypeAlias _buildFunctionTypeAlias(FunctionTypeAlias node) { |
| return _InfoFunctionTypeAlias( |
| 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, |
| ), |
| ); |
| } |
| |
| List<_InfoFunctionTypeAlias> _buildFunctionTypeAliases(CompilationUnit unit) { |
| return unit.declarations |
| .whereType<FunctionTypeAlias>() |
| .map(_buildFunctionTypeAlias) |
| .toList(); |
| } |
| |
| _InfoGenericTypeAlias _buildGenericTypeAlias(GenericTypeAlias node) { |
| var aliasedType = node.type; |
| return _InfoGenericTypeAlias( |
| firstTokenOffset: node.offset, |
| codeOffset: node.offset, |
| codeLength: node.length, |
| nameOffset: node.name.offsetIfNotEmpty, |
| documentationComment: _getDocumentationComment(node), |
| typeParameters: _buildTypeParameters(node.typeParameters), |
| aliasedTypeParameters: |
| aliasedType is GenericFunctionType |
| ? _buildTypeParameters(aliasedType.typeParameters) |
| : [], |
| aliasedFormalParameters: |
| aliasedType is GenericFunctionType |
| ? _buildFormalParameters(aliasedType.parameters) |
| : [], |
| constantOffsets: _buildConstantOffsets( |
| metadata: node.metadata, |
| typeParameters: node.typeParameters, |
| aliasedType: node.type, |
| ), |
| ); |
| } |
| |
| List<_InfoGenericTypeAlias> _buildGenericTypeAliases(CompilationUnit unit) { |
| return unit.declarations |
| .whereType<GenericTypeAlias>() |
| .map(_buildGenericTypeAlias) |
| .toList(); |
| } |
| |
| _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, |
| required List<ClassMember> members, |
| List<_InfoFieldDeclaration>? fields, |
| }) { |
| var instanceData = _buildInstanceData( |
| node, |
| name: name, |
| typeParameters: typeParameters, |
| members: members, |
| fields: fields, |
| ); |
| return _InterfaceData( |
| instanceData: instanceData, |
| constructors: |
| members |
| .whereType<ConstructorDeclaration>() |
| .map((node) => _buildConstructor(node)) |
| .toList(), |
| ); |
| } |
| |
| 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.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(); |
| } |
| |
| _InfoExtensionTypeRepresentation _buildRepresentation( |
| RepresentationDeclaration node, |
| ) { |
| var constructorName = node.constructorName; |
| return _InfoExtensionTypeRepresentation( |
| firstTokenOffset: node.offset, |
| codeOffset: node.offset, |
| codeLength: node.length, |
| constructorPeriodOffset: constructorName?.period.offset, |
| constructorNameOffset: constructorName?.name.offsetIfNotEmpty, |
| constructorNameEnd: node.leftParenthesis.offset, |
| fieldNameOffset: node.fieldName.offsetIfNotEmpty, |
| fieldConstantOffsets: _buildConstantOffsets(metadata: node.fieldMetadata), |
| ); |
| } |
| |
| _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(); |
| } |
| |
| _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 []; |
| } |
| return node.typeParameters.map(_buildTypeParameter).toList(); |
| } |
| |
| 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(BufferedSink sink) { |
| sink.writeList(typeParameters, (v) => v.write(sink)); |
| sink.writeUint30List(constantOffsets); |
| super.write(sink); |
| } |
| } |
| |
| class _InfoCombinator { |
| final int offset; |
| final int end; |
| |
| _InfoCombinator({required this.offset, required this.end}); |
| |
| factory _InfoCombinator.read(SummaryDataReader reader) { |
| return _InfoCombinator( |
| offset: reader.readUInt30(), |
| end: reader.readUInt30(), |
| ); |
| } |
| |
| void write(BufferedSink sink) { |
| sink.writeUInt30(offset); |
| sink.writeUInt30(end); |
| } |
| } |
| |
| class _InfoConstructorDeclaration extends _InfoExecutableDeclaration { |
| 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.typeNameOffset, |
| required this.periodOffset, |
| required this.nameEnd, |
| }); |
| |
| _InfoConstructorDeclaration.read(super.reader) |
| : typeNameOffset = reader.readUInt30(), |
| periodOffset = reader.readOptionalUInt30(), |
| nameEnd = reader.readOptionalUInt30(), |
| super.read(); |
| |
| @override |
| void write(BufferedSink sink) { |
| sink.writeUInt30(typeNameOffset); |
| sink.writeOptionalUInt30(periodOffset); |
| sink.writeOptionalUInt30(nameEnd); |
| super.write(sink); |
| } |
| } |
| |
| 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(BufferedSink sink) { |
| sink.writeList(typeParameters, (v) => v.write(sink)); |
| sink.writeList(parameters, (v) => v.write(sink)); |
| sink.writeUint30List(constantOffsets); |
| super.write(sink); |
| } |
| } |
| |
| class _InfoExport { |
| final int exportKeywordOffset; |
| final List<_InfoCombinator> combinators; |
| |
| _InfoExport({required this.exportKeywordOffset, required this.combinators}); |
| |
| factory _InfoExport.read(SummaryDataReader reader) { |
| return _InfoExport( |
| exportKeywordOffset: reader.readUInt30(), |
| combinators: reader.readList(_InfoCombinator.read), |
| ); |
| } |
| |
| void write(BufferedSink sink) { |
| sink.writeUInt30(exportKeywordOffset); |
| sink.writeList(combinators, (v) => v.write(sink)); |
| } |
| } |
| |
| class _InfoExtensionDeclaration extends _InfoInstanceDeclaration { |
| _InfoExtensionDeclaration({required super.data}); |
| |
| _InfoExtensionDeclaration.read(super.reader) : super.read(); |
| } |
| |
| class _InfoExtensionTypeDeclaration extends _InfoInterfaceDeclaration { |
| final _InfoExtensionTypeRepresentation representation; |
| |
| _InfoExtensionTypeDeclaration({ |
| required super.data, |
| required this.representation, |
| }); |
| |
| _InfoExtensionTypeDeclaration.read(super.reader) |
| : representation = _InfoExtensionTypeRepresentation.read(reader), |
| super.read(); |
| |
| @override |
| void write(BufferedSink sink) { |
| representation.write(sink); |
| super.write(sink); |
| } |
| } |
| |
| class _InfoExtensionTypeRepresentation { |
| final int firstTokenOffset; |
| final int codeOffset; |
| final int codeLength; |
| final int? constructorPeriodOffset; |
| final int? constructorNameOffset; |
| final int? constructorNameEnd; |
| final int? fieldNameOffset; |
| final Uint32List fieldConstantOffsets; |
| |
| _InfoExtensionTypeRepresentation({ |
| required this.firstTokenOffset, |
| required this.codeOffset, |
| required this.codeLength, |
| required this.constructorPeriodOffset, |
| required this.constructorNameOffset, |
| required this.constructorNameEnd, |
| required this.fieldNameOffset, |
| required this.fieldConstantOffsets, |
| }); |
| |
| factory _InfoExtensionTypeRepresentation.read(SummaryDataReader reader) { |
| return _InfoExtensionTypeRepresentation( |
| firstTokenOffset: reader.readUInt30(), |
| codeOffset: reader.readUInt30(), |
| codeLength: reader.readUInt30(), |
| constructorPeriodOffset: reader.readOptionalUInt30(), |
| constructorNameOffset: reader.readOptionalUInt30(), |
| constructorNameEnd: reader.readOptionalUInt30(), |
| fieldNameOffset: reader.readOptionalUInt30(), |
| fieldConstantOffsets: reader.readUInt30List(), |
| ); |
| } |
| |
| void write(BufferedSink sink) { |
| sink.writeUInt30(firstTokenOffset); |
| sink.writeUInt30(codeOffset); |
| sink.writeUInt30(codeLength); |
| sink.writeOptionalUInt30(constructorPeriodOffset); |
| sink.writeOptionalUInt30(constructorNameOffset); |
| sink.writeOptionalUInt30(constructorNameEnd); |
| sink.writeOptionalUInt30(fieldNameOffset); |
| sink.writeUint30List(fieldConstantOffsets); |
| } |
| } |
| |
| 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(BufferedSink sink) { |
| sink.writeUint30List(constantOffsets); |
| super.write(sink); |
| } |
| } |
| |
| 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(BufferedSink sink) { |
| sink.writeList(typeParameters, (v) => v.write(sink)); |
| sink.writeList(parameters, (v) => v.write(sink)); |
| super.write(sink); |
| } |
| } |
| |
| class _InfoFunctionTypeAlias extends _InfoNode { |
| final List<_InfoTypeParameter> typeParameters; |
| final List<_InfoFormalParameter> parameters; |
| final Uint32List constantOffsets; |
| |
| _InfoFunctionTypeAlias({ |
| 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(); |
| |
| _InfoFunctionTypeAlias.read(super.reader) |
| : typeParameters = reader.readList(_InfoTypeParameter.read), |
| parameters = reader.readList(_InfoFormalParameter.read), |
| constantOffsets = reader.readUInt30List(), |
| super.read(); |
| |
| @override |
| void write(BufferedSink sink) { |
| sink.writeList(typeParameters, (v) => v.write(sink)); |
| sink.writeList(parameters, (v) => v.write(sink)); |
| sink.writeUint30List(constantOffsets); |
| super.write(sink); |
| } |
| } |
| |
| class _InfoGenericTypeAlias extends _InfoNode { |
| final List<_InfoTypeParameter> typeParameters; |
| final List<_InfoTypeParameter> aliasedTypeParameters; |
| final List<_InfoFormalParameter> aliasedFormalParameters; |
| final Uint32List constantOffsets; |
| |
| _InfoGenericTypeAlias({ |
| required super.firstTokenOffset, |
| required super.codeOffset, |
| required super.codeLength, |
| required super.nameOffset, |
| required super.documentationComment, |
| required this.typeParameters, |
| required this.aliasedTypeParameters, |
| required this.aliasedFormalParameters, |
| required this.constantOffsets, |
| }) : super(); |
| |
| _InfoGenericTypeAlias.read(super.reader) |
| : typeParameters = reader.readList(_InfoTypeParameter.read), |
| aliasedTypeParameters = reader.readList(_InfoTypeParameter.read), |
| aliasedFormalParameters = reader.readList(_InfoFormalParameter.read), |
| constantOffsets = reader.readUInt30List(), |
| super.read(); |
| |
| @override |
| void write(BufferedSink sink) { |
| sink.writeList(typeParameters, (v) => v.write(sink)); |
| sink.writeList(aliasedTypeParameters, (v) => v.write(sink)); |
| sink.writeList(aliasedFormalParameters, (v) => v.write(sink)); |
| sink.writeUint30List(constantOffsets); |
| super.write(sink); |
| } |
| } |
| |
| 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(SummaryDataReader reader) { |
| return _InfoImport( |
| importKeywordOffset: reader.readUInt30(), |
| prefixOffset: reader.readOptionalUInt30(), |
| combinators: reader.readList(_InfoCombinator.read), |
| ); |
| } |
| |
| void write(BufferedSink sink) { |
| sink.writeUInt30(importKeywordOffset); |
| sink.writeOptionalUInt30(prefixOffset); |
| sink.writeList(combinators, (v) => v.write(sink)); |
| } |
| } |
| |
| 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(BufferedSink sink) { |
| sink.writeList(typeParameters, (v) => v.write(sink)); |
| sink.writeList(fields, (v) => v.write(sink)); |
| sink.writeList(getters, (v) => v.write(sink)); |
| sink.writeList(setters, (v) => v.write(sink)); |
| sink.writeList(methods, (v) => v.write(sink)); |
| sink.writeUint30List(constantOffsets); |
| super.write(sink); |
| } |
| } |
| |
| 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(BufferedSink sink) { |
| sink.writeList(constructors, (v) => v.write(sink)); |
| super.write(sink); |
| } |
| } |
| |
| class _InfoLibraryName { |
| final int offset; |
| final int length; |
| |
| _InfoLibraryName({required this.offset, required this.length}); |
| |
| factory _InfoLibraryName.read(SummaryDataReader reader) { |
| return _InfoLibraryName( |
| offset: reader.readUInt30() - 1, |
| length: reader.readUInt30(), |
| ); |
| } |
| |
| void write(BufferedSink sink) { |
| sink.writeUInt30(offset + 1); |
| sink.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(SummaryDataReader reader) |
| : firstTokenOffset = reader.readUInt30(), |
| codeOffset = reader.readUInt30(), |
| codeLength = reader.readUInt30(), |
| nameOffset = reader.readOptionalUInt30(), |
| documentationComment = reader.readStringUtf8().nullIfEmpty; |
| |
| void write(BufferedSink sink) { |
| sink.writeUInt30(firstTokenOffset); |
| sink.writeUInt30(codeOffset); |
| sink.writeUInt30(codeLength); |
| sink.writeOptionalUInt30(nameOffset); |
| sink.writeStringUtf8(documentationComment ?? ''); |
| } |
| } |
| |
| class _InfoPart { |
| final int partKeywordOffset; |
| |
| _InfoPart({required this.partKeywordOffset}); |
| |
| factory _InfoPart.read(SummaryDataReader reader) { |
| return _InfoPart(partKeywordOffset: reader.readUInt30()); |
| } |
| |
| void write(BufferedSink sink) { |
| sink.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(BufferedSink sink) { |
| sink.writeUint30List(constantOffsets); |
| super.write(sink); |
| } |
| } |
| |
| 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<_InfoFunctionTypeAlias> functionTypeAliases; |
| final List<_InfoGenericTypeAlias> genericTypeAliases; |
| final List<_InfoMixinDeclaration> mixinDeclarations; |
| final List<_InfoExecutableDeclaration> topLevelFunctions; |
| final List<_InfoExecutableDeclaration> topLevelGetters; |
| final List<_InfoExecutableDeclaration> topLevelSetters; |
| final List<_InfoTopLevelVariable> topLevelVariable; |
| |
| _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.functionTypeAliases, |
| required this.genericTypeAliases, |
| required this.mixinDeclarations, |
| required this.topLevelFunctions, |
| required this.topLevelGetters, |
| required this.topLevelSetters, |
| required this.topLevelVariable, |
| }); |
| |
| _InfoUnit.read(SummaryDataReader 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), |
| functionTypeAliases = reader.readList(_InfoFunctionTypeAlias.read), |
| genericTypeAliases = reader.readList(_InfoGenericTypeAlias.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); |
| |
| void write(BufferedSink sink) { |
| sink.writeUInt30(codeOffset); |
| sink.writeUInt30(codeLength); |
| sink.writeUint30List(lineStarts); |
| libraryName.write(sink); |
| sink.writeUint30List(libraryConstantOffsets); |
| sink.writeOptionalStringUtf8(docComment); |
| sink.writeList(imports, (v) => v.write(sink)); |
| sink.writeList(exports, (v) => v.write(sink)); |
| sink.writeList(parts, (v) => v.write(sink)); |
| sink.writeList(classDeclarations, (v) => v.write(sink)); |
| sink.writeList(classTypeAliases, (v) => v.write(sink)); |
| sink.writeList(enums, (v) => v.write(sink)); |
| sink.writeList(extensions, (v) => v.write(sink)); |
| sink.writeList(extensionTypes, (v) => v.write(sink)); |
| sink.writeList(functionTypeAliases, (v) => v.write(sink)); |
| sink.writeList(genericTypeAliases, (v) => v.write(sink)); |
| sink.writeList(mixinDeclarations, (v) => v.write(sink)); |
| sink.writeList(topLevelFunctions, (v) => v.write(sink)); |
| sink.writeList(topLevelGetters, (v) => v.write(sink)); |
| sink.writeList(topLevelSetters, (v) => v.write(sink)); |
| sink.writeList(topLevelVariable, (v) => v.write(sink)); |
| } |
| } |
| |
| 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 element) { |
| if (element is FieldFragmentImpl && element.isEnumConstant) { |
| _applyToEnumConstantInitializer(element); |
| } else if (element is VariableFragmentImpl) { |
| element.constantInitializer?.accept(this); |
| } |
| } |
| |
| void applyToConstructorInitializers(ConstructorFragmentImpl element) { |
| for (var initializer in element.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 element) { |
| var initializer = element.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 SummaryDataReader { |
| List<T> readList<T>(T Function(SummaryDataReader) 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 _ListOfElement<T extends FragmentImpl> on List<T> { |
| List<T> get notSynthetic { |
| return where((e) => !e.isSynthetic).toList(); |
| } |
| } |