blob: ceb91b244ef7605772f2cef9c36c9e8186c43e4d [file] [log] [blame]
// Copyright (c) 2020, 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:_fe_analyzer_shared/src/type_inference/type_analyzer_operations.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/source/source.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/analysis/info_declaration_store.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/field_name_non_promotability_info.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/name_union.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/error/inference_error.dart';
import 'package:analyzer/src/fine/library_manifest.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary2/ast_binary_reader.dart';
import 'package:analyzer/src/summary2/ast_binary_tag.dart';
import 'package:analyzer/src/summary2/data_reader.dart';
import 'package:analyzer/src/summary2/element_flags.dart';
import 'package:analyzer/src/summary2/export.dart';
import 'package:analyzer/src/summary2/informative_data.dart';
import 'package:analyzer/src/summary2/linked_element_factory.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/utilities/extensions/collection.dart';
import 'package:analyzer/src/utilities/extensions/element.dart';
import 'package:analyzer/src/utilities/extensions/string.dart';
import 'package:analyzer/src/utilities/uri_cache.dart';
import 'package:pub_semver/pub_semver.dart';
class BundleReader {
final SummaryDataReader _reader;
final Map<Uri, Uint8List> _unitsInformativeBytes;
final InfoDeclarationStore _infoDeclarationStore;
final Map<Uri, LibraryReader> libraryMap = {};
BundleReader({
required LinkedElementFactory elementFactory,
required Uint8List resolutionBytes,
Map<Uri, Uint8List> unitsInformativeBytes = const {},
required InfoDeclarationStore infoDeclarationStore,
required Map<Uri, LibraryManifest> libraryManifests,
}) : _reader = SummaryDataReader(resolutionBytes),
_unitsInformativeBytes = unitsInformativeBytes,
_infoDeclarationStore = infoDeclarationStore {
const bytesOfU32 = 4;
const countOfU32 = 4;
_reader.offset = _reader.bytes.length - bytesOfU32 * countOfU32;
var baseResolutionOffset = _reader.readUInt32();
var librariesOffset = _reader.readUInt32();
var referencesOffset = _reader.readUInt32();
var stringsOffset = _reader.readUInt32();
_reader.createStringTable(stringsOffset);
var referenceReader = _ReferenceReader(
elementFactory,
_reader,
referencesOffset,
);
_reader.offset = librariesOffset;
var libraryHeaderList = _reader.readTypedList(() {
return _LibraryHeader(
uri: uriCache.parse(_reader.readStringReference()),
offset: _reader.readUInt30(),
classMembersLengths: _reader.readUInt30List(),
);
});
for (var libraryHeader in libraryHeaderList) {
var uri = libraryHeader.uri;
var reference = elementFactory.rootReference.getChild('$uri');
libraryMap[uri] = LibraryReader._(
elementFactory: elementFactory,
reader: _reader,
uri: uri,
unitsInformativeBytes: _unitsInformativeBytes,
baseResolutionOffset: baseResolutionOffset,
referenceReader: referenceReader,
reference: reference,
offset: libraryHeader.offset,
classMembersLengths: libraryHeader.classMembersLengths,
infoDeclarationStore: _infoDeclarationStore,
manifest: libraryManifests[uri],
);
}
}
}
class ClassElementLinkedData extends ElementLinkedData<ClassFragmentImpl> {
ApplyConstantOffsets? applyConstantOffsets;
void Function()? _readMembers;
void Function()? applyInformativeDataToMembers;
ClassElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required LibraryFragmentImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@override
void readMembers(covariant ClassFragmentImpl fragment) {
// Read members of all fragments, in order.
// So we always read a method augmentation after its target.
for (var fragment in fragment.element.fragments) {
var linkedData = fragment.linkedData;
if (linkedData is ClassElementLinkedData) {
linkedData._readSingleFragmentMembers(fragment);
}
}
}
@override
void _clearLinkedDataOnRead(ClassFragmentImpl element) {
// Don't clear yet, we use it to read members on demand.
}
@override
void _read(element, reader) {
element.metadata = reader._readAnnotationList(unitElement: unitElement);
_readTypeParameters(reader, element.typeParameters);
element.supertype = reader._readOptionalInterfaceType();
element.mixins = reader._readInterfaceTypeList();
element.interfaces = reader._readInterfaceTypeList();
applyConstantOffsets?.perform();
}
void _readSingleFragmentMembers(ClassFragmentImpl element) {
// We might read class members before other properties.
element.linkedData?.read(element);
element.linkedData = null;
if (element.isMixinApplication) {
element.constructors;
} else {
_readMembers?.call();
_readMembers = null;
applyInformativeDataToMembers?.call();
applyInformativeDataToMembers = null;
}
}
}
class CompilationUnitElementLinkedData
extends ElementLinkedData<LibraryFragmentImpl> {
ApplyConstantOffsets? applyConstantOffsets;
CompilationUnitElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required LibraryFragmentImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@override
void _clearLinkedDataOnRead(LibraryFragmentImpl element) {
element.linkedData = null;
}
@override
void _read(element, reader) {
for (var import in element.libraryImports) {
import.metadata = reader._readAnnotationList(unitElement: unitElement);
var uri = import.uri;
if (uri is DirectiveUriWithLibraryImpl) {
uri.library2 = reader.libraryOfUri(uri.source.uri);
}
}
for (var export in element.libraryExports) {
export.metadata = reader._readAnnotationList(unitElement: unitElement);
var uri = export.uri;
if (uri is DirectiveUriWithLibraryImpl) {
uri.library2 = reader.libraryOfUri(uri.source.uri);
}
}
for (var part in element.parts) {
part.metadata = reader._readAnnotationList(unitElement: unitElement);
}
applyConstantOffsets?.perform();
}
}
class ConstructorElementLinkedData
extends ElementLinkedData<ConstructorFragmentImpl> {
ApplyConstantOffsets? applyConstantOffsets;
ConstructorElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required LibraryFragmentImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@override
void _clearLinkedDataOnRead(ConstructorFragmentImpl element) {
element.linkedData = null;
}
@override
void _read(element, reader) {
_addEnclosingElementTypeParameters(reader, element);
element.metadata = reader._readAnnotationList(unitElement: unitElement);
reader._addFormalParameters(element.parameters);
_readFormalParameters(reader, element.parameters);
element.superConstructor = reader.readElement() as ConstructorElementMixin?;
element.redirectedConstructor =
reader.readElement() as ConstructorElementMixin?;
element.constantInitializers = reader._readNodeList();
applyConstantOffsets?.perform();
}
}
/// Lazy reader of resolution information.
abstract class ElementLinkedData<E extends FragmentImpl> {
final Reference reference;
final LibraryReader _libraryReader;
final LibraryFragmentImpl unitElement;
/// When this object is created, this offset is the offset of the resolution
/// information in the [_libraryReader]. After reading is done, this offset
/// is set to `-1`.
int _offset;
ElementLinkedData(
this.reference,
LibraryReader libraryReader,
this.unitElement,
int offset,
) : _libraryReader = libraryReader,
_offset = offset;
void read(FragmentImpl element) {
_clearLinkedDataOnRead(element as E);
if (_offset == -1) {
return;
}
var dataReader = _libraryReader._reader.fork(_offset);
_offset = -1;
var reader = ResolutionReader(
_libraryReader._elementFactory,
_libraryReader._referenceReader,
dataReader,
);
_read(element, reader);
}
/// Ensure that all members of the [element] are available. This includes
/// being able to ask them for example using [ClassElement.methods2], and
/// as well access them through their [Reference]s. For a class declaration
/// this means reading them, for a named mixin application this means
/// computing constructors.
void readMembers(InstanceFragmentImpl element) {}
void _addEnclosingElementTypeParameters(
ResolutionReader reader,
FragmentImpl element,
) {
var enclosing = element.enclosingElement3;
if (enclosing is InstanceFragmentImpl) {
reader._addTypeParameters(enclosing.typeParameters);
} else if (enclosing is LibraryFragmentImpl) {
// Nothing.
} else if (enclosing is EnumFragmentImpl) {
reader._addTypeParameters(enclosing.typeParameters);
} else if (enclosing is ExtensionFragmentImpl) {
reader._addTypeParameters(enclosing.typeParameters);
} else if (enclosing is MixinFragmentImpl) {
reader._addTypeParameters(enclosing.typeParameters);
} else {
throw UnimplementedError('${enclosing.runtimeType}');
}
}
void _clearLinkedDataOnRead(E element);
void _read(E element, ResolutionReader reader);
void _readFormalParameters(
ResolutionReader reader,
List<FormalParameterFragmentImpl> parameters,
) {
for (var parameter in parameters) {
parameter.metadata = reader._readAnnotationList(unitElement: unitElement);
_readTypeParameters(reader, parameter.typeParameters);
_readFormalParameters(reader, parameter.parameters);
parameter.type = reader.readRequiredType();
if (parameter is ConstVariableElement) {
var defaultParameter = parameter as ConstVariableElement;
var initializer = reader._readOptionalExpression();
if (initializer != null) {
defaultParameter.constantInitializer = initializer;
}
}
if (parameter is FieldFormalParameterFragmentImpl) {
parameter.field = reader.readElement() as FieldFragmentImpl?;
}
}
}
void _readTypeParameters(
ResolutionReader reader,
List<TypeParameterFragmentImpl> typeParameters,
) {
reader._addTypeParameters(typeParameters);
for (var typeParameter in typeParameters) {
typeParameter.metadata = reader._readAnnotationList(
unitElement: unitElement,
);
typeParameter.bound = reader.readType();
typeParameter.defaultType = reader.readType();
}
}
}
class EnumElementLinkedData extends ElementLinkedData<EnumFragmentImpl> {
ApplyConstantOffsets? applyConstantOffsets;
EnumElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required LibraryFragmentImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@override
void _clearLinkedDataOnRead(EnumFragmentImpl element) {
element.linkedData = null;
}
@override
void _read(element, reader) {
element.metadata = reader._readAnnotationList(
unitElement: element.enclosingElement3,
);
_readTypeParameters(reader, element.typeParameters);
element.supertype = reader._readOptionalInterfaceType();
element.mixins = reader._readInterfaceTypeList();
element.interfaces = reader._readInterfaceTypeList();
applyConstantOffsets?.perform();
}
}
class ExtensionElementLinkedData
extends ElementLinkedData<ExtensionFragmentImpl> {
ApplyConstantOffsets? applyConstantOffsets;
ExtensionElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required LibraryFragmentImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@override
void _clearLinkedDataOnRead(ExtensionFragmentImpl element) {
element.linkedData = null;
}
@override
void _read(element, reader) {
element.metadata = reader._readAnnotationList(
unitElement: element.enclosingElement3,
);
_readTypeParameters(reader, element.typeParameters);
var extendedType = reader.readRequiredType();
var augmented = element.augmentedInternal;
augmented.extendedType = extendedType;
applyConstantOffsets?.perform();
}
}
class ExtensionTypeElementLinkedData
extends ElementLinkedData<ExtensionTypeFragmentImpl> {
ApplyConstantOffsets? applyConstantOffsets;
ExtensionTypeElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required LibraryFragmentImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@override
void _clearLinkedDataOnRead(ExtensionTypeFragmentImpl element) {
element.linkedData = null;
}
@override
void _read(element, reader) {
element.metadata = reader._readAnnotationList(
unitElement: element.enclosingElement3,
);
_readTypeParameters(reader, element.typeParameters);
element.interfaces = reader._readInterfaceTypeList();
element.typeErasure = reader.readRequiredType();
applyConstantOffsets?.perform();
}
}
class FieldElementLinkedData extends ElementLinkedData<FieldFragmentImpl> {
ApplyConstantOffsets? applyConstantOffsets;
FieldElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required LibraryFragmentImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@override
void _clearLinkedDataOnRead(FieldFragmentImpl element) {
element.linkedData = null;
}
@override
void _read(element, reader) {
_addEnclosingElementTypeParameters(reader, element);
element.metadata = reader._readAnnotationList(unitElement: unitElement);
element.type = reader.readRequiredType();
if (element is ConstFieldFragmentImpl) {
var initializer = reader._readOptionalExpression();
if (initializer != null) {
element.constantInitializer = initializer;
ConstantContextForExpressionImpl(element, initializer);
}
}
applyConstantOffsets?.perform();
}
}
class FunctionElementLinkedData
extends ElementLinkedData<FunctionFragmentImpl> {
ApplyConstantOffsets? applyConstantOffsets;
FunctionElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required LibraryFragmentImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@override
void _clearLinkedDataOnRead(FunctionFragmentImpl element) {
element.linkedData = null;
}
@override
void _read(element, reader) {
element.metadata = reader._readAnnotationList(unitElement: unitElement);
_readTypeParameters(reader, element.typeParameters);
element.returnType = reader.readRequiredType();
_readFormalParameters(reader, element.parameters);
applyConstantOffsets?.perform();
}
}
/// Not an [ElementLinkedData], just a bundle with data.
class LibraryAugmentationElementLinkedData {
final int offset;
ApplyConstantOffsets? applyConstantOffsets;
LibraryAugmentationElementLinkedData({required this.offset});
}
class LibraryElementLinkedData extends ElementLinkedData<LibraryElementImpl> {
ApplyConstantOffsets? applyConstantOffsets;
/// When we are applying offsets to a library, we want to lock it.
bool _isLocked = false;
LibraryElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required LibraryFragmentImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
LinkedElementFactory get elementFactory {
return _libraryReader._elementFactory;
}
void lock() {
assert(!_isLocked);
_isLocked = true;
}
@override
void read(FragmentImpl element) {
if (!_isLocked) {
super.read(element);
}
}
void unlock() {
assert(_isLocked);
_isLocked = false;
}
@override
void _clearLinkedDataOnRead(LibraryElementImpl element) {
element.linkedData = null;
}
@override
void _read(element, reader) {
element.metadata = reader._readAnnotationList(unitElement: unitElement);
element.entryPoint2 = reader.readElement2() as TopLevelFunctionElementImpl?;
element.fieldNameNonPromotabilityInfo = _readFieldNameNonPromotabilityInfo(
reader,
);
element.exportNamespace = elementFactory.buildExportNamespace(
element.source.uri,
element.exportedReferences,
);
applyConstantOffsets?.perform();
}
Map<String, FieldNameNonPromotabilityInfo>?
_readFieldNameNonPromotabilityInfo(ResolutionReader reader) {
return reader.readOptionalObject(() {
return reader.readMap(
readKey: () => reader.readStringReference(),
readValue: () {
return FieldNameNonPromotabilityInfo(
conflictingFields: reader.readElementList2(),
conflictingGetters: reader.readElementList2(),
conflictingNsmClasses: reader.readElementList2(),
);
},
);
});
}
}
class LibraryReader {
final LinkedElementFactory _elementFactory;
final SummaryDataReader _reader;
final Uri uri;
final Map<Uri, Uint8List> _unitsInformativeBytes;
final int _baseResolutionOffset;
final _ReferenceReader _referenceReader;
final Reference _reference;
final int _offset;
final InfoDeclarationStore _deserializedDataStore;
final LibraryManifest? manifest;
final Uint32List _classMembersLengths;
int _classMembersLengthsIndex = 0;
late final LibraryElementImpl _libraryElement;
LibraryReader._({
required LinkedElementFactory elementFactory,
required SummaryDataReader reader,
required this.uri,
required Map<Uri, Uint8List> unitsInformativeBytes,
required int baseResolutionOffset,
required _ReferenceReader referenceReader,
required Reference reference,
required int offset,
required Uint32List classMembersLengths,
required InfoDeclarationStore infoDeclarationStore,
required this.manifest,
}) : _elementFactory = elementFactory,
_reader = reader,
_unitsInformativeBytes = unitsInformativeBytes,
_baseResolutionOffset = baseResolutionOffset,
_referenceReader = referenceReader,
_reference = reference,
_offset = offset,
_classMembersLengths = classMembersLengths,
_deserializedDataStore = infoDeclarationStore;
LibraryElementImpl readElement({required Source librarySource}) {
var analysisContext = _elementFactory.analysisContext;
var analysisSession = _elementFactory.analysisSession;
_reader.offset = _offset;
// TODO(scheglov): https://github.com/dart-lang/sdk/issues/51855
// This should not be needed.
// But I have a suspicion that we attempt to read the library twice.
_classMembersLengthsIndex = 0;
// Read enough data to create the library.
var name = _reader.readStringReference();
var featureSet = _readFeatureSet();
// Create the library, link to the reference.
_libraryElement = LibraryElementImpl(
analysisContext,
analysisSession,
name,
-1,
0,
featureSet,
);
_reference.element = _libraryElement;
_reference.element2 = _libraryElement;
_libraryElement.reference = _reference;
// Read the rest of non-resolution data for the library.
LibraryElementFlags.read(_reader, _libraryElement);
_libraryElement.languageVersion = _readLanguageVersion();
_libraryElement.exportedReferences = _reader.readTypedList(
_readExportedReference,
);
_libraryElement.nameUnion = ElementNameUnion.read(_reader.readUInt30List());
_libraryElement.manifest = manifest;
_libraryElement.loadLibraryProvider = LoadLibraryFunctionProvider(
fragmentReference: _readReference(),
elementReference: _readReference(),
);
// Read the library units.
_libraryElement.definingCompilationUnit = _readUnitElement(
containerUnit: null,
unitSource: librarySource,
);
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
_libraryElement.linkedData = LibraryElementLinkedData(
reference: _reference,
libraryReader: this,
unitElement: _libraryElement.definingCompilationUnit,
offset: resolutionOffset,
);
_declareDartCoreDynamicNever();
InformativeDataApplier(
_elementFactory,
_unitsInformativeBytes,
_deserializedDataStore,
).applyTo(_libraryElement);
return _libraryElement;
}
/// These elements are implicitly declared in `dart:core`.
void _declareDartCoreDynamicNever() {
if (_reference.name == 'dart:core') {
_reference.getChild('dynamic').element = DynamicFragmentImpl.instance;
_reference.getChild('Never').element = NeverFragmentImpl.instance;
}
}
ClassFragmentImpl _readClassElement(
LibraryFragmentImpl unitElement,
Reference unitReference,
) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var reference = _readReference();
var reference2 = _readReference();
var fragmentName = _readFragmentName();
var name = fragmentName ?? '';
var fragment = ClassFragmentImpl(name, -1);
fragment.name2 = fragmentName;
if (reference2.element2 case ClassElementImpl2 element?) {
fragment.augmentedInternal = element;
} else {
var element = ClassElementImpl2(reference2, fragment);
_libraryElement.classes.add(element);
}
var linkedData = ClassElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
);
fragment.setLinkedData(reference, linkedData);
ClassElementFlags.read(_reader, fragment);
fragment.typeParameters = _readTypeParameters();
if (!fragment.isMixinApplication) {
var membersOffset = _reader.offset;
linkedData._readMembers = () {
_reader.offset = membersOffset;
_readClassElementMembers(fragment, reference);
};
_reader.offset += _classMembersLengths[_classMembersLengthsIndex++];
}
return fragment;
}
void _readClassElementMembers(
ClassFragmentImpl fragment,
Reference reference,
) {
var unitElement = fragment.enclosingElement3;
var accessors = <PropertyAccessorFragmentImpl>[];
var fields = <FieldFragmentImpl>[];
_readFields(unitElement, fragment, reference, accessors, fields);
_readPropertyAccessors(
unitElement,
fragment,
reference,
accessors,
fields,
'@field',
);
fragment.fields = fields.toFixedList();
fragment.accessors = accessors.toFixedList();
fragment.constructors = _readConstructors(unitElement, fragment, reference);
fragment.methods = _readMethods(unitElement, fragment, reference);
}
void _readClasses(LibraryFragmentImpl unitElement, Reference unitReference) {
unitElement.classes = _reader.readTypedList(() {
return _readClassElement(unitElement, unitReference);
});
}
List<ConstructorFragmentImpl> _readConstructors(
LibraryFragmentImpl unitElement,
InterfaceFragmentImpl classElement,
Reference classReference,
) {
return _reader.readTypedList(() {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var reference = _readReference();
var name = reference.elementName.ifEqualThen('new', '');
var element = ConstructorFragmentImpl(name, -1);
element.typeName = _reader.readOptionalStringReference();
element.name2 = _reader.readStringReference();
var linkedData = ConstructorElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
);
element.setLinkedData(reference, linkedData);
ConstructorElementFlags.read(_reader, element);
element.parameters = _readParameters();
return element;
});
}
DirectiveUriImpl _readDirectiveUri({
required LibraryFragmentImpl containerUnit,
}) {
DirectiveUriWithRelativeUriStringImpl readWithRelativeUriString() {
var relativeUriString = _reader.readStringReference();
return DirectiveUriWithRelativeUriStringImpl(
relativeUriString: relativeUriString,
);
}
DirectiveUriWithRelativeUriImpl readWithRelativeUri() {
var parent = readWithRelativeUriString();
var relativeUri = uriCache.parse(_reader.readStringReference());
return DirectiveUriWithRelativeUriImpl(
relativeUriString: parent.relativeUriString,
relativeUri: relativeUri,
);
}
DirectiveUriWithSourceImpl readWithSource() {
var parent = readWithRelativeUri();
var analysisContext = _elementFactory.analysisContext;
var sourceFactory = analysisContext.sourceFactory;
var sourceUriStr = _reader.readStringReference();
var sourceUri = uriCache.parse(sourceUriStr);
var source = sourceFactory.forUri2(sourceUri);
// TODO(scheglov): https://github.com/dart-lang/sdk/issues/49431
var fixedSource = source ?? sourceFactory.forUri('dart:math')!;
return DirectiveUriWithSourceImpl(
relativeUriString: parent.relativeUriString,
relativeUri: parent.relativeUri,
source: fixedSource,
);
}
var kindIndex = _reader.readByte();
var kind = DirectiveUriKind.values[kindIndex];
switch (kind) {
case DirectiveUriKind.withLibrary:
var parent = readWithSource();
return DirectiveUriWithLibraryImpl.read(
relativeUriString: parent.relativeUriString,
relativeUri: parent.relativeUri,
source: parent.source,
);
case DirectiveUriKind.withUnit:
var parent = readWithSource();
var unitElement = _readUnitElement(
containerUnit: containerUnit,
unitSource: parent.source,
);
return DirectiveUriWithUnitImpl(
relativeUriString: parent.relativeUriString,
relativeUri: parent.relativeUri,
libraryFragment: unitElement,
);
case DirectiveUriKind.withSource:
return readWithSource();
case DirectiveUriKind.withRelativeUri:
return readWithRelativeUri();
case DirectiveUriKind.withRelativeUriString:
return readWithRelativeUriString();
case DirectiveUriKind.withNothing:
return DirectiveUriImpl();
}
}
EnumFragmentImpl _readEnumElement(
LibraryFragmentImpl unitElement,
Reference unitReference,
) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var reference = _readReference();
var reference2 = _readReference();
var fragmentName = _readFragmentName();
var name = fragmentName ?? '';
var fragment = EnumFragmentImpl(name, -1);
fragment.name2 = fragmentName;
if (reference2.element2 case EnumElementImpl2 element?) {
fragment.augmentedInternal = element;
} else {
var element = EnumElementImpl2(reference2, fragment);
_libraryElement.enums.add(element);
}
var linkedData = EnumElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
);
fragment.setLinkedData(reference, linkedData);
EnumElementFlags.read(_reader, fragment);
fragment.typeParameters = _readTypeParameters();
var accessors = <PropertyAccessorFragmentImpl>[];
var fields = <FieldFragmentImpl>[];
_readFields(unitElement, fragment, reference, accessors, fields);
_readPropertyAccessors(
unitElement,
fragment,
reference,
accessors,
fields,
'@field',
);
fragment.fields = fields.toFixedList();
fragment.accessors = accessors.toFixedList();
fragment.constructors = _readConstructors(unitElement, fragment, reference);
fragment.methods = _readMethods(unitElement, fragment, reference);
return fragment;
}
void _readEnums(LibraryFragmentImpl unitElement, Reference unitReference) {
unitElement.enums = _reader.readTypedList(() {
return _readEnumElement(unitElement, unitReference);
});
}
ExportedReference _readExportedReference() {
var kind = _reader.readByte();
if (kind == 0) {
var index = _reader.readUInt30();
var reference = _referenceReader.referenceOfIndex(index);
return ExportedReferenceDeclared(reference: reference);
} else if (kind == 1) {
var index = _reader.readUInt30();
var reference = _referenceReader.referenceOfIndex(index);
return ExportedReferenceExported(
reference: reference,
locations: _reader.readTypedList(_readExportLocation),
);
} else {
throw StateError('kind: $kind');
}
}
LibraryExportElementImpl _readExportElement({
required LibraryFragmentImpl containerUnit,
}) {
return LibraryExportElementImpl(
combinators: _reader.readTypedList(_readNamespaceCombinator),
exportKeywordOffset: -1,
uri: _readDirectiveUri(containerUnit: containerUnit),
);
}
ExportLocation _readExportLocation() {
return ExportLocation(
fragmentIndex: _reader.readUInt30(),
exportIndex: _reader.readUInt30(),
);
}
ExtensionFragmentImpl _readExtensionElement(
LibraryFragmentImpl unitElement,
Reference unitReference,
) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var reference = _readReference();
var reference2 = _readReference();
var fragmentName = _readFragmentName();
var name = fragmentName;
var fragment = ExtensionFragmentImpl(name, -1);
fragment.name2 = fragmentName;
if (reference2.element2 case ExtensionElementImpl2 element?) {
fragment.augmentedInternal = element;
} else {
var element = ExtensionElementImpl2(reference2, fragment);
_libraryElement.extensions.add(element);
}
fragment.setLinkedData(
reference,
ExtensionElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
),
);
ExtensionElementFlags.read(_reader, fragment);
fragment.typeParameters = _readTypeParameters();
var accessors = <PropertyAccessorFragmentImpl>[];
var fields = <FieldFragmentImpl>[];
_readPropertyAccessors(
unitElement,
fragment,
reference,
accessors,
fields,
'@field',
);
_readFields(unitElement, fragment, reference, accessors, fields);
fragment.accessors = accessors;
fragment.fields = fields;
fragment.methods = _readMethods(unitElement, fragment, reference);
return fragment;
}
void _readExtensions(
LibraryFragmentImpl unitElement,
Reference unitReference,
) {
unitElement.extensions = _reader.readTypedList(() {
return _readExtensionElement(unitElement, unitReference);
});
}
ExtensionTypeFragmentImpl _readExtensionTypeElement(
LibraryFragmentImpl unitElement,
Reference unitReference,
) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var reference = _readReference();
var reference2 = _readReference();
var fragmentName = _readFragmentName();
var name = fragmentName ?? '';
var fragment = ExtensionTypeFragmentImpl(name, -1);
fragment.name2 = fragmentName;
if (reference2.element2 case ExtensionTypeElementImpl2 element?) {
fragment.augmentedInternal = element;
} else {
var element = ExtensionTypeElementImpl2(reference2, fragment);
_libraryElement.extensionTypes.add(element);
}
fragment.setLinkedData(
reference,
ExtensionTypeElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
),
);
ExtensionTypeElementFlags.read(_reader, fragment);
fragment.typeParameters = _readTypeParameters();
var fields = <FieldFragmentImpl>[];
var accessors = <PropertyAccessorFragmentImpl>[];
_readFields(unitElement, fragment, reference, accessors, fields);
_readPropertyAccessors(
unitElement,
fragment,
reference,
accessors,
fields,
'@field',
);
fragment.fields = fields;
fragment.accessors = accessors;
fragment.constructors = _readConstructors(unitElement, fragment, reference);
fragment.methods = _readMethods(unitElement, fragment, reference);
return fragment;
}
void _readExtensionTypes(
LibraryFragmentImpl unitElement,
Reference unitReference,
) {
unitElement.extensionTypes = _reader.readTypedList(() {
return _readExtensionTypeElement(unitElement, unitReference);
});
}
FeatureSet _readFeatureSet() {
var featureSetEncoded = _reader.readUint8List();
return ExperimentStatus.fromStorage(featureSetEncoded);
}
FieldFragmentImpl _readFieldElement(
LibraryFragmentImpl unitElement,
FragmentImpl classElement,
Reference classReference,
) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var reference = _readReference();
var getterReference = _readOptionalReference();
var setterReference = _readOptionalReference();
var fragmentName = _readFragmentName();
// TODO(scheglov): we do this only because FieldElement2 uses this name.
var name = _reader.readStringReference();
var isConstElement = _reader.readBool();
FieldFragmentImpl element;
if (isConstElement) {
element = ConstFieldFragmentImpl(name, -1);
} else {
element = FieldFragmentImpl(name, -1);
}
element.name2 = fragmentName;
var linkedData = FieldElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
);
element.setLinkedData(reference, linkedData);
FieldElementFlags.read(_reader, element);
element.typeInferenceError = _readTopLevelInferenceError();
if (!element.isAugmentation) {
if (getterReference != null) {
var getter = element.createImplicitGetter(getterReference);
getter.hasEnclosingTypeParameterReference =
element.hasEnclosingTypeParameterReference;
}
if (element.hasSetter && setterReference != null) {
var setter = element.createImplicitSetter(setterReference);
setter.hasEnclosingTypeParameterReference =
element.hasEnclosingTypeParameterReference;
}
}
return element;
}
void _readFields(
LibraryFragmentImpl unitElement,
FragmentImpl classElement,
Reference classReference,
List<PropertyAccessorFragmentImpl> accessors,
List<FieldFragmentImpl> variables,
) {
var createdElements = <FieldFragmentImpl>[];
var variableElementCount = _reader.readUInt30();
for (var i = 0; i < variableElementCount; i++) {
var variable = _readFieldElement(
unitElement,
classElement,
classReference,
);
createdElements.add(variable);
variables.add(variable);
var getter = variable.getter;
if (getter is GetterFragmentImpl) {
accessors.add(getter);
}
var setter = variable.setter;
if (setter is SetterFragmentImpl) {
accessors.add(setter);
}
}
}
String? _readFragmentName() {
return _reader.readOptionalStringReference();
}
void _readFunctions(
LibraryFragmentImpl unitElement,
Reference unitReference,
) {
unitElement.functions = _reader.readTypedList(() {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var reference = _readReference();
var reference2 = _readReference();
var fragmentName = _readFragmentName();
var name = reference.elementName;
var fragment = TopLevelFunctionFragmentImpl(name, -1);
fragment.name2 = fragmentName;
if (reference2.element2 case TopLevelFunctionElementImpl element?) {
fragment.element = element;
} else {
var element = TopLevelFunctionElementImpl(reference2, fragment);
_libraryElement.topLevelFunctions.add(element);
}
var linkedData = FunctionElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
);
fragment.setLinkedData(reference, linkedData);
FunctionElementFlags.read(_reader, fragment);
fragment.typeParameters = _readTypeParameters();
fragment.parameters = _readParameters();
return fragment;
});
}
LibraryImportElementImpl _readImportElement({
required LibraryFragmentImpl containerUnit,
}) {
var element = LibraryImportElementImpl(
combinators: _reader.readTypedList(_readNamespaceCombinator),
importKeywordOffset: -1,
prefix2: _readLibraryImportPrefixFragment(libraryFragment: containerUnit),
uri: _readDirectiveUri(containerUnit: containerUnit),
);
LibraryImportElementFlags.read(_reader, element);
return element;
}
LibraryLanguageVersion _readLanguageVersion() {
var packageMajor = _reader.readUInt30();
var packageMinor = _reader.readUInt30();
var package = Version(packageMajor, packageMinor, 0);
Version? override;
if (_reader.readBool()) {
var overrideMajor = _reader.readUInt30();
var overrideMinor = _reader.readUInt30();
override = Version(overrideMajor, overrideMinor, 0);
}
return LibraryLanguageVersion(package: package, override: override);
}
PrefixFragmentImpl? _readLibraryImportPrefixFragment({
required LibraryFragmentImpl libraryFragment,
}) {
return _reader.readOptionalObject(() {
var fragmentName = _readFragmentName();
var reference = _readReference();
var isDeferred = _reader.readBool();
var fragment = PrefixFragmentImpl(
enclosingFragment: libraryFragment,
name2: fragmentName,
nameOffset2: null,
isDeferred: isDeferred,
);
var element = reference.element2 as PrefixElementImpl2?;
if (element == null) {
element = PrefixElementImpl2(
reference: reference,
firstFragment: fragment,
);
} else {
element.addFragment(fragment);
}
fragment.element = element;
return fragment;
});
}
List<MethodFragmentImpl> _readMethods(
LibraryFragmentImpl unitElement,
FragmentImpl enclosingElement,
Reference enclosingReference,
) {
return _reader.readTypedList(() {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var reference = _readReference();
var fragmentName = _readFragmentName();
// TODO(scheglov): we do this only because MethodElement2 uses this name.
var name = _reader.readStringReference();
var fragment = MethodFragmentImpl(name, -1);
fragment.name2 = fragmentName;
var linkedData = MethodElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
);
fragment.setLinkedData(reference, linkedData);
MethodElementFlags.read(_reader, fragment);
fragment.typeParameters = _readTypeParameters();
fragment.parameters = _readParameters();
fragment.typeInferenceError = _readTopLevelInferenceError();
return fragment;
});
}
MixinFragmentImpl _readMixinElement(
LibraryFragmentImpl unitElement,
Reference unitReference,
) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var reference = _readReference();
var reference2 = _readReference();
var fragmentName = _readFragmentName();
var name = fragmentName ?? '';
var fragment = MixinFragmentImpl(name, -1);
fragment.name2 = fragmentName;
if (reference2.element2 case MixinElementImpl2 element?) {
fragment.augmentedInternal = element;
} else {
var element = MixinElementImpl2(reference2, fragment);
_libraryElement.mixins.add(element);
}
var linkedData = MixinElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
);
fragment.setLinkedData(reference, linkedData);
MixinElementFlags.read(_reader, fragment);
fragment.typeParameters = _readTypeParameters();
var fields = <FieldFragmentImpl>[];
var accessors = <PropertyAccessorFragmentImpl>[];
_readFields(unitElement, fragment, reference, accessors, fields);
_readPropertyAccessors(
unitElement,
fragment,
reference,
accessors,
fields,
'@field',
);
fragment.fields = fields.toFixedList();
fragment.accessors = accessors.toFixedList();
fragment.constructors = _readConstructors(unitElement, fragment, reference);
fragment.methods = _readMethods(unitElement, fragment, reference);
fragment.superInvokedNames = _reader.readStringReferenceList();
return fragment;
}
void _readMixins(LibraryFragmentImpl unitElement, Reference unitReference) {
unitElement.mixins = _reader.readTypedList(() {
return _readMixinElement(unitElement, unitReference);
});
}
NamespaceCombinator _readNamespaceCombinator() {
var tag = _reader.readByte();
if (tag == Tag.HideCombinator) {
var combinator = HideElementCombinatorImpl();
combinator.hiddenNames = _reader.readStringReferenceList();
return combinator;
} else if (tag == Tag.ShowCombinator) {
var combinator = ShowElementCombinatorImpl();
combinator.shownNames = _reader.readStringReferenceList();
return combinator;
} else {
throw UnimplementedError('tag: $tag');
}
}
/// Read the reference of a non-local element.
Reference? _readOptionalReference() {
return _reader.readOptionalObject(() => _readReference());
}
// TODO(scheglov): Deduplicate parameter reading implementation.
List<FormalParameterFragmentImpl> _readParameters() {
return _reader.readTypedList(() {
var fragmentName = _readFragmentName();
var name = _reader.readStringReference();
var isDefault = _reader.readBool();
var isInitializingFormal = _reader.readBool();
var isSuperFormal = _reader.readBool();
var reference = _readOptionalReference();
var kindIndex = _reader.readByte();
var kind = ResolutionReader._formalParameterKind(kindIndex);
FormalParameterFragmentImpl element;
if (!isDefault) {
if (isInitializingFormal) {
element = FieldFormalParameterFragmentImpl(
name: name,
nameOffset: -1,
name2: name.nullIfEmpty,
nameOffset2: null,
parameterKind: kind,
);
} else if (isSuperFormal) {
element = SuperFormalParameterFragmentImpl(
name: name,
nameOffset: -1,
name2: name.nullIfEmpty,
nameOffset2: null,
parameterKind: kind,
);
} else {
element = FormalParameterFragmentImpl(
name: name,
nameOffset: -1,
name2: name.nullIfEmpty,
nameOffset2: null,
parameterKind: kind,
);
}
} else {
if (isInitializingFormal) {
element = DefaultFieldFormalParameterElementImpl(
name: name,
nameOffset: -1,
name2: name.nullIfEmpty,
nameOffset2: null,
parameterKind: kind,
);
} else if (isSuperFormal) {
element = DefaultSuperFormalParameterElementImpl(
name: name,
nameOffset: -1,
name2: name.nullIfEmpty,
nameOffset2: null,
parameterKind: kind,
);
} else {
element = DefaultParameterFragmentImpl(
name: name,
nameOffset: -1,
name2: name.nullIfEmpty,
nameOffset2: null,
parameterKind: kind,
);
}
if (reference != null) {
element.reference = reference;
reference.element = element;
}
}
element.name2 = fragmentName;
ParameterElementFlags.read(_reader, element);
element.typeParameters = _readTypeParameters();
element.parameters = _readParameters();
return element;
});
}
PartElementImpl _readPartElement({
required LibraryFragmentImpl containerUnit,
}) {
var uri = _readDirectiveUri(containerUnit: containerUnit);
return PartElementImpl(uri: uri);
}
PropertyAccessorFragmentImpl _readPropertyAccessorElement(
LibraryFragmentImpl unitElement,
FragmentImpl classElement,
Reference classReference,
) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var reference = _readReference();
var fragmentName = _readFragmentName();
var name = reference.elementName;
var flags = _reader.readUInt30();
var fragment =
PropertyAccessorElementFlags.isGetter(flags)
? GetterFragmentImpl(name, -1)
: SetterFragmentImpl(name, -1);
fragment.name2 = fragmentName;
var linkedData = PropertyAccessorElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
);
fragment.setLinkedData(reference, linkedData);
PropertyAccessorElementFlags.setFlagsBasedOnFlagByte(fragment, flags);
fragment.parameters = _readParameters();
return fragment;
}
void _readPropertyAccessors(
LibraryFragmentImpl unitElement,
FragmentImpl enclosingElement,
Reference enclosingReference,
List<PropertyAccessorFragmentImpl> accessorFragments,
List<PropertyInducingElementImpl> propertyFragments,
String containerRefName, {
List<TopLevelVariableElementImpl2>? variables2,
}) {
var accessorCount = _reader.readUInt30();
for (var i = 0; i < accessorCount; i++) {
var accessor = _readPropertyAccessorElement(
unitElement,
enclosingElement,
enclosingReference,
);
accessorFragments.add(accessor);
if (accessor.isAugmentation) {
continue;
}
// Read the property references.
var propertyFragmentReference = _readReference();
// TODO(scheglov): should be required?
var propertyElementReference = _readOptionalReference();
var name = accessor.displayName;
bool canUseExisting(PropertyInducingElementImpl property) {
return property.isSynthetic ||
accessor.isSetter && property.setter == null;
}
PropertyInducingElementImpl propertyFragment;
var existing = propertyFragmentReference.element;
if (enclosingElement is LibraryFragmentImpl) {
if (existing is TopLevelVariableFragmentImpl &&
canUseExisting(existing)) {
propertyFragment = existing;
} else {
var variableFragment =
TopLevelVariableFragmentImpl(name, -1)
..enclosingElement3 = enclosingElement
..reference = propertyFragmentReference
..isSynthetic = true
..name2 = accessor.name2;
propertyFragment = variableFragment;
propertyFragmentReference.element ??= propertyFragment;
propertyFragments.add(variableFragment);
// TODO(scheglov): should be required?
propertyElementReference!;
var variableElement = TopLevelVariableElementImpl2(
propertyElementReference,
variableFragment,
);
variables2!.add(variableElement);
}
} else {
var isPromotable = _reader.readBool();
if (existing is FieldFragmentImpl && canUseExisting(existing)) {
propertyFragment = existing;
} else {
propertyFragment =
FieldFragmentImpl(name, -1)
..enclosingElement3 = enclosingElement
..reference = propertyFragmentReference
..name2 = accessor.name2
..isStatic = accessor.isStatic
..isSynthetic = true
..isPromotable = isPromotable
..hasEnclosingTypeParameterReference =
accessor.hasEnclosingTypeParameterReference;
propertyFragmentReference.element ??= propertyFragment;
propertyFragments.add(propertyFragment);
}
}
accessor.variable2 = propertyFragment;
switch (accessor) {
case GetterFragmentImpl():
propertyFragment.getter = accessor;
case SetterFragmentImpl():
propertyFragment.setter = accessor;
if (propertyFragment.isSynthetic) {
propertyFragment.isFinal = false;
}
}
}
}
/// Read the reference of a non-local element.
Reference _readReference() {
var referenceIndex = _reader.readUInt30();
return _referenceReader.referenceOfIndex(referenceIndex);
}
TopLevelInferenceError? _readTopLevelInferenceError() {
var kindIndex = _reader.readByte();
var kind = TopLevelInferenceErrorKind.values[kindIndex];
if (kind == TopLevelInferenceErrorKind.none) {
return null;
}
return TopLevelInferenceError(
kind: kind,
arguments: _reader.readStringReferenceList(),
);
}
TopLevelVariableFragmentImpl _readTopLevelVariableElement(
LibraryFragmentImpl unitElement,
Reference unitReference,
) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var reference = _readReference();
var reference2 = _readReference();
var getterReference = _readOptionalReference();
var setterReference = _readOptionalReference();
var fragmentName = _readFragmentName();
// TODO(scheglov): we do this only because FieldElement2 uses this name.
var name = _reader.readStringReference();
var isConst = _reader.readBool();
TopLevelVariableFragmentImpl fragment;
if (isConst) {
fragment = ConstTopLevelVariableFragmentImpl(name, -1);
} else {
fragment = TopLevelVariableFragmentImpl(name, -1);
}
fragment.name2 = fragmentName;
if (reference2.element2 case TopLevelVariableElementImpl2 element) {
fragment.element = element;
} else {
var element = TopLevelVariableElementImpl2(reference2, fragment);
_libraryElement.topLevelVariables.add(element);
}
var linkedData = TopLevelVariableElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
);
fragment.setLinkedData(reference, linkedData);
fragment.isConst = isConst;
TopLevelVariableElementFlags.read(_reader, fragment);
fragment.typeInferenceError = _readTopLevelInferenceError();
if (getterReference != null) {
var getter = fragment.createImplicitGetter(getterReference);
getter.hasEnclosingTypeParameterReference = false;
}
if (fragment.hasSetter && setterReference != null) {
var getter = fragment.createImplicitSetter(setterReference);
getter.hasEnclosingTypeParameterReference = false;
}
return fragment;
}
void _readTopLevelVariables(
LibraryFragmentImpl unitElement,
Reference unitReference,
List<PropertyAccessorFragmentImpl> accessors,
List<TopLevelVariableFragmentImpl> variables,
) {
var variableElementCount = _reader.readUInt30();
for (var i = 0; i < variableElementCount; i++) {
var variable = _readTopLevelVariableElement(unitElement, unitReference);
variables.add(variable);
var getter = variable.getter;
if (getter is GetterFragmentImpl) {
accessors.add(getter);
}
var setter = variable.setter;
if (setter is SetterFragmentImpl) {
accessors.add(setter);
}
}
}
TypeAliasFragmentImpl _readTypeAliasElement(
LibraryFragmentImpl unitElement,
Reference unitReference,
) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var reference = _readReference();
var reference2 = _readReference();
var fragmentName = _readFragmentName();
var name = _reader.readStringReference();
var isFunctionTypeAliasBased = _reader.readBool();
TypeAliasFragmentImpl fragment;
if (isFunctionTypeAliasBased) {
fragment = TypeAliasFragmentImpl(name, -1);
fragment.isFunctionTypeAliasBased = true;
} else {
fragment = TypeAliasFragmentImpl(name, -1);
}
fragment.name2 = fragmentName;
if (reference2.element2 case TypeAliasElementImpl2 element) {
fragment.element = element;
} else {
var element = TypeAliasElementImpl2(reference2, fragment);
_libraryElement.typeAliases.add(element);
}
var linkedData = TypeAliasElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
);
fragment.setLinkedData(reference, linkedData);
fragment.isFunctionTypeAliasBased = isFunctionTypeAliasBased;
TypeAliasElementFlags.read(_reader, fragment);
fragment.typeParameters = _readTypeParameters();
return fragment;
}
void _readTypeAliases(
LibraryFragmentImpl unitElement,
Reference unitReference,
) {
unitElement.typeAliases = _reader.readTypedList(() {
return _readTypeAliasElement(unitElement, unitReference);
});
}
List<TypeParameterFragmentImpl> _readTypeParameters() {
return _reader.readTypedList(() {
var name = _reader.readStringReference();
var fragmentName = _readFragmentName();
var varianceEncoding = _reader.readByte();
var variance = _decodeVariance(varianceEncoding);
var element = TypeParameterFragmentImpl(name, -1);
element.name2 = fragmentName;
element.variance = variance;
return element;
});
}
LibraryFragmentImpl _readUnitElement({
required LibraryFragmentImpl? containerUnit,
required Source unitSource,
}) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var unitElement = LibraryFragmentImpl(
library: _libraryElement,
source: unitSource,
lineInfo: LineInfo([0]),
);
var unitReference = _reference
.getChild('@fragment')
.getChild('${unitSource.uri}');
unitElement.setLinkedData(
unitReference,
CompilationUnitElementLinkedData(
reference: unitReference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
),
);
unitElement.isSynthetic = _reader.readBool();
unitElement.libraryImports = _reader.readTypedList(() {
return _readImportElement(containerUnit: unitElement);
});
unitElement.libraryExports = _reader.readTypedList(() {
return _readExportElement(containerUnit: unitElement);
});
_readClasses(unitElement, unitReference);
_readEnums(unitElement, unitReference);
_readExtensions(unitElement, unitReference);
_readExtensionTypes(unitElement, unitReference);
_readFunctions(unitElement, unitReference);
_readMixins(unitElement, unitReference);
_readTypeAliases(unitElement, unitReference);
var accessorFragments = <PropertyAccessorFragmentImpl>[];
var variableFragments = <TopLevelVariableFragmentImpl>[];
_readTopLevelVariables(
unitElement,
unitReference,
accessorFragments,
variableFragments,
);
_readPropertyAccessors(
unitElement,
unitElement,
unitReference,
accessorFragments,
variableFragments,
'@topLevelVariable',
variables2: _libraryElement.topLevelVariables,
);
unitElement.accessors = accessorFragments.toFixedList();
unitElement.topLevelVariables = variableFragments.toFixedList();
unitElement.parts = _reader.readTypedList(() {
return _readPartElement(containerUnit: unitElement);
});
return unitElement;
}
static Variance? _decodeVariance(int index) {
var tag = TypeParameterVarianceTag.values[index];
switch (tag) {
case TypeParameterVarianceTag.legacy:
return null;
case TypeParameterVarianceTag.unrelated:
return Variance.unrelated;
case TypeParameterVarianceTag.covariant:
return Variance.covariant;
case TypeParameterVarianceTag.contravariant:
return Variance.contravariant;
case TypeParameterVarianceTag.invariant:
return Variance.invariant;
}
}
}
class MethodElementLinkedData extends ElementLinkedData<MethodFragmentImpl> {
ApplyConstantOffsets? applyConstantOffsets;
MethodElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required LibraryFragmentImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@override
void _clearLinkedDataOnRead(MethodFragmentImpl element) {
element.linkedData = null;
}
@override
void _read(element, reader) {
_addEnclosingElementTypeParameters(reader, element);
element.metadata = reader._readAnnotationList(unitElement: unitElement);
_readTypeParameters(reader, element.typeParameters);
_readFormalParameters(reader, element.parameters);
element.returnType = reader.readRequiredType();
applyConstantOffsets?.perform();
}
}
class MixinElementLinkedData extends ElementLinkedData<MixinFragmentImpl> {
ApplyConstantOffsets? applyConstantOffsets;
MixinElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required LibraryFragmentImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@override
void _clearLinkedDataOnRead(MixinFragmentImpl element) {
element.linkedData = null;
}
@override
void _read(element, reader) {
element.metadata = reader._readAnnotationList(
unitElement: element.enclosingElement3,
);
_readTypeParameters(reader, element.typeParameters);
element.superclassConstraints = reader._readInterfaceTypeList();
element.interfaces = reader._readInterfaceTypeList();
var augmented = element.augmentedInternal;
augmented.superclassConstraints = reader._readInterfaceTypeList();
applyConstantOffsets?.perform();
}
}
class PropertyAccessorElementLinkedData
extends ElementLinkedData<PropertyAccessorFragmentImpl> {
ApplyConstantOffsets? applyConstantOffsets;
PropertyAccessorElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required LibraryFragmentImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@override
void _clearLinkedDataOnRead(PropertyAccessorFragmentImpl element) {
element.linkedData = null;
}
@override
void _read(element, reader) {
_addEnclosingElementTypeParameters(reader, element);
element.metadata = reader._readAnnotationList(unitElement: unitElement);
element.returnType = reader.readRequiredType();
_readFormalParameters(reader, element.parameters);
applyConstantOffsets?.perform();
}
}
/// Helper for reading elements and types from their binary encoding.
class ResolutionReader {
final LinkedElementFactory _elementFactory;
final _ReferenceReader _referenceReader;
final SummaryDataReader _reader;
/// The stack of [TypeParameterFragmentImpl]s and [FormalParameterFragmentImpl] that are
/// available in the scope of [readElement] and [readType].
///
/// This stack is shared with the client of the reader, and update mostly
/// by the client. However it is also updated during [_readFunctionType].
final List<FragmentImpl> _localElements = [];
ResolutionReader(this._elementFactory, this._referenceReader, this._reader);
LibraryElementImpl libraryOfUri(Uri uri) {
return _elementFactory.libraryOfUri2(uri);
}
bool readBool() {
return _reader.readBool();
}
int readByte() {
return _reader.readByte();
}
double readDouble() {
return _reader.readDouble();
}
ElementOrMember? readElement() {
var memberFlags = _reader.readByte();
var element = _readRawElement();
if (element == null) {
return null;
}
if (memberFlags == Tag.RawElement) {
return element;
}
if (memberFlags == Tag.MemberWithTypeArguments) {
var enclosing = element.enclosingElement3 as InstanceFragmentImpl;
var firstFragment = enclosing.element.firstFragment;
var declarationTypeParameters =
firstFragment.typeParameters.map((tp) => tp.asElement2).toList();
var substitution = Substitution.empty;
var typeArguments = _readTypeList();
if (typeArguments.isNotEmpty) {
substitution = Substitution.fromPairs2(
declarationTypeParameters,
typeArguments,
);
}
if (element is ExecutableFragmentImpl) {
return ExecutableMember.from2(element, substitution);
} else {
element as FieldFragmentImpl;
return FieldMember.from2(element, substitution);
}
}
throw UnimplementedError('memberFlags: $memberFlags');
}
Element? readElement2() {
var element = readElement();
switch (element) {
case null:
return null;
case PrefixElementImpl():
return element.element2;
case FragmentImpl():
return element.asElement2;
case ExecutableMember():
return element;
default:
throw UnimplementedError('${element.runtimeType}');
}
}
List<T> readElementList2<T extends Element>() {
return _reader.readTypedListCast<T>(readElement2);
}
T readEnum<T extends Enum>(List<T> values) {
return _reader.readEnum(values);
}
Map<K, V> readMap<K, V>({
required K Function() readKey,
required V Function() readValue,
}) {
return _reader.readMap(readKey: readKey, readValue: readValue);
}
FunctionTypeImpl? readOptionalFunctionType() {
var type = readType();
return type is FunctionTypeImpl ? type : null;
}
T? readOptionalObject<T>(T Function() read) {
return _reader.readOptionalObject(read);
}
List<TypeImpl>? readOptionalTypeList() {
if (_reader.readBool()) {
return _readTypeList();
} else {
return null;
}
}
TypeImpl readRequiredType() {
return readType()!;
}
SourceRange readSourceRange() {
var offset = readUInt30();
var length = readUInt30();
return SourceRange(offset, length);
}
String readStringReference() {
return _reader.readStringReference();
}
List<String> readStringReferenceList() {
return _reader.readStringReferenceList();
}
TypeImpl? readType() {
var tag = _reader.readByte();
if (tag == Tag.NullType) {
return null;
} else if (tag == Tag.DynamicType) {
var type = DynamicTypeImpl.instance;
return _readAliasElementArguments(type);
} else if (tag == Tag.FunctionType) {
var type = _readFunctionType();
return _readAliasElementArguments(type);
} else if (tag == Tag.InterfaceType) {
var element = readElement() as InterfaceFragmentImpl;
var typeArguments = _readTypeList();
var nullability = _readNullability();
var type = InterfaceTypeImpl(
element: element.asElement2,
typeArguments: typeArguments,
nullabilitySuffix: nullability,
);
return _readAliasElementArguments(type);
} else if (tag == Tag.InterfaceType_noTypeArguments_none) {
var element = readElement() as InterfaceFragmentImpl;
var type = element.instantiateImpl(
typeArguments: const [],
nullabilitySuffix: NullabilitySuffix.none,
);
return _readAliasElementArguments(type);
} else if (tag == Tag.InterfaceType_noTypeArguments_question) {
var element = readElement() as InterfaceFragmentImpl;
var type = element.instantiateImpl(
typeArguments: const [],
nullabilitySuffix: NullabilitySuffix.question,
);
return _readAliasElementArguments(type);
} else if (tag == Tag.InvalidType) {
var type = InvalidTypeImpl.instance;
return _readAliasElementArguments(type);
} else if (tag == Tag.NeverType) {
var nullability = _readNullability();
var type = NeverTypeImpl.instance.withNullability(nullability);
return _readAliasElementArguments(type);
} else if (tag == Tag.RecordType) {
var type = _readRecordType();
return _readAliasElementArguments(type);
} else if (tag == Tag.TypeParameterType) {
var element = readElement() as TypeParameterFragmentImpl;
var nullability = _readNullability();
var type = TypeParameterTypeImpl(
element3: element.asElement2,
nullabilitySuffix: nullability,
);
return _readAliasElementArguments(type);
} else if (tag == Tag.VoidType) {
var type = VoidTypeImpl.instance;
return _readAliasElementArguments(type);
} else {
throw UnimplementedError('$tag');
}
}
List<T> readTypedList<T>(T Function() read) {
return _reader.readTypedList(read);
}
int readUInt30() {
return _reader.readUInt30();
}
int readUInt32() {
return _reader.readUInt32();
}
void setOffset(int offset) {
_reader.offset = offset;
}
void _addFormalParameters(List<FormalParameterFragmentImpl> parameters) {
for (var parameter in parameters) {
_localElements.add(parameter);
}
}
void _addTypeParameters(List<TypeParameterFragmentImpl> typeParameters) {
for (var typeParameter in typeParameters) {
_localElements.add(typeParameter);
}
}
FragmentImpl? _readAliasedElement(LibraryFragmentImpl unitElement) {
var tag = _reader.readByte();
if (tag == AliasedElementTag.nothing) {
return null;
} else if (tag == AliasedElementTag.genericFunctionElement) {
var typeParameters = _readTypeParameters(unitElement);
var formalParameters = _readFormalParameters(unitElement);
var returnType = readRequiredType();
_localElements.length -= typeParameters.length;
return GenericFunctionTypeFragmentImpl.forOffset(-1)
..typeParameters = typeParameters
..parameters = formalParameters
..returnType = returnType;
} else {
throw UnimplementedError('tag: $tag');
}
}
TypeImpl _readAliasElementArguments(TypeImpl type) {
var aliasElement = _readRawElement();
if (aliasElement is TypeAliasFragmentImpl) {
var aliasArguments = _readTypeList();
if (type is DynamicTypeImpl) {
// TODO(scheglov): add support for `dynamic` aliasing
return type;
} else if (type is FunctionTypeImpl) {
return FunctionTypeImpl(
typeFormals: type.typeFormals,
parameters: type.parameters,
returnType: type.returnType,
nullabilitySuffix: type.nullabilitySuffix,
alias: InstantiatedTypeAliasElementImpl(
element2: aliasElement.asElement2,
typeArguments: aliasArguments,
),
);
} else if (type is InterfaceTypeImpl) {
return InterfaceTypeImpl(
element: type.element3,
typeArguments: type.typeArguments,
nullabilitySuffix: type.nullabilitySuffix,
alias: InstantiatedTypeAliasElementImpl(
element2: aliasElement.asElement2,
typeArguments: aliasArguments,
),
);
} else if (type is RecordTypeImpl) {
return RecordTypeImpl(
positionalFields: type.positionalFields,
namedFields: type.namedFields,
nullabilitySuffix: type.nullabilitySuffix,
alias: InstantiatedTypeAliasElementImpl(
element2: aliasElement.asElement2,
typeArguments: aliasArguments,
),
);
} else if (type is TypeParameterTypeImpl) {
return TypeParameterTypeImpl(
element3: type.element3,
nullabilitySuffix: type.nullabilitySuffix,
alias: InstantiatedTypeAliasElementImpl(
element2: aliasElement.asElement2,
typeArguments: aliasArguments,
),
);
} else if (type is VoidTypeImpl) {
// TODO(scheglov): add support for `void` aliasing
return type;
} else {
throw UnimplementedError('${type.runtimeType}');
}
}
return type;
}
List<ElementAnnotationImpl> _readAnnotationList({
required LibraryFragmentImpl unitElement,
}) {
return readTypedList(() {
var ast = _readRequiredNode() as AnnotationImpl;
return ElementAnnotationImpl(unitElement)
..annotationAst = ast
..element2 = ast.element2;
});
}
List<FormalParameterFragmentImpl> _readFormalParameters(
LibraryFragmentImpl? unitElement,
) {
return readTypedList(() {
var kindIndex = _reader.readByte();
var kind = _formalParameterKind(kindIndex);
var isDefault = _reader.readBool();
var hasImplicitType = _reader.readBool();
var isInitializingFormal = _reader.readBool();
var typeParameters = _readTypeParameters(unitElement);
var type = readRequiredType();
var name = readStringReference();
if (!isDefault) {
FormalParameterFragmentImpl element;
if (isInitializingFormal) {
element = FieldFormalParameterFragmentImpl(
name: name,
nameOffset: -1,
name2: name.nullIfEmpty,
nameOffset2: null,
parameterKind: kind,
)..type = type;
} else {
element = FormalParameterFragmentImpl(
name: name,
nameOffset: -1,
name2: name.nullIfEmpty,
nameOffset2: null,
parameterKind: kind,
)..type = type;
}
element.hasImplicitType = hasImplicitType;
element.typeParameters = typeParameters;
element.parameters = _readFormalParameters(unitElement);
// TODO(scheglov): reuse for formal parameters
_localElements.length -= typeParameters.length;
if (unitElement != null) {
element.metadata = _readAnnotationList(unitElement: unitElement);
}
return element;
} else {
var element = DefaultParameterFragmentImpl(
name: name,
nameOffset: -1,
name2: name.nullIfEmpty,
nameOffset2: null,
parameterKind: kind,
)..type = type;
element.hasImplicitType = hasImplicitType;
element.typeParameters = typeParameters;
element.parameters = _readFormalParameters(unitElement);
// TODO(scheglov): reuse for formal parameters
_localElements.length -= typeParameters.length;
if (unitElement != null) {
element.metadata = _readAnnotationList(unitElement: unitElement);
}
return element;
}
});
}
// TODO(scheglov): Optimize for write/read of types without type parameters.
FunctionTypeImpl _readFunctionType() {
// TODO(scheglov): reuse for formal parameters
var typeParameters = _readTypeParameters(null);
var returnType = readRequiredType();
var formalParameters = _readFormalParameters(null);
var nullability = _readNullability();
_localElements.length -= typeParameters.length;
return FunctionTypeImpl(
typeFormals: typeParameters,
parameters: formalParameters,
returnType: returnType,
nullabilitySuffix: nullability,
);
}
InterfaceTypeImpl _readInterfaceType() {
return readType() as InterfaceTypeImpl;
}
List<InterfaceTypeImpl> _readInterfaceTypeList() {
return readTypedList(_readInterfaceType);
}
List<T> _readNodeList<T>() {
return readTypedList(() {
return _readRequiredNode() as T;
});
}
NullabilitySuffix _readNullability() {
var index = _reader.readByte();
return NullabilitySuffix.values[index];
}
ExpressionImpl? _readOptionalExpression() {
if (_reader.readBool()) {
return _readRequiredNode() as ExpressionImpl;
} else {
return null;
}
}
InterfaceType? _readOptionalInterfaceType() {
return readType() as InterfaceType?;
}
FragmentImpl? _readRawElement() {
var index = _reader.readUInt30();
if ((index & 0x1) == 0x1) {
return _localElements[index >> 1];
}
var referenceIndex = index >> 1;
var reference = _referenceReader.referenceOfIndex(referenceIndex);
return _elementFactory.elementOfReference(reference);
}
RecordTypeImpl _readRecordType() {
var positionalFields = readTypedList(() {
return RecordTypePositionalFieldImpl(type: readRequiredType());
});
var namedFields = readTypedList(() {
return RecordTypeNamedFieldImpl(
name: _reader.readStringReference(),
type: readRequiredType(),
);
});
var nullabilitySuffix = _readNullability();
return RecordTypeImpl(
positionalFields: positionalFields,
namedFields: namedFields,
nullabilitySuffix: nullabilitySuffix,
);
}
AstNode _readRequiredNode() {
var astReader = AstBinaryReader(reader: this);
return astReader.readNode();
}
List<TypeImpl> _readTypeList() {
return readTypedList(() {
return readRequiredType();
});
}
List<TypeParameterFragmentImpl> _readTypeParameters(
LibraryFragmentImpl? unitElement,
) {
var typeParameters = readTypedList(() {
var name = readStringReference();
var typeParameter = TypeParameterFragmentImpl(name, -1);
_localElements.add(typeParameter);
return typeParameter;
});
for (var typeParameter in typeParameters) {
typeParameter.bound = readType();
if (unitElement != null) {
typeParameter.metadata = _readAnnotationList(unitElement: unitElement);
}
}
return typeParameters;
}
static ParameterKind _formalParameterKind(int encoding) {
if (encoding == Tag.ParameterKindRequiredPositional) {
return ParameterKind.REQUIRED;
} else if (encoding == Tag.ParameterKindOptionalPositional) {
return ParameterKind.POSITIONAL;
} else if (encoding == Tag.ParameterKindRequiredNamed) {
return ParameterKind.NAMED_REQUIRED;
} else if (encoding == Tag.ParameterKindOptionalNamed) {
return ParameterKind.NAMED;
} else {
throw StateError('Unexpected parameter kind encoding: $encoding');
}
}
}
class TopLevelVariableElementLinkedData
extends ElementLinkedData<TopLevelVariableFragmentImpl> {
ApplyConstantOffsets? applyConstantOffsets;
TopLevelVariableElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required LibraryFragmentImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@override
void _clearLinkedDataOnRead(TopLevelVariableFragmentImpl element) {
element.linkedData = null;
}
@override
void _read(element, reader) {
element.metadata = reader._readAnnotationList(unitElement: unitElement);
element.type = reader.readRequiredType();
if (element is ConstTopLevelVariableFragmentImpl) {
var initializer = reader._readOptionalExpression();
if (initializer != null) {
element.constantInitializer = initializer;
ConstantContextForExpressionImpl(element, initializer);
}
}
applyConstantOffsets?.perform();
}
}
class TypeAliasElementLinkedData
extends ElementLinkedData<TypeAliasFragmentImpl> {
ApplyConstantOffsets? applyConstantOffsets;
TypeAliasElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required LibraryFragmentImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@override
void _clearLinkedDataOnRead(TypeAliasFragmentImpl element) {
element.linkedData = null;
}
@override
void _read(element, reader) {
element.metadata = reader._readAnnotationList(unitElement: unitElement);
_readTypeParameters(reader, element.typeParameters);
element.aliasedElement = reader._readAliasedElement(unitElement);
element.aliasedType = reader.readRequiredType();
applyConstantOffsets?.perform();
}
}
/// Information that we need to know about each library before reading it,
/// and without reading it.
///
/// Specifically, the [offset] allows us to know the location of each library,
/// so that when we need to read this library, we know where it starts without
/// reading previous libraries.
class _LibraryHeader {
final Uri uri;
final int offset;
/// We don't read class members when reading libraries, by performance
/// reasons - in many cases only some classes of a library are used. But
/// we need to know how much data to skip for each class.
final Uint32List classMembersLengths;
_LibraryHeader({
required this.uri,
required this.offset,
required this.classMembersLengths,
});
}
class _ReferenceReader {
final LinkedElementFactory elementFactory;
final SummaryDataReader _reader;
late final Uint32List _parents;
late final Uint32List _names;
late final List<Reference?> _references;
_ReferenceReader(this.elementFactory, this._reader, int offset) {
_reader.offset = offset;
_parents = _reader.readUInt30List();
_names = _reader.readUInt30List();
assert(_parents.length == _names.length);
_references = List.filled(_names.length, null);
}
Reference referenceOfIndex(int index) {
var reference = _references[index];
if (reference != null) {
return reference;
}
if (index == 0) {
reference = elementFactory.rootReference;
_references[index] = reference;
return reference;
}
var nameIndex = _names[index];
var name = _reader.stringOfIndex(nameIndex);
var parentIndex = _parents[index];
var parent = referenceOfIndex(parentIndex);
reference = parent.getChild(name);
_references[index] = reference;
return reference;
}
}