blob: e24fc84c89eb42768f491af28691a3f485102c85 [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/ast/ast.dart' show CompilationUnit;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary2/ast_binary_writer.dart';
import 'package:analyzer/src/summary2/builder/library_builder.dart';
import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
import 'package:analyzer/src/summary2/linked_bundle_context.dart';
import 'package:analyzer/src/summary2/linked_unit_context.dart';
import 'package:analyzer/src/summary2/reference.dart';
LinkResult link(
Reference rootReference,
Map<Source, Map<Source, CompilationUnit>> unitMap,
) {
var linker = Linker(rootReference);
linker.link(unitMap);
return LinkResult(linker.references, linker.libraryResults);
}
class LibraryLinkResult {
final Source source;
final Map<Source, UnitLinkResult> units;
LibraryLinkResult(this.source, this.units);
}
class Linker {
final Reference rootReference;
/// References used in all libraries being linked.
/// Element references in [LinkedNode]s are indexes in this list.
final List<Reference> references = [null];
/// The output results.
var libraryResults = <Source, LibraryLinkResult>{};
/// Libraries that are being linked, or are already linked.
final Map<Uri, LibraryBuilder> builders = {};
Linker(this.rootReference);
void addBuilder(LibraryBuilder builder) {
builders[builder.uri] = builder;
}
void addSyntheticConstructors() {
for (var library in builders.values) {
if (library is SourceLibraryBuilder) {
library.addSyntheticConstructors();
}
}
}
void buildOutlines() {
computeLibraryScopes();
resolveTypes();
addSyntheticConstructors();
}
void computeLibraryScopes() {
for (var uri in builders.keys) {
var library = builders[uri];
library.buildInitialExportScope();
}
// TODO(scheglov) process imports and exports
}
void link(Map<Source, Map<Source, CompilationUnit>> unitMap) {
var linkedBundleContext = LinkedBundleContext(references);
for (var librarySource in unitMap.keys) {
var libraryUriStr = librarySource.uri.toString();
var libraryReference = rootReference.getChild(libraryUriStr);
var unitResults = <Source, UnitLinkResult>{};
libraryResults[librarySource] = LibraryLinkResult(
librarySource,
unitResults,
);
var libraryBuilder = SourceLibraryBuilder(
this,
linkedBundleContext,
librarySource.uri,
libraryReference,
);
addBuilder(libraryBuilder);
var libraryUnits = unitMap[librarySource];
for (var unitSource in libraryUnits.keys) {
var unit = libraryUnits[unitSource];
var writer = AstBinaryWriter();
var unitData = writer.writeNode(unit);
var unitLinkResult = UnitLinkResult(writer.tokens, unitData);
unitResults[unitSource] = unitLinkResult;
var linkedUnitContext = LinkedUnitContext(
linkedBundleContext,
writer.tokens,
);
libraryBuilder.addUnit(linkedUnitContext, unitData);
}
libraryBuilder.addLocalDeclarations();
}
buildOutlines();
}
void resolveTypes() {
for (var uri in builders.keys) {
var library = builders[uri];
if (library is SourceLibraryBuilder) {
library.resolveTypes();
}
}
}
}
class LinkResult {
/// Element references in [LinkedNode]s are indexes in this list.
final List<Reference> references;
final Map<Source, LibraryLinkResult> libraries;
LinkResult(this.references, this.libraries);
}
class UnitLinkResult {
final UnlinkedTokensBuilder tokens;
final LinkedNodeBuilder node;
UnitLinkResult(this.tokens, this.node);
}