blob: 268706f67cac504213f136a81a54f92c455df005 [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:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.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/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/dart/resolver/variance.dart';
import 'package:analyzer/src/generated/source.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/macro_application_error.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/task/inference_error.dart';
import 'package:pub_semver/pub_semver.dart';
class BundleReader {
final SummaryDataReader _reader;
final Map<Uri, Uint8List> _unitsInformativeBytes;
final Map<Uri, LibraryReader> libraryMap = {};
BundleReader({
required LinkedElementFactory elementFactory,
required Uint8List resolutionBytes,
Map<Uri, Uint8List> unitsInformativeBytes = const {},
}) : _reader = SummaryDataReader(resolutionBytes),
_unitsInformativeBytes = unitsInformativeBytes {
_reader.offset = _reader.bytes.length - 4 * 4;
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: Uri.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,
unitsInformativeBytes: _unitsInformativeBytes,
baseResolutionOffset: baseResolutionOffset,
referenceReader: referenceReader,
reference: reference,
offset: libraryHeader.offset,
classMembersLengths: libraryHeader.classMembersLengths,
);
}
}
}
class ClassElementLinkedData extends ElementLinkedData<ClassElementImpl> {
ApplyConstantOffsets? applyConstantOffsets;
void Function()? _readMembers;
void Function()? applyInformativeDataToMembers;
ClassElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required CompilationUnitElementImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
/// Ensure that all members of the [element] are available. This includes
/// being able to ask them for example using [ClassElement.methods], 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(ClassElementImpl element) {
if (element.isMixinApplication) {
element.constructors;
} else {
_readMembers?.call();
_readMembers = null;
applyInformativeDataToMembers?.call();
applyInformativeDataToMembers = null;
}
}
@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();
}
}
class CompilationUnitElementLinkedData
extends ElementLinkedData<CompilationUnitElementImpl> {
CompilationUnitElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required CompilationUnitElementImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@override
void _read(element, reader) {}
}
class ConstructorElementLinkedData
extends ElementLinkedData<ConstructorElementImpl> {
ApplyConstantOffsets? applyConstantOffsets;
ConstructorElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required CompilationUnitElementImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@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 ConstructorElement?;
element.redirectedConstructor = reader.readElement() as ConstructorElement?;
element.constantInitializers = reader._readNodeList();
applyConstantOffsets?.perform();
}
}
/// Lazy reader of resolution information.
abstract class ElementLinkedData<E extends ElementImpl> {
final Reference reference;
final LibraryReader _libraryReader;
final CompilationUnitElementImpl 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(ElementImpl element) {
if (_offset == -1) {
return;
}
var dataReader = _libraryReader._reader.fork(_offset);
_offset = -1;
var reader = ResolutionReader(
_libraryReader._elementFactory,
_libraryReader._referenceReader,
dataReader,
);
_read(element as E, reader);
}
void _addEnclosingElementTypeParameters(
ResolutionReader reader,
ElementImpl element,
) {
var enclosing = element.enclosingElement;
if (enclosing is ClassElement) {
reader._addTypeParameters(enclosing.typeParameters);
} else if (enclosing is CompilationUnitElement) {
// Nothing.
} else if (enclosing is ExtensionElement) {
reader._addTypeParameters(enclosing.typeParameters);
} else {
throw UnimplementedError('${enclosing.runtimeType}');
}
}
void _read(E element, ResolutionReader reader);
void _readFormalParameters(
ResolutionReader reader,
List<ParameterElement> parameters,
) {
for (var parameter in parameters) {
parameter as ParameterElementImpl;
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 FieldFormalParameterElementImpl) {
parameter.field = reader.readElement() as FieldElement?;
}
}
}
void _readTypeParameters(
ResolutionReader reader,
List<TypeParameterElement> typeParameters,
) {
reader._addTypeParameters(typeParameters);
for (var typeParameter in typeParameters) {
typeParameter as TypeParameterElementImpl;
typeParameter.metadata = reader._readAnnotationList(
unitElement: unitElement,
);
typeParameter.bound = reader.readType();
typeParameter.defaultType = reader.readType();
}
}
}
class EnumElementLinkedData extends ElementLinkedData<EnumElementImpl> {
ApplyConstantOffsets? applyConstantOffsets;
EnumElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required CompilationUnitElementImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@override
void _read(element, reader) {
element.metadata = reader._readAnnotationList(
unitElement: element.enclosingElement,
);
_readTypeParameters(reader, element.typeParameters);
element.supertype = reader._readOptionalInterfaceType();
element.mixins = reader._readInterfaceTypeList();
element.interfaces = reader._readInterfaceTypeList();
applyConstantOffsets?.perform();
}
}
class ExtensionElementLinkedData
extends ElementLinkedData<ExtensionElementImpl> {
ApplyConstantOffsets? applyConstantOffsets;
ExtensionElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required CompilationUnitElementImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@override
void _read(element, reader) {
element.metadata = reader._readAnnotationList(
unitElement: element.enclosingElement,
);
_readTypeParameters(reader, element.typeParameters);
element.extendedType = reader.readRequiredType();
applyConstantOffsets?.perform();
}
}
class FieldElementLinkedData extends ElementLinkedData<FieldElementImpl> {
ApplyConstantOffsets? applyConstantOffsets;
FieldElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required CompilationUnitElementImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@override
void _read(element, reader) {
_addEnclosingElementTypeParameters(reader, element);
element.metadata = reader._readAnnotationList(
unitElement: unitElement,
);
element.type = reader.readRequiredType();
if (element is ConstFieldElementImpl) {
var initializer = reader._readOptionalExpression();
if (initializer != null) {
element.constantInitializer = initializer;
ConstantContextForExpressionImpl(initializer);
}
}
applyConstantOffsets?.perform();
}
}
class FunctionElementLinkedData extends ElementLinkedData<FunctionElementImpl> {
ApplyConstantOffsets? applyConstantOffsets;
FunctionElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required CompilationUnitElementImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@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();
}
}
class LibraryElementLinkedData extends ElementLinkedData<LibraryElementImpl> {
ApplyConstantOffsets? applyConstantOffsets;
LibraryElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required CompilationUnitElementImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
LinkedElementFactory get elementFactory {
return _libraryReader._elementFactory;
}
@override
void _read(element, reader) {
element.metadata = reader._readAnnotationList(
unitElement: unitElement,
);
for (var import in element.imports2) {
import as ImportElement2Impl;
import.metadata = reader._readAnnotationList(
unitElement: unitElement,
);
final uri = import.uri;
if (uri is DirectiveUriWithLibraryImpl) {
uri.library = reader.libraryOfUri(uri.source.uri);
}
}
for (var export in element.exports) {
export as ExportElementImpl;
export.metadata = reader._readAnnotationList(
unitElement: unitElement,
);
export.exportedLibrary = reader.readElement() as LibraryElementImpl?;
}
for (final part in element.parts2) {
part as PartElementImpl;
part.metadata = reader._readAnnotationList(
unitElement: unitElement,
);
}
element.entryPoint = reader.readElement() as FunctionElement?;
applyConstantOffsets?.perform();
}
}
class LibraryReader {
final LinkedElementFactory _elementFactory;
final SummaryDataReader _reader;
final Map<Uri, Uint8List> _unitsInformativeBytes;
final int _baseResolutionOffset;
final _ReferenceReader _referenceReader;
final Reference _reference;
final int _offset;
final Uint32List _classMembersLengths;
int _classMembersLengthsIndex = 0;
LibraryReader._({
required LinkedElementFactory elementFactory,
required SummaryDataReader reader,
required Map<Uri, Uint8List> unitsInformativeBytes,
required int baseResolutionOffset,
required _ReferenceReader referenceReader,
required Reference reference,
required int offset,
required Uint32List classMembersLengths,
}) : _elementFactory = elementFactory,
_reader = reader,
_unitsInformativeBytes = unitsInformativeBytes,
_baseResolutionOffset = baseResolutionOffset,
_referenceReader = referenceReader,
_reference = reference,
_offset = offset,
_classMembersLengths = classMembersLengths;
LibraryElementImpl readElement({required Source librarySource}) {
var analysisContext = _elementFactory.analysisContext;
var analysisSession = _elementFactory.analysisSession;
_reader.offset = _offset;
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var name = _reader.readStringReference();
var featureSet = _readFeatureSet();
var libraryElement = LibraryElementImpl(
analysisContext, analysisSession, name, -1, 0, featureSet);
_reference.element = libraryElement;
libraryElement.reference = _reference;
libraryElement.languageVersion = _readLanguageVersion();
libraryElement.imports2 = _reader.readTypedList(() {
return _readImportElement(
libraryElement: libraryElement,
);
});
libraryElement.exports = _reader.readTypedList(_readExportElement);
LibraryElementFlags.read(_reader, libraryElement);
for (final import in libraryElement.imports2) {
final prefixElement = import.prefix?.element;
if (prefixElement is PrefixElementImpl) {
libraryElement.encloseElement(prefixElement);
}
}
libraryElement.definingCompilationUnit = _readUnitElement(
libraryElement: libraryElement,
librarySource: librarySource,
unitSource: librarySource,
);
libraryElement.parts2 = _reader.readTypedList(() {
return _readPartElement(
libraryElement: libraryElement,
);
});
libraryElement.exportedReferences = _reader.readTypedList(
_readExportedReference,
);
libraryElement.linkedData = LibraryElementLinkedData(
reference: _reference,
libraryReader: this,
unitElement: libraryElement.definingCompilationUnit,
offset: resolutionOffset,
);
_declareDartCoreDynamicNever();
InformativeDataApplier(_elementFactory, _unitsInformativeBytes)
.applyTo(libraryElement);
return libraryElement;
}
/// These elements are implicitly declared in `dart:core`.
void _declareDartCoreDynamicNever() {
if (_reference.name == 'dart:core') {
_reference.getChild('dynamic').element = DynamicElementImpl.instance;
_reference.getChild('Never').element = NeverElementImpl.instance;
}
}
ClassElementImpl _readClassElement(
CompilationUnitElementImpl unitElement,
Reference unitReference,
) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var name = _reader.readStringReference();
var reference = unitReference.getChild('@class').getChild(name);
var element = ClassElementImpl(name, -1);
var linkedData = ClassElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
);
element.setLinkedData(reference, linkedData);
ClassElementFlags.read(_reader, element);
element.macroApplicationErrors = _reader.readTypedList(
() => MacroApplicationError(_reader),
);
element.typeParameters = _readTypeParameters();
if (!element.isMixinApplication) {
var membersOffset = _reader.offset;
linkedData._readMembers = () {
_reader.offset = membersOffset;
_readClassElementMembers(unitElement, element, reference);
};
_reader.offset += _classMembersLengths[_classMembersLengthsIndex++];
}
return element;
}
void _readClassElementMembers(
CompilationUnitElementImpl unitElement,
ClassElementImpl element,
Reference reference,
) {
var accessors = <PropertyAccessorElementImpl>[];
var fields = <FieldElement>[];
_readFields(unitElement, element, reference, accessors, fields);
_readPropertyAccessors(
unitElement, element, reference, accessors, fields, '@field');
element.fields = fields;
element.accessors = accessors;
element.constructors = _readConstructors(unitElement, element, reference);
element.methods = _readMethods(unitElement, element, reference);
}
void _readClasses(
CompilationUnitElementImpl unitElement,
Reference unitReference,
) {
var length = _reader.readUInt30();
unitElement.classes = List.generate(length, (index) {
return _readClassElement(unitElement, unitReference);
});
}
List<ConstructorElementImpl> _readConstructors(
CompilationUnitElementImpl unitElement,
AbstractClassElementImpl classElement,
Reference classReference,
) {
var containerRef = classReference.getChild('@constructor');
var length = _reader.readUInt30();
return List.generate(length, (_) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var name = _reader.readStringReference();
var reference = containerRef.getChild(name);
var element = ConstructorElementImpl(name, -1);
var linkedData = ConstructorElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
);
element.setLinkedData(reference, linkedData);
ConstructorElementFlags.read(_reader, element);
element.parameters = _readParameters(element, reference);
return element;
});
}
DirectiveUri _readDirectiveUri({
required LibraryElementImpl libraryElement,
}) {
DirectiveUriWithRelativeUriStringImpl readWithRelativeUriString() {
final relativeUriString = _reader.readStringReference();
return DirectiveUriWithRelativeUriStringImpl(
relativeUriString: relativeUriString,
);
}
DirectiveUriWithRelativeUriImpl readWithRelativeUri() {
final parent = readWithRelativeUriString();
final relativeUri = Uri.parse(_reader.readStringReference());
return DirectiveUriWithRelativeUriImpl(
relativeUriString: parent.relativeUriString,
relativeUri: relativeUri,
);
}
DirectiveUriWithSourceImpl readWithSource() {
final parent = readWithRelativeUri();
final analysisContext = _elementFactory.analysisContext;
final sourceFactory = analysisContext.sourceFactory;
final sourceUriStr = _reader.readStringReference();
final sourceUri = Uri.parse(sourceUriStr);
final source = sourceFactory.forUri2(sourceUri);
// TODO(scheglov) https://github.com/dart-lang/sdk/issues/49431
final fixedSource = source ?? sourceFactory.forUri('dart:math')!;
return DirectiveUriWithSourceImpl(
relativeUriString: parent.relativeUriString,
relativeUri: parent.relativeUri,
source: fixedSource,
);
}
final kindIndex = _reader.readByte();
final kind = DirectiveUriKind.values[kindIndex];
switch (kind) {
case DirectiveUriKind.withUnit:
final parent = readWithSource();
final unitElement = _readUnitElement(
libraryElement: libraryElement,
librarySource: libraryElement.source,
unitSource: parent.source,
);
return DirectiveUriWithUnitImpl(
relativeUriString: parent.relativeUriString,
relativeUri: parent.relativeUri,
unit: unitElement,
);
case DirectiveUriKind.withLibrary:
final parent = readWithSource();
return DirectiveUriWithLibraryImpl.read(
relativeUriString: parent.relativeUriString,
relativeUri: parent.relativeUri,
source: parent.source,
);
case DirectiveUriKind.withSource:
return readWithSource();
case DirectiveUriKind.withRelativeUri:
return readWithRelativeUri();
case DirectiveUriKind.withRelativeUriString:
return readWithRelativeUriString();
case DirectiveUriKind.withNothing:
return DirectiveUriImpl();
}
}
EnumElementImpl _readEnumElement(
CompilationUnitElementImpl unitElement,
Reference unitReference,
) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var name = _reader.readStringReference();
var reference = unitReference.getChild('@enum').getChild(name);
var element = EnumElementImpl(name, -1);
var linkedData = EnumElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
);
element.setLinkedData(reference, linkedData);
EnumElementFlags.read(_reader, element);
element.typeParameters = _readTypeParameters();
var accessors = <PropertyAccessorElement>[];
var fields = <FieldElement>[];
_readFields(unitElement, element, reference, accessors, fields);
_readPropertyAccessors(
unitElement, element, reference, accessors, fields, '@field');
element.fields = fields;
element.accessors = accessors;
element.constructors = _readConstructors(unitElement, element, reference);
element.methods = _readMethods(unitElement, element, reference);
return element;
}
void _readEnums(
CompilationUnitElementImpl unitElement,
Reference unitReference,
) {
var count = _reader.readUInt30();
unitElement.enums = List.generate(count, (_) {
return _readEnumElement(unitElement, unitReference);
});
}
ExportedReference _readExportedReference() {
final kind = _reader.readByte();
if (kind == 0) {
final index = _reader.readUInt30();
final reference = _referenceReader.referenceOfIndex(index);
return ExportedReferenceDeclared(
reference: reference,
);
} else if (kind == 1) {
final index = _reader.readUInt30();
final reference = _referenceReader.referenceOfIndex(index);
return ExportedReferenceExported(
reference: reference,
indexes: _reader.readUInt30List(),
);
} else {
throw StateError('kind: $kind');
}
}
ExportElementImpl _readExportElement() {
var element = ExportElementImpl(-1);
element.uri = _reader.readOptionalStringReference();
element.combinators = _reader.readTypedList(_readNamespaceCombinator);
return element;
}
ExtensionElementImpl _readExtensionElement(
CompilationUnitElementImpl unitElement,
Reference unitReference,
) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var name = _reader.readOptionalStringReference();
var refName = _reader.readStringReference();
var reference = unitReference.getChild('@extension').getChild(refName);
var element = ExtensionElementImpl(name, -1);
element.setLinkedData(
reference,
ExtensionElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
),
);
element.typeParameters = _readTypeParameters();
var accessors = <PropertyAccessorElement>[];
var fields = <FieldElement>[];
_readPropertyAccessors(
unitElement, element, reference, accessors, fields, '@field');
_readFields(unitElement, element, reference, accessors, fields);
element.accessors = accessors;
element.fields = fields;
element.methods = _readMethods(unitElement, element, reference);
return element;
}
void _readExtensions(
CompilationUnitElementImpl unitElement,
Reference unitReference,
) {
var count = _reader.readUInt30();
unitElement.extensions = List.generate(count, (_) {
return _readExtensionElement(unitElement, unitReference);
});
}
FeatureSet _readFeatureSet() {
var featureSetEncoded = _reader.readUint8List();
return ExperimentStatus.fromStorage(featureSetEncoded);
}
FieldElementImpl _readFieldElement(
CompilationUnitElementImpl unitElement,
ElementImpl classElement,
Reference classReference,
Reference containerRef,
) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var name = _reader.readStringReference();
var isConstElement = _reader.readBool();
var reference = containerRef.getChild(name);
FieldElementImpl element;
if (isConstElement) {
element = ConstFieldElementImpl(name, -1);
} else {
element = FieldElementImpl(name, -1);
}
var linkedData = FieldElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
);
element.setLinkedData(reference, linkedData);
FieldElementFlags.read(_reader, element);
element.typeInferenceError = _readTopLevelInferenceError();
element.createImplicitAccessors(classReference, name);
return element;
}
void _readFields(
CompilationUnitElementImpl unitElement,
ElementImpl classElement,
Reference classReference,
List<PropertyAccessorElement> accessors,
List<FieldElement> variables,
) {
var containerRef = classReference.getChild('@field');
var createdElements = <FieldElement>[];
var variableElementCount = _reader.readUInt30();
for (var i = 0; i < variableElementCount; i++) {
var variable = _readFieldElement(
unitElement, classElement, classReference, containerRef);
createdElements.add(variable);
variables.add(variable);
var getter = variable.getter;
if (getter is PropertyAccessorElementImpl) {
accessors.add(getter);
}
var setter = variable.setter;
if (setter is PropertyAccessorElementImpl) {
accessors.add(setter);
}
}
}
void _readFunctions(
CompilationUnitElementImpl unitElement,
Reference unitReference,
) {
var count = _reader.readUInt30();
unitElement.functions = List.generate(count, (_) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var name = _reader.readStringReference();
var reference = unitReference.getChild('@function').getChild(name);
var element = FunctionElementImpl(name, -1);
var linkedData = FunctionElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
);
element.setLinkedData(reference, linkedData);
FunctionElementFlags.read(_reader, element);
element.typeParameters = _readTypeParameters();
element.parameters = _readParameters(element, reference);
return element;
});
}
ImportElement2Impl _readImportElement({
required LibraryElementImpl libraryElement,
}) {
final uri = _readDirectiveUri(
libraryElement: libraryElement,
);
final prefix = _readImportElementPrefix();
final combinators = _reader.readTypedList(_readNamespaceCombinator);
final element = ImportElement2Impl(
importKeywordOffset: -1,
uri: uri,
prefix: prefix,
)..combinators = combinators;
ImportElementFlags.read(_reader, element);
return element;
}
ImportElementPrefixImpl? _readImportElementPrefix() {
PrefixElementImpl buildElement(String name) {
final reference = _reference.getChild('@prefix').getChild(name);
final existing = reference.element;
if (existing is PrefixElementImpl) {
return existing;
} else {
return PrefixElementImpl(name, -1, reference: reference);
}
}
final kindIndex = _reader.readByte();
final kind = ImportElementPrefixKind.values[kindIndex];
switch (kind) {
case ImportElementPrefixKind.isDeferred:
final name = _reader.readStringReference();
return DeferredImportElementPrefixImpl(
element: buildElement(name),
);
case ImportElementPrefixKind.isNotDeferred:
final name = _reader.readStringReference();
return ImportElementPrefixImpl(
element: buildElement(name),
);
case ImportElementPrefixKind.isNull:
return null;
}
}
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);
}
List<MethodElementImpl> _readMethods(
CompilationUnitElementImpl unitElement,
ElementImpl enclosingElement,
Reference enclosingReference,
) {
var containerRef = enclosingReference.getChild('@method');
var length = _reader.readUInt30();
return List.generate(length, (_) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var name = _reader.readStringReference();
var reference = containerRef.getChild(name);
var element = MethodElementImpl(name, -1);
var linkedData = MethodElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
);
element.setLinkedData(reference, linkedData);
MethodElementFlags.read(_reader, element);
element.typeParameters = _readTypeParameters();
element.parameters = _readParameters(element, reference);
element.typeInferenceError = _readTopLevelInferenceError();
return element;
});
}
MixinElementImpl _readMixinElement(
CompilationUnitElementImpl unitElement,
Reference unitReference,
) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var name = _reader.readStringReference();
var reference = unitReference.getChild('@mixin').getChild(name);
var element = MixinElementImpl(name, -1);
var linkedData = MixinElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
);
element.setLinkedData(reference, linkedData);
MixinElementFlags.read(_reader, element);
element.typeParameters = _readTypeParameters();
var fields = <FieldElement>[];
var accessors = <PropertyAccessorElement>[];
_readFields(unitElement, element, reference, accessors, fields);
_readPropertyAccessors(
unitElement, element, reference, accessors, fields, '@field');
element.fields = fields;
element.accessors = accessors;
element.constructors = _readConstructors(unitElement, element, reference);
element.methods = _readMethods(unitElement, element, reference);
element.superInvokedNames = _reader.readStringReferenceList();
return element;
}
void _readMixins(
CompilationUnitElementImpl unitElement,
Reference unitReference,
) {
var length = _reader.readUInt30();
unitElement.mixins = List.generate(length, (index) {
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');
}
}
List<ParameterElementImpl> _readParameters(
ElementImpl enclosingElement,
Reference enclosingReference,
) {
var containerRef = enclosingReference.getChild('@parameter');
var length = _reader.readUInt30();
return List.generate(length, (_) {
var name = _reader.readStringReference();
var isInitializingFormal = _reader.readBool();
var isSuperFormal = _reader.readBool();
var reference = containerRef.getChild(name);
var kindIndex = _reader.readByte();
var kind = ResolutionReader._formalParameterKind(kindIndex);
ParameterElementImpl element;
if (kind.isRequiredPositional) {
if (isInitializingFormal) {
element = FieldFormalParameterElementImpl(
name: name,
nameOffset: -1,
parameterKind: kind,
);
} else if (isSuperFormal) {
element = SuperFormalParameterElementImpl(
name: name,
nameOffset: -1,
parameterKind: kind,
);
} else {
element = ParameterElementImpl(
name: name,
nameOffset: -1,
parameterKind: kind,
);
}
} else {
if (isInitializingFormal) {
element = DefaultFieldFormalParameterElementImpl(
name: name,
nameOffset: -1,
parameterKind: kind,
);
} else if (isSuperFormal) {
element = DefaultSuperFormalParameterElementImpl(
name: name,
nameOffset: -1,
parameterKind: kind,
);
} else {
element = DefaultParameterElementImpl(
name: name,
nameOffset: -1,
parameterKind: kind,
);
}
element.reference = reference;
reference.element = element;
}
ParameterElementFlags.read(_reader, element);
element.typeParameters = _readTypeParameters();
element.parameters = _readParameters(element, reference);
return element;
});
}
PartElement _readPartElement({
required LibraryElementImpl libraryElement,
}) {
final uri = _readDirectiveUri(
libraryElement: libraryElement,
);
return PartElementImpl(
uri: uri,
);
}
PropertyAccessorElementImpl _readPropertyAccessorElement(
CompilationUnitElementImpl unitElement,
ElementImpl classElement,
Reference classReference,
) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var name = _reader.readStringReference();
var element = PropertyAccessorElementImpl(name, -1);
PropertyAccessorElementFlags.read(_reader, element);
var reference = classReference
.getChild(element.isGetter ? '@getter' : '@setter')
.getChild(name);
var linkedData = PropertyAccessorElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
);
element.setLinkedData(reference, linkedData);
element.parameters = _readParameters(element, reference);
return element;
}
void _readPropertyAccessors(
CompilationUnitElementImpl unitElement,
ElementImpl enclosingElement,
Reference enclosingReference,
List<PropertyAccessorElement> accessors,
List<PropertyInducingElement> properties,
String containerRefName,
) {
var containerRef = enclosingReference.getChild(containerRefName);
var accessorCount = _reader.readUInt30();
for (var i = 0; i < accessorCount; i++) {
var accessor = _readPropertyAccessorElement(
unitElement,
enclosingElement,
enclosingReference,
);
accessors.add(accessor);
var name = accessor.displayName;
var isGetter = accessor.isGetter;
var reference = containerRef.getChild(name);
PropertyInducingElementImpl property;
if (enclosingElement is CompilationUnitElementImpl) {
var existing = reference.element;
if (existing is TopLevelVariableElementImpl) {
property = existing;
} else {
var field = TopLevelVariableElementImpl(name, -1);
property = field;
}
} else {
var existing = reference.element;
if (existing is FieldElementImpl) {
property = existing;
} else {
var field = FieldElementImpl(name, -1);
field.isStatic = accessor.isStatic;
property = field;
}
}
if (reference.element == null) {
reference.element = property;
properties.add(property);
property.enclosingElement = enclosingElement;
property.isSynthetic = true;
}
accessor.variable = property;
if (isGetter) {
property.getter = accessor;
} else {
property.setter = accessor;
if (property.isSynthetic) {
property.isFinal = false;
}
}
}
}
TopLevelInferenceError? _readTopLevelInferenceError() {
var kindIndex = _reader.readByte();
var kind = TopLevelInferenceErrorKind.values[kindIndex];
if (kind == TopLevelInferenceErrorKind.none) {
return null;
}
return TopLevelInferenceError(
kind: kind,
arguments: _reader.readStringReferenceList(),
);
}
TopLevelVariableElementImpl _readTopLevelVariableElement(
CompilationUnitElementImpl unitElement,
Reference unitReference,
) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var name = _reader.readStringReference();
var isConst = _reader.readBool();
var reference = unitReference.getChild('@variable').getChild(name);
TopLevelVariableElementImpl element;
if (isConst) {
element = ConstTopLevelVariableElementImpl(name, -1);
} else {
element = TopLevelVariableElementImpl(name, -1);
}
var linkedData = TopLevelVariableElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
);
element.setLinkedData(reference, linkedData);
element.isConst = isConst;
TopLevelVariableElementFlags.read(_reader, element);
element.typeInferenceError = _readTopLevelInferenceError();
element.createImplicitAccessors(unitReference, name);
return element;
}
void _readTopLevelVariables(
CompilationUnitElementImpl unitElement,
Reference unitReference,
List<PropertyAccessorElementImpl> accessors,
List<TopLevelVariableElementImpl> 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 PropertyAccessorElementImpl) {
accessors.add(getter);
}
var setter = variable.setter;
if (setter is PropertyAccessorElementImpl) {
accessors.add(setter);
}
}
}
TypeAliasElementImpl _readTypeAliasElement(
CompilationUnitElementImpl unitElement,
Reference unitReference,
) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var name = _reader.readStringReference();
var reference = unitReference.getChild('@typeAlias').getChild(name);
var isFunctionTypeAliasBased = _reader.readBool();
TypeAliasElementImpl element;
if (isFunctionTypeAliasBased) {
element = TypeAliasElementImpl(name, -1);
element.isFunctionTypeAliasBased = true;
} else {
element = TypeAliasElementImpl(name, -1);
}
var linkedData = TypeAliasElementLinkedData(
reference: reference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
);
element.setLinkedData(reference, linkedData);
element.isFunctionTypeAliasBased = isFunctionTypeAliasBased;
TypeAliasElementFlags.read(_reader, element);
element.typeParameters = _readTypeParameters();
return element;
}
void _readTypeAliases(
CompilationUnitElementImpl unitElement,
Reference unitReference,
) {
var length = _reader.readUInt30();
unitElement.typeAliases = List.generate(length, (_) {
return _readTypeAliasElement(unitElement, unitReference);
});
}
List<TypeParameterElementImpl> _readTypeParameters() {
var length = _reader.readUInt30();
return List.generate(length, (_) {
var name = _reader.readStringReference();
var varianceEncoding = _reader.readByte();
var variance = _decodeVariance(varianceEncoding);
var element = TypeParameterElementImpl(name, -1);
element.variance = variance;
return element;
});
}
CompilationUnitElementImpl _readUnitElement({
required LibraryElementImpl libraryElement,
required Source librarySource,
required Source unitSource,
}) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var unitElement = CompilationUnitElementImpl(
source: unitSource,
librarySource: librarySource,
lineInfo: LineInfo([0]),
);
final unitContainerRef = _reference.getChild('@unit');
final unitReference = unitContainerRef.getChild('${unitSource.uri}');
unitElement.setLinkedData(
unitReference,
CompilationUnitElementLinkedData(
reference: unitReference,
libraryReader: this,
unitElement: unitElement,
offset: resolutionOffset,
),
);
unitElement.uri = _reader.readOptionalStringReference();
unitElement.isSynthetic = _reader.readBool();
_readClasses(unitElement, unitReference);
_readEnums(unitElement, unitReference);
_readExtensions(unitElement, unitReference);
_readFunctions(unitElement, unitReference);
_readMixins(unitElement, unitReference);
_readTypeAliases(unitElement, unitReference);
var accessors = <PropertyAccessorElementImpl>[];
var variables = <TopLevelVariableElementImpl>[];
_readTopLevelVariables(unitElement, unitReference, accessors, variables);
_readPropertyAccessors(unitElement, unitElement, unitReference, accessors,
variables, '@variable');
unitElement.accessors = accessors;
unitElement.topLevelVariables = variables;
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<MethodElementImpl> {
ApplyConstantOffsets? applyConstantOffsets;
MethodElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required CompilationUnitElementImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@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<MixinElementImpl> {
ApplyConstantOffsets? applyConstantOffsets;
MixinElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required CompilationUnitElementImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@override
void _read(element, reader) {
element.metadata = reader._readAnnotationList(
unitElement: element.enclosingElement,
);
_readTypeParameters(reader, element.typeParameters);
element.superclassConstraints = reader._readInterfaceTypeList();
element.interfaces = reader._readInterfaceTypeList();
applyConstantOffsets?.perform();
}
}
class PropertyAccessorElementLinkedData
extends ElementLinkedData<PropertyAccessorElementImpl> {
ApplyConstantOffsets? applyConstantOffsets;
PropertyAccessorElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required CompilationUnitElementImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@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 [TypeParameterElement]s and [ParameterElement] 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<Element> _localElements = [];
ResolutionReader(
this._elementFactory,
this._referenceReader,
this._reader,
);
LibraryElementImpl libraryOfUri(Uri uri) {
return _elementFactory.libraryOfUri2(uri);
}
int readByte() {
return _reader.readByte();
}
double readDouble() {
return _reader.readDouble();
}
Element? readElement() {
var memberFlags = _reader.readByte();
var element = _readRawElement();
if (element == null) {
return null;
}
if (memberFlags == Tag.RawElement) {
return element;
}
if (memberFlags == Tag.MemberLegacyWithTypeArguments ||
memberFlags == Tag.MemberWithTypeArguments) {
var arguments = _readTypeList();
// TODO(scheglov) why to check for empty? If we have this flags.
if (arguments.isNotEmpty) {
var typeParameters =
(element.enclosingElement as TypeParameterizedElement)
.typeParameters;
var substitution = Substitution.fromPairs(typeParameters, arguments);
element =
ExecutableMember.from2(element as ExecutableElement, substitution);
}
}
if (memberFlags == Tag.MemberLegacyWithTypeArguments) {
return Member.legacy(element);
}
if (memberFlags == Tag.MemberWithTypeArguments) {
return element;
}
throw UnimplementedError('memberFlags: $memberFlags');
}
FunctionType? readOptionalFunctionType() {
var type = readType();
return type is FunctionType ? type : null;
}
List<DartType>? readOptionalTypeList() {
if (_reader.readBool()) {
return _readTypeList();
} else {
return null;
}
}
DartType readRequiredType() {
return readType()!;
}
String readStringReference() {
return _reader.readStringReference();
}
List<String> readStringReferenceList() {
return _reader.readStringReferenceList();
}
DartType? 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 ClassElement;
var typeArguments = _readTypeList();
var nullability = _readNullability();
var type = InterfaceTypeImpl(
element: element,
typeArguments: typeArguments,
nullabilitySuffix: nullability,
);
return _readAliasElementArguments(type);
} else if (tag == Tag.InterfaceType_noTypeArguments_none) {
var element = readElement() as ClassElement;
var type = InterfaceTypeImpl(
element: element,
typeArguments: const <DartType>[],
nullabilitySuffix: NullabilitySuffix.none,
);
return _readAliasElementArguments(type);
} else if (tag == Tag.InterfaceType_noTypeArguments_question) {
var element = readElement() as ClassElement;
var type = InterfaceTypeImpl(
element: element,
typeArguments: const <DartType>[],
nullabilitySuffix: NullabilitySuffix.question,
);
return _readAliasElementArguments(type);
} else if (tag == Tag.InterfaceType_noTypeArguments_star) {
var element = readElement() as ClassElement;
var type = InterfaceTypeImpl(
element: element,
typeArguments: const <DartType>[],
nullabilitySuffix: NullabilitySuffix.star,
);
return _readAliasElementArguments(type);
} else if (tag == Tag.NeverType) {
var nullability = _readNullability();
var type = NeverTypeImpl.instance.withNullability(nullability);
return _readAliasElementArguments(type);
} else if (tag == Tag.TypeParameterType) {
var element = readElement() as TypeParameterElement;
var nullability = _readNullability();
var type = TypeParameterTypeImpl(
element: element,
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) {
var length = readUInt30();
return List<T>.generate(length, (_) {
return read();
});
}
int readUInt30() {
return _reader.readUInt30();
}
int readUInt32() {
return _reader.readUInt32();
}
void _addFormalParameters(List<ParameterElement> parameters) {
for (var parameter in parameters) {
_localElements.add(parameter);
}
}
void _addTypeParameters(List<TypeParameterElement> typeParameters) {
for (var typeParameter in typeParameters) {
_localElements.add(typeParameter);
}
}
ElementImpl? _readAliasedElement(CompilationUnitElementImpl 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 GenericFunctionTypeElementImpl.forOffset(-1)
..typeParameters = typeParameters
..parameters = formalParameters
..returnType = returnType;
} else {
throw UnimplementedError('tag: $tag');
}
}
DartType _readAliasElementArguments(DartType type) {
var aliasElement = _readRawElement();
if (aliasElement is TypeAliasElement) {
var aliasArguments = _readTypeList();
if (type is DynamicType) {
// TODO(scheglov) add support for `dynamic` aliasing
return type;
} else if (type is FunctionType) {
return FunctionTypeImpl(
typeFormals: type.typeFormals,
parameters: type.parameters,
returnType: type.returnType,
nullabilitySuffix: type.nullabilitySuffix,
alias: InstantiatedTypeAliasElementImpl(
element: aliasElement,
typeArguments: aliasArguments,
),
);
} else if (type is InterfaceType) {
return InterfaceTypeImpl(
element: type.element,
typeArguments: type.typeArguments,
nullabilitySuffix: type.nullabilitySuffix,
alias: InstantiatedTypeAliasElementImpl(
element: aliasElement,
typeArguments: aliasArguments,
),
);
} else if (type is TypeParameterType) {
return TypeParameterTypeImpl(
element: type.element,
nullabilitySuffix: type.nullabilitySuffix,
alias: InstantiatedTypeAliasElementImpl(
element: aliasElement,
typeArguments: aliasArguments,
),
);
} else if (type is VoidType) {
// TODO(scheglov) add support for `void` aliasing
return type;
} else {
throw UnimplementedError('${type.runtimeType}');
}
}
return type;
}
List<ElementAnnotationImpl> _readAnnotationList({
required CompilationUnitElementImpl unitElement,
}) {
var length = _reader.readUInt30();
if (length == 0) {
return const <ElementAnnotationImpl>[];
}
return List.generate(length, (_) {
var ast = _readRequiredNode() as Annotation;
return ElementAnnotationImpl(unitElement)
..annotationAst = ast
..element = ast.element;
});
}
List<ParameterElementImpl> _readFormalParameters(
CompilationUnitElementImpl? unitElement,
) {
var formalParameterCount = _reader.readUInt30();
return List.generate(formalParameterCount, (_) {
var kindIndex = _reader.readByte();
var kind = _formalParameterKind(kindIndex);
var hasImplicitType = _reader.readBool();
var isInitializingFormal = _reader.readBool();
var typeParameters = _readTypeParameters(unitElement);
var type = readRequiredType();
var name = readStringReference();
if (kind.isRequiredPositional) {
ParameterElementImpl element;
if (isInitializingFormal) {
element = FieldFormalParameterElementImpl(
name: name,
nameOffset: -1,
parameterKind: kind,
)..type = type;
} else {
element = ParameterElementImpl(
name: name,
nameOffset: -1,
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 = DefaultParameterElementImpl(
name: name,
nameOffset: -1,
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.
FunctionType _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,
);
}
InterfaceType _readInterfaceType() {
return readType() as InterfaceType;
}
List<InterfaceType> _readInterfaceTypeList() {
var length = _reader.readUInt30();
if (length == 0) {
return const <InterfaceType>[];
}
return List.generate(length, (_) => _readInterfaceType());
}
List<T> _readNodeList<T>() {
var length = _reader.readUInt30();
return List<T>.generate(length, (_) {
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?;
}
Element? _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);
}
AstNode _readRequiredNode() {
var astReader = AstBinaryReader(reader: this);
return astReader.readNode();
}
List<DartType> _readTypeList() {
var types = <DartType>[];
var length = _reader.readUInt30();
for (var i = 0; i < length; i++) {
var argument = readType()!;
types.add(argument);
}
return types;
}
List<TypeParameterElementImpl> _readTypeParameters(
CompilationUnitElementImpl? unitElement,
) {
var typeParameterCount = _reader.readUInt30();
var typeParameters = List.generate(typeParameterCount, (_) {
var name = readStringReference();
var typeParameter = TypeParameterElementImpl(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<TopLevelVariableElementImpl> {
ApplyConstantOffsets? applyConstantOffsets;
TopLevelVariableElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required CompilationUnitElementImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@override
void _read(element, reader) {
element.metadata = reader._readAnnotationList(
unitElement: unitElement,
);
element.type = reader.readRequiredType();
if (element is ConstTopLevelVariableElementImpl) {
var initializer = reader._readOptionalExpression();
if (initializer != null) {
element.constantInitializer = initializer;
ConstantContextForExpressionImpl(initializer);
}
}
applyConstantOffsets?.perform();
}
}
class TypeAliasElementLinkedData
extends ElementLinkedData<TypeAliasElementImpl> {
ApplyConstantOffsets? applyConstantOffsets;
TypeAliasElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required CompilationUnitElementImpl unitElement,
required int offset,
}) : super(reference, libraryReader, unitElement, offset);
@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;
}
}