blob: b472f5ada40c98c11bd7b3a7d3fed1ffd2ad8935 [file] [log] [blame]
// Copyright (c) 2019, 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 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/utilities.dart';
import 'package:analyzer/dart/ast/ast.dart' as ast;
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/visitor.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart' hide DirectiveUri;
import 'package:analyzer/src/dart/analysis/file_state.dart' as file_state;
import 'package:analyzer/src/dart/analysis/unlinked_data.dart';
import 'package:analyzer/src/dart/ast/ast.dart' as ast;
import 'package:analyzer/src/dart/ast/mixin_super_invoked_names.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary2/combinator.dart';
import 'package:analyzer/src/summary2/constructor_initializer_resolver.dart';
import 'package:analyzer/src/summary2/default_value_resolver.dart';
import 'package:analyzer/src/summary2/element_builder.dart';
import 'package:analyzer/src/summary2/export.dart';
import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/macro_application.dart';
import 'package:analyzer/src/summary2/metadata_resolver.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/summary2/reference_resolver.dart';
import 'package:analyzer/src/summary2/types_builder.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
class DefiningLinkingUnit extends LinkingUnit {
DefiningLinkingUnit({
required super.reference,
required super.node,
required super.element,
required super.container,
});
}
class ImplicitEnumNodes {
final EnumElementImpl element;
final ast.NamedTypeImpl valuesTypeNode;
final ConstFieldElementImpl valuesField;
ImplicitEnumNodes({
required this.element,
required this.valuesTypeNode,
required this.valuesField,
});
}
class LibraryBuilder {
final Linker linker;
final LibraryFileKind kind;
final Uri uri;
final Reference reference;
final LibraryElementImpl element;
final List<LinkingUnit> units;
final List<ImplicitEnumNodes> implicitEnumNodes = [];
/// Local declarations.
final Map<String, Reference> _declaredReferences = {};
/// The export scope of the library.
final ExportScope exportScope = ExportScope();
/// The `export` directives that export this library.
final List<Export> exports = [];
late final LibraryMacroApplier? _macroApplier = () {
if (!element.featureSet.isEnabled(Feature.macros)) {
return null;
}
final macroExecutor = linker.macroExecutor;
if (macroExecutor == null) {
return null;
}
return LibraryMacroApplier(
macroExecutor: macroExecutor,
declarationBuilder: linker.macroDeclarationBuilder,
libraryBuilder: this,
);
}();
LibraryBuilder._({
required this.linker,
required this.kind,
required this.uri,
required this.reference,
required this.element,
required this.units,
});
SourceFactory get _sourceFactory {
return linker.elementFactory.analysisContext.sourceFactory;
}
void addExporters() {
final containers = [element, ...element.augmentations];
for (var containerIndex = 0;
containerIndex < containers.length;
containerIndex++) {
final container = containers[containerIndex];
final exportElements = container.libraryExports;
for (var exportIndex = 0;
exportIndex < exportElements.length;
exportIndex++) {
final exportElement = exportElements[exportIndex];
final exportedLibrary = exportElement.exportedLibrary;
if (exportedLibrary is! LibraryElementImpl) {
continue;
}
final combinators = exportElement.combinators.map((combinator) {
if (combinator is ShowElementCombinator) {
return Combinator.show(combinator.shownNames);
} else if (combinator is HideElementCombinator) {
return Combinator.hide(combinator.hiddenNames);
} else {
throw UnimplementedError();
}
}).toList();
final exportedUri = exportedLibrary.source.uri;
final exportedBuilder = linker.builders[exportedUri];
final export = Export(
exporter: this,
location: ExportLocation(
containerIndex: containerIndex,
exportIndex: exportIndex,
),
combinators: combinators,
);
if (exportedBuilder != null) {
exportedBuilder.exports.add(export);
} else {
final exportedReferences = exportedLibrary.exportedReferences;
for (final exported in exportedReferences) {
final reference = exported.reference;
final name = reference.name;
if (reference.isSetter) {
export.addToExportScope('$name=', exported);
} else {
export.addToExportScope(name, exported);
}
}
}
}
}
}
/// Build elements for declarations in the library units, add top-level
/// declarations to the local scope, for combining into export scopes.
void buildElements() {
_buildDirectives(
kind: kind,
container: element,
);
for (var linkingUnit in units) {
var elementBuilder = ElementBuilder(
libraryBuilder: this,
container: linkingUnit.container,
unitReference: linkingUnit.reference,
unitElement: linkingUnit.element,
);
if (linkingUnit is DefiningLinkingUnit) {
elementBuilder.buildLibraryElementChildren(linkingUnit.node);
}
elementBuilder.buildDeclarationElements(linkingUnit.node);
}
_declareDartCoreDynamicNever();
}
void buildEnumChildren() {
var typeProvider = element.typeProvider;
for (var enum_ in implicitEnumNodes) {
enum_.element.supertype =
typeProvider.enumType ?? typeProvider.objectType;
var valuesType = typeProvider.listType(
element.typeSystem.instantiateToBounds2(
classElement: enum_.element,
nullabilitySuffix: typeProvider.objectType.nullabilitySuffix,
),
);
enum_.valuesTypeNode.type = valuesType;
enum_.valuesField.type = valuesType;
}
}
void buildInitialExportScope() {
_declaredReferences.forEach((name, reference) {
if (name.startsWith('_')) return;
if (reference.isPrefix) return;
exportScope.declare(name, reference);
});
}
void collectMixinSuperInvokedNames() {
for (var linkingUnit in units) {
for (var declaration in linkingUnit.node.declarations) {
if (declaration is ast.MixinDeclaration) {
var names = <String>{};
var collector = MixinSuperInvokedNamesCollector(names);
for (var executable in declaration.members) {
if (executable is ast.MethodDeclaration) {
executable.body.accept(collector);
}
}
var element = declaration.declaredElement as MixinElementImpl;
element.superInvokedNames = names.toList();
}
}
}
}
void declare(String name, Reference reference) {
_declaredReferences[name] = reference;
}
Future<void> executeMacroDeclarationsPhase() async {
final macroApplier = _macroApplier;
if (macroApplier == null) {
return;
}
final augmentationLibrary = await macroApplier.executeDeclarationsPhase();
if (augmentationLibrary == null) {
return;
}
final parseResult = parseString(
content: augmentationLibrary,
featureSet: element.featureSet,
throwIfDiagnostics: false,
);
final unitNode = parseResult.unit as ast.CompilationUnitImpl;
// We don't actually keep this unit, but we need it for now as a container.
// Eventually we will use actual augmentation libraries.
final unitUri = uri.resolve('_macro_declarations.dart');
final unitReference = reference.getChild('@unit').getChild('$unitUri');
final unitElement = CompilationUnitElementImpl(
source: _sourceFactory.forUri2(unitUri)!,
librarySource: element.source,
lineInfo: parseResult.lineInfo,
)
..enclosingElement = element
..isSynthetic = true
..uri = unitUri.toString();
final elementBuilder = ElementBuilder(
libraryBuilder: this,
container: element,
unitReference: unitReference,
unitElement: unitElement,
);
elementBuilder.buildDeclarationElements(unitNode);
// We move elements, so they don't have real offsets.
unitElement.accept(_FlushElementOffsets());
final nodesToBuildType = NodesToBuildType();
final resolver = ReferenceResolver(linker, nodesToBuildType, element);
unitNode.accept(resolver);
TypesBuilder(linker).build(nodesToBuildType);
// Transplant built elements as if the augmentation was applied.
final augmentedUnitElement = element.definingCompilationUnit;
for (final augmentation in unitElement.classes) {
// TODO(scheglov) if augmentation
final augmented = element.getType(augmentation.name);
if (augmented is ClassElementImpl) {
augmented.accessors = [
...augmented.accessors,
...augmentation.accessors,
];
augmented.constructors = [
...augmented.constructors,
...augmentation.constructors.where((e) => !e.isSynthetic),
];
augmented.fields = [
...augmented.fields,
...augmentation.fields,
];
augmented.methods = [
...augmented.methods,
...augmentation.methods,
];
}
}
augmentedUnitElement.accessors = [
...augmentedUnitElement.accessors,
...unitElement.accessors,
];
augmentedUnitElement.topLevelVariables = [
...augmentedUnitElement.topLevelVariables,
...unitElement.topLevelVariables,
];
}
Future<void> executeMacroTypesPhase({
required OperationPerformanceImpl performance,
}) async {
final macroApplier = _macroApplier;
if (macroApplier == null) {
return;
}
await performance.runAsync(
'buildApplications',
(performance) async {
await macroApplier.buildApplications(
performance: performance,
);
},
);
final augmentationLibrary = await performance.runAsync(
'executeTypesPhase',
(performance) async {
return await macroApplier.executeTypesPhase();
},
);
if (augmentationLibrary == null) {
return;
}
var parseResult = parseString(
content: augmentationLibrary,
featureSet: element.featureSet,
throwIfDiagnostics: false,
);
var unitNode = parseResult.unit as ast.CompilationUnitImpl;
// For now we model augmentation libraries as parts.
var unitUri = uri.resolve('_macro_types.dart');
final unitSource = _sourceFactory.forUri2(unitUri)!;
var unitElement = CompilationUnitElementImpl(
source: unitSource,
librarySource: element.source,
lineInfo: parseResult.lineInfo,
)
..enclosingElement = element
..isSynthetic = true
..uri = unitUri.toString();
var unitReference = reference.getChild('@unit').getChild('$unitUri');
_bindReference(unitReference, unitElement);
element.parts2.add(
PartElementImpl(
uri: DirectiveUriWithUnitImpl(
relativeUriString: '_macro_types.dart',
relativeUri: unitUri,
unit: unitElement,
),
),
);
ElementBuilder(
libraryBuilder: this,
container: element,
unitReference: unitReference,
unitElement: unitElement,
).buildDeclarationElements(unitNode);
// We move elements, so they don't have real offsets.
unitElement.accept(_FlushElementOffsets());
units.add(
LinkingUnit(
reference: unitReference,
node: unitNode,
container: element,
element: unitElement,
),
);
linker.macroGeneratedUnits.add(
LinkMacroGeneratedUnit(
uri: unitUri,
content: parseResult.content,
unit: parseResult.unit,
),
);
}
void resolveConstructors() {
ConstructorInitializerResolver(linker, element).resolve();
}
void resolveDefaultValues() {
DefaultValueResolver(linker, element).resolve();
}
void resolveMetadata() {
for (var linkingUnit in units) {
var resolver = MetadataResolver(linker, element, linkingUnit.element);
linkingUnit.node.accept(resolver);
}
}
void resolveTypes(NodesToBuildType nodesToBuildType) {
for (var linkingUnit in units) {
var resolver = ReferenceResolver(
linker,
nodesToBuildType,
linkingUnit.container,
);
linkingUnit.node.accept(resolver);
}
}
void storeExportScope() {
element.exportedReferences = exportScope.map.values.toList();
var definedNames = <String, Element>{};
for (var entry in exportScope.map.entries) {
var reference = entry.value.reference;
var element = linker.elementFactory.elementOfReference(reference);
if (element != null) {
definedNames[entry.key] = element;
}
}
var namespace = Namespace(definedNames);
element.exportNamespace = namespace;
var entryPoint = namespace.get(FunctionElement.MAIN_FUNCTION_NAME);
if (entryPoint is FunctionElement) {
element.entryPoint = entryPoint;
}
}
AugmentationImportElementImpl _buildAugmentationImport(
LibraryOrAugmentationElementImpl augmentationTarget,
AugmentationImportState state,
) {
final DirectiveUri uri;
if (state is AugmentationImportWithFile) {
final importedAugmentation = state.importedAugmentation;
if (importedAugmentation != null) {
final importedFile = importedAugmentation.file;
final unitNode = importedFile.parse();
final unitElement = CompilationUnitElementImpl(
source: importedFile.source,
// TODO(scheglov) Remove this parameter.
librarySource: importedFile.source,
lineInfo: unitNode.lineInfo,
);
unitElement.setCodeRange(0, unitNode.length);
final unitReference =
reference.getChild('@augmentation').getChild(importedFile.uriStr);
_bindReference(unitReference, unitElement);
final augmentation = LibraryAugmentationElementImpl(
augmentationTarget: augmentationTarget,
nameOffset: importedAugmentation.unlinked.libraryKeywordOffset,
);
augmentation.definingCompilationUnit = unitElement;
augmentation.reference = unitElement.reference!;
_buildDirectives(
kind: importedAugmentation,
container: augmentation,
);
uri = DirectiveUriWithAugmentationImpl(
relativeUriString: state.uri.relativeUriStr,
relativeUri: state.uri.relativeUri,
source: importedFile.source,
augmentation: augmentation,
);
units.add(
DefiningLinkingUnit(
reference: unitReference,
node: unitNode,
element: unitElement,
container: augmentation,
),
);
} else {
uri = DirectiveUriWithSourceImpl(
relativeUriString: state.uri.relativeUriStr,
relativeUri: state.uri.relativeUri,
source: state.importedSource,
);
}
} else {
final selectedUri = state.uri;
if (selectedUri is file_state.DirectiveUriWithUri) {
uri = DirectiveUriWithRelativeUriImpl(
relativeUriString: selectedUri.relativeUriStr,
relativeUri: selectedUri.relativeUri,
);
} else if (selectedUri is file_state.DirectiveUriWithString) {
uri = DirectiveUriWithRelativeUriStringImpl(
relativeUriString: selectedUri.relativeUriStr,
);
} else {
uri = DirectiveUriImpl();
}
}
return AugmentationImportElementImpl(
importKeywordOffset: state.unlinked.importKeywordOffset,
uri: uri,
);
}
List<NamespaceCombinator> _buildCombinators(
List<UnlinkedCombinator> combinators2,
) {
return combinators2.map((unlinked) {
if (unlinked.isShow) {
return ShowElementCombinatorImpl()
..offset = unlinked.keywordOffset
..end = unlinked.endOffset
..shownNames = unlinked.names;
} else {
// TODO(scheglov) Why no offsets?
return HideElementCombinatorImpl()..hiddenNames = unlinked.names;
}
}).toList();
}
/// Builds directive elements, for the library and recursively for its
/// augmentations.
void _buildDirectives({
required LibraryOrAugmentationFileKind kind,
required LibraryOrAugmentationElementImpl container,
}) {
container.libraryExports = kind.libraryExports.map(_buildExport).toList();
container.libraryImports = kind.libraryImports.map((state) {
return _buildImport(
container: container,
state: state,
);
}).toList();
container.augmentationImports = kind.augmentationImports.map((state) {
return _buildAugmentationImport(container, state);
}).toList();
}
LibraryExportElementImpl _buildExport(LibraryExportState state) {
final combinators = _buildCombinators(
state.unlinked.combinators,
);
final DirectiveUri uri;
if (state is LibraryExportWithFile) {
final exportedLibraryKind = state.exportedLibrary;
if (exportedLibraryKind != null) {
final exportedFile = exportedLibraryKind.file;
final exportedUri = exportedFile.uri;
final elementFactory = linker.elementFactory;
final exportedLibrary = elementFactory.libraryOfUri2(exportedUri);
uri = DirectiveUriWithLibraryImpl(
relativeUriString: state.selectedUri.relativeUriStr,
relativeUri: state.selectedUri.relativeUri,
source: exportedLibrary.source,
library: exportedLibrary,
);
} else {
uri = DirectiveUriWithSourceImpl(
relativeUriString: state.selectedUri.relativeUriStr,
relativeUri: state.selectedUri.relativeUri,
source: state.exportedSource,
);
}
} else if (state is LibraryExportWithInSummarySource) {
final exportedLibrarySource = state.exportedLibrarySource;
if (exportedLibrarySource != null) {
final exportedUri = exportedLibrarySource.uri;
final elementFactory = linker.elementFactory;
final exportedLibrary = elementFactory.libraryOfUri2(exportedUri);
uri = DirectiveUriWithLibraryImpl(
relativeUriString: state.selectedUri.relativeUriStr,
relativeUri: state.selectedUri.relativeUri,
source: exportedLibrary.source,
library: exportedLibrary,
);
} else {
uri = DirectiveUriWithSourceImpl(
relativeUriString: state.selectedUri.relativeUriStr,
relativeUri: state.selectedUri.relativeUri,
source: state.exportedSource,
);
}
} else {
final selectedUri = state.selectedUri;
if (selectedUri is file_state.DirectiveUriWithUri) {
uri = DirectiveUriWithRelativeUriImpl(
relativeUriString: selectedUri.relativeUriStr,
relativeUri: selectedUri.relativeUri,
);
} else if (selectedUri is file_state.DirectiveUriWithString) {
uri = DirectiveUriWithRelativeUriStringImpl(
relativeUriString: selectedUri.relativeUriStr,
);
} else {
uri = DirectiveUriImpl();
}
}
return LibraryExportElementImpl(
combinators: combinators,
exportKeywordOffset: state.unlinked.exportKeywordOffset,
uri: uri,
);
}
LibraryImportElementImpl _buildImport({
required LibraryOrAugmentationElementImpl container,
required LibraryImportState state,
}) {
final importPrefix = state.unlinked.prefix.mapOrNull((unlinked) {
final prefix = _buildPrefix(
name: unlinked.name,
nameOffset: unlinked.nameOffset,
container: container,
);
if (unlinked.deferredOffset != null) {
return DeferredImportElementPrefixImpl(
element: prefix,
);
} else {
return ImportElementPrefixImpl(
element: prefix,
);
}
});
final combinators = _buildCombinators(
state.unlinked.combinators,
);
final DirectiveUri uri;
if (state is LibraryImportWithFile) {
final importedLibraryKind = state.importedLibrary;
if (importedLibraryKind != null) {
final importedFile = importedLibraryKind.file;
final importedUri = importedFile.uri;
final elementFactory = linker.elementFactory;
final importedLibrary = elementFactory.libraryOfUri2(importedUri);
uri = DirectiveUriWithLibraryImpl(
relativeUriString: state.selectedUri.relativeUriStr,
relativeUri: state.selectedUri.relativeUri,
source: importedLibrary.source,
library: importedLibrary,
);
} else {
uri = DirectiveUriWithSourceImpl(
relativeUriString: state.selectedUri.relativeUriStr,
relativeUri: state.selectedUri.relativeUri,
source: state.importedSource,
);
}
} else if (state is LibraryImportWithInSummarySource) {
final importedLibrarySource = state.importedLibrarySource;
if (importedLibrarySource != null) {
final importedUri = importedLibrarySource.uri;
final elementFactory = linker.elementFactory;
final importedLibrary = elementFactory.libraryOfUri2(importedUri);
uri = DirectiveUriWithLibraryImpl(
relativeUriString: state.selectedUri.relativeUriStr,
relativeUri: state.selectedUri.relativeUri,
source: importedLibrary.source,
library: importedLibrary,
);
} else {
uri = DirectiveUriWithSourceImpl(
relativeUriString: state.selectedUri.relativeUriStr,
relativeUri: state.selectedUri.relativeUri,
source: state.importedSource,
);
}
} else {
final selectedUri = state.selectedUri;
if (selectedUri is file_state.DirectiveUriWithUri) {
uri = DirectiveUriWithRelativeUriImpl(
relativeUriString: selectedUri.relativeUriStr,
relativeUri: selectedUri.relativeUri,
);
} else if (selectedUri is file_state.DirectiveUriWithString) {
uri = DirectiveUriWithRelativeUriStringImpl(
relativeUriString: selectedUri.relativeUriStr,
);
} else {
uri = DirectiveUriImpl();
}
}
return LibraryImportElementImpl(
combinators: combinators,
importKeywordOffset: state.unlinked.importKeywordOffset,
prefix: importPrefix,
uri: uri,
)..isSynthetic = state.isSyntheticDartCore;
}
PrefixElementImpl _buildPrefix({
required String name,
required int nameOffset,
required LibraryOrAugmentationElementImpl container,
}) {
// TODO(scheglov) Make reference required.
final containerRef = container.reference!;
final reference = containerRef.getChild('@prefix').getChild(name);
final existing = reference.element;
if (existing is PrefixElementImpl) {
return existing;
} else {
final result = PrefixElementImpl(
name,
nameOffset,
reference: reference,
);
container.encloseElement(result);
return result;
}
}
/// These elements are implicitly declared in `dart:core`.
void _declareDartCoreDynamicNever() {
if (reference.name == 'dart:core') {
var dynamicRef = reference.getChild('dynamic');
dynamicRef.element = DynamicElementImpl.instance;
declare('dynamic', dynamicRef);
var neverRef = reference.getChild('Never');
neverRef.element = NeverElementImpl.instance;
declare('Never', neverRef);
}
}
static void build(Linker linker, LibraryFileKind inputLibrary) {
final elementFactory = linker.elementFactory;
final rootReference = linker.rootReference;
final libraryFile = inputLibrary.file;
final libraryUriStr = libraryFile.uriStr;
final libraryReference = rootReference.getChild(libraryUriStr);
final libraryUnitNode = libraryFile.parse();
var name = '';
var nameOffset = -1;
var nameLength = 0;
for (final directive in libraryUnitNode.directives) {
if (directive is ast.LibraryDirective) {
name = directive.name.components.map((e) => e.name).join('.');
nameOffset = directive.name.offset;
nameLength = directive.name.length;
break;
}
}
final libraryElement = LibraryElementImpl(
elementFactory.analysisContext,
elementFactory.analysisSession,
name,
nameOffset,
nameLength,
libraryUnitNode.featureSet,
);
libraryElement.isSynthetic = !libraryFile.exists;
libraryElement.languageVersion = libraryUnitNode.languageVersion!;
_bindReference(libraryReference, libraryElement);
elementFactory.setLibraryTypeSystem(libraryElement);
final unitContainerRef = libraryReference.getChild('@unit');
final linkingUnits = <LinkingUnit>[];
{
final unitElement = CompilationUnitElementImpl(
source: libraryFile.source,
librarySource: libraryFile.source,
lineInfo: libraryUnitNode.lineInfo,
);
unitElement.isSynthetic = !libraryFile.exists;
unitElement.setCodeRange(0, libraryUnitNode.length);
final unitReference = unitContainerRef.getChild(libraryFile.uriStr);
_bindReference(unitReference, unitElement);
linkingUnits.add(
DefiningLinkingUnit(
reference: unitReference,
node: libraryUnitNode,
element: unitElement,
container: libraryElement,
),
);
libraryElement.definingCompilationUnit = unitElement;
}
final parts = <PartElementImpl>[];
for (final partState in inputLibrary.parts) {
final uriState = partState.uri;
final DirectiveUri directiveUri;
if (partState is PartWithFile) {
final includedPart = partState.includedPart;
if (includedPart != null) {
final partFile = includedPart.file;
final partUnitNode = partFile.parse();
final unitElement = CompilationUnitElementImpl(
source: partFile.source,
librarySource: libraryFile.source,
lineInfo: partUnitNode.lineInfo,
);
unitElement.isSynthetic = !partFile.exists;
unitElement.uri = partFile.uriStr;
unitElement.setCodeRange(0, partUnitNode.length);
final unitReference = unitContainerRef.getChild(partFile.uriStr);
_bindReference(unitReference, unitElement);
linkingUnits.add(
LinkingUnit(
reference: unitReference,
node: partUnitNode,
container: libraryElement,
element: unitElement,
),
);
directiveUri = DirectiveUriWithUnitImpl(
relativeUriString: partState.uri.relativeUriStr,
relativeUri: partState.uri.relativeUri,
unit: unitElement,
);
} else {
directiveUri = DirectiveUriWithSourceImpl(
relativeUriString: partState.uri.relativeUriStr,
relativeUri: partState.uri.relativeUri,
source: partState.includedFile.source,
);
}
} else if (uriState is file_state.DirectiveUriWithSource) {
directiveUri = DirectiveUriWithSourceImpl(
relativeUriString: uriState.relativeUriStr,
relativeUri: uriState.relativeUri,
source: uriState.source,
);
} else if (uriState is file_state.DirectiveUriWithUri) {
directiveUri = DirectiveUriWithRelativeUriImpl(
relativeUriString: uriState.relativeUriStr,
relativeUri: uriState.relativeUri,
);
} else if (uriState is file_state.DirectiveUriWithString) {
directiveUri = DirectiveUriWithRelativeUriStringImpl(
relativeUriString: uriState.relativeUriStr,
);
} else {
directiveUri = DirectiveUriImpl();
}
parts.add(
PartElementImpl(
uri: directiveUri,
),
);
}
libraryElement.parts2 = parts;
final builder = LibraryBuilder._(
linker: linker,
kind: inputLibrary,
uri: libraryFile.uri,
reference: libraryReference,
element: libraryElement,
units: linkingUnits,
);
linker.builders[builder.uri] = builder;
}
static void _bindReference(Reference reference, ElementImpl element) {
reference.element = element;
element.reference = reference;
}
}
class LinkingUnit {
final Reference reference;
final ast.CompilationUnitImpl node;
final LibraryOrAugmentationElementImpl container;
final CompilationUnitElementImpl element;
LinkingUnit({
required this.reference,
required this.node,
required this.container,
required this.element,
});
}
class _FlushElementOffsets extends GeneralizingElementVisitor<void> {
@override
void visitElement(covariant ElementImpl element) {
element.isTempAugmentation = true;
element.nameOffset = -1;
if (element is ConstructorElementImpl) {
element.periodOffset = null;
element.nameEnd = null;
}
super.visitElement(element);
}
}
extension<T> on T? {
R? mapOrNull<R>(R Function(T) mapper) {
final self = this;
return self != null ? mapper(self) : null;
}
}