Add export dependencies to Kernel libraries and use them to resynthesize ExportElement(s) in Analyzer.

R=ahe@google.com, brianwilkerson@google.com, sigmund@google.com
BUG=

Review-Url: https://codereview.chromium.org/2991753002 .
This commit is contained in:
Konstantin Shcheglov 2017-07-26 12:33:16 -07:00
parent f7e81325d8
commit 8a08dbd08e
11 changed files with 98 additions and 135 deletions

View file

@ -4292,6 +4292,11 @@ class ExportElementImpl extends UriReferencedElementImpl
*/
final UnlinkedExportNonPublic _unlinkedExportNonPublic;
/**
* The kernel of the element.
*/
final kernel.LibraryDependency _kernel;
/**
* The library that is exported from this library by this export directive.
*/
@ -4314,14 +4319,24 @@ class ExportElementImpl extends UriReferencedElementImpl
ExportElementImpl(int offset)
: _unlinkedExportPublic = null,
_unlinkedExportNonPublic = null,
_kernel = null,
super(null, offset);
/**
* Initialize using the given kernel.
*/
ExportElementImpl.forKernel(LibraryElementImpl enclosingLibrary, this._kernel)
: _unlinkedExportPublic = null,
_unlinkedExportNonPublic = null,
super.forSerialized(enclosingLibrary);
/**
* Initialize using the given serialized information.
*/
ExportElementImpl.forSerialized(this._unlinkedExportPublic,
this._unlinkedExportNonPublic, LibraryElementImpl enclosingLibrary)
: super.forSerialized(enclosingLibrary);
: _kernel = null,
super.forSerialized(enclosingLibrary);
@override
List<NamespaceCombinator> get combinators {
@ -4339,9 +4354,18 @@ class ExportElementImpl extends UriReferencedElementImpl
@override
LibraryElement get exportedLibrary {
if (_unlinkedExportNonPublic != null && _exportedLibrary == null) {
LibraryElementImpl library = enclosingElement as LibraryElementImpl;
_exportedLibrary = library.resynthesizerContext.buildExportedLibrary(uri);
if (_exportedLibrary == null) {
if (_kernel != null) {
Uri exportedUri = _kernel.targetLibrary.importUri;
String exportedUriStr = exportedUri.toString();
LibraryElementImpl library = enclosingElement as LibraryElementImpl;
_exportedLibrary = library._kernelContext.getLibrary(exportedUriStr);
}
if (_unlinkedExportNonPublic != null) {
LibraryElementImpl library = enclosingElement as LibraryElementImpl;
_exportedLibrary =
library.resynthesizerContext.buildExportedLibrary(uri);
}
}
return _exportedLibrary;
}
@ -6235,28 +6259,37 @@ class LibraryElementImpl extends ElementImpl implements LibraryElement {
@override
List<ExportElement> get exports {
if (_unlinkedDefiningUnit != null && _exports == null) {
List<UnlinkedExportNonPublic> unlinkedNonPublicExports =
_unlinkedDefiningUnit.exports;
List<UnlinkedExportPublic> unlinkedPublicExports =
_unlinkedDefiningUnit.publicNamespace.exports;
assert(
_unlinkedDefiningUnit.exports.length == unlinkedPublicExports.length);
int length = unlinkedNonPublicExports.length;
if (length != 0) {
List<ExportElement> exports = new List<ExportElement>();
for (int i = 0; i < length; i++) {
UnlinkedExportPublic serializedExportPublic =
unlinkedPublicExports[i];
UnlinkedExportNonPublic serializedExportNonPublic =
unlinkedNonPublicExports[i];
ExportElementImpl exportElement = new ExportElementImpl.forSerialized(
serializedExportPublic, serializedExportNonPublic, library);
exports.add(exportElement);
if (_exports == null) {
if (_kernelContext != null) {
_exports = _kernelContext.library.dependencies
.where((k) => k.isExport)
.map((k) => new ExportElementImpl.forKernel(this, k))
.toList(growable: false);
}
if (_unlinkedDefiningUnit != null) {
List<UnlinkedExportNonPublic> unlinkedNonPublicExports =
_unlinkedDefiningUnit.exports;
List<UnlinkedExportPublic> unlinkedPublicExports =
_unlinkedDefiningUnit.publicNamespace.exports;
assert(_unlinkedDefiningUnit.exports.length ==
unlinkedPublicExports.length);
int length = unlinkedNonPublicExports.length;
if (length != 0) {
List<ExportElement> exports = new List<ExportElement>();
for (int i = 0; i < length; i++) {
UnlinkedExportPublic serializedExportPublic =
unlinkedPublicExports[i];
UnlinkedExportNonPublic serializedExportNonPublic =
unlinkedNonPublicExports[i];
ExportElementImpl exportElement =
new ExportElementImpl.forSerialized(
serializedExportPublic, serializedExportNonPublic, library);
exports.add(exportElement);
}
_exports = exports;
} else {
_exports = const <ExportElement>[];
}
_exports = exports;
} else {
_exports = const <ExportElement>[];
}
}
return _exports ?? const <ExportElement>[];

View file

@ -468,16 +468,6 @@ class ResynthesizeKernelStrongTest extends ResynthesizeTest {
await super.test_executable_parameter_type_typedef();
}
@failingTest
test_export_class() async {
await super.test_export_class();
}
@failingTest
test_export_class_type_alias() async {
await super.test_export_class_type_alias();
}
@failingTest
test_export_configurations_useDefault() async {
await super.test_export_configurations_useDefault();
@ -493,16 +483,6 @@ class ResynthesizeKernelStrongTest extends ResynthesizeTest {
await super.test_export_configurations_useSecond();
}
@failingTest
test_export_function() async {
await super.test_export_function();
}
@failingTest
test_export_getter() async {
await super.test_export_getter();
}
@failingTest
test_export_hide() async {
await super.test_export_hide();
@ -513,36 +493,11 @@ class ResynthesizeKernelStrongTest extends ResynthesizeTest {
await super.test_export_multiple_combinators();
}
@failingTest
test_export_setter() async {
await super.test_export_setter();
}
@failingTest
test_export_show() async {
await super.test_export_show();
}
@failingTest
test_export_typedef() async {
await super.test_export_typedef();
}
@failingTest
test_export_variable() async {
await super.test_export_variable();
}
@failingTest
test_export_variable_const() async {
await super.test_export_variable_const();
}
@failingTest
test_export_variable_final() async {
await super.test_export_variable_final();
}
@failingTest
test_exportImport_configurations_useDefault() async {
await super.test_exportImport_configurations_useDefault();
@ -553,11 +508,6 @@ class ResynthesizeKernelStrongTest extends ResynthesizeTest {
await super.test_exportImport_configurations_useFirst();
}
@failingTest
test_exports() async {
await super.test_exports();
}
@failingTest
test_field_covariant() async {
await super.test_field_covariant();
@ -588,11 +538,6 @@ class ResynthesizeKernelStrongTest extends ResynthesizeTest {
await super.test_function_documented();
}
@failingTest
test_function_entry_point_in_export() async {
await super.test_function_entry_point_in_export();
}
@failingTest
test_function_entry_point_in_export_hidden() async {
await super.test_function_entry_point_in_export_hidden();
@ -808,36 +753,11 @@ class ResynthesizeKernelStrongTest extends ResynthesizeTest {
await super.test_library_documented_stars();
}
@failingTest
test_main_class_alias_via_export() async {
await super.test_main_class_alias_via_export();
}
@failingTest
test_main_class_via_export() async {
await super.test_main_class_via_export();
}
@failingTest
test_main_getter_via_export() async {
await super.test_main_getter_via_export();
}
@failingTest
test_main_typedef() async {
await super.test_main_typedef();
}
@failingTest
test_main_typedef_via_export() async {
await super.test_main_typedef_via_export();
}
@failingTest
test_main_variable_via_export() async {
await super.test_main_variable_via_export();
}
@failingTest
test_metadata_classDeclaration() async {
await super.test_metadata_classDeclaration();
@ -1365,11 +1285,6 @@ class ResynthesizeKernelStrongTest extends ResynthesizeTest {
await super.test_unresolved_annotation_unnamedConstructorCall_noClass();
}
@failingTest
test_unresolved_export() async {
await super.test_unresolved_export();
}
@failingTest
test_unresolved_import() async {
await super.test_unresolved_import();

View file

@ -37,7 +37,7 @@ import 'builder.dart'
abstract class LibraryBuilder<T extends TypeBuilder, R> extends Builder {
final Scope scope;
final Scope exports;
final Scope exportScope;
final ScopeBuilder scopeBuilder;
@ -56,11 +56,11 @@ abstract class LibraryBuilder<T extends TypeBuilder, R> extends Builder {
bool mayImplementRestrictedTypes = false;
LibraryBuilder(Uri fileUri, this.scope, this.exports)
LibraryBuilder(Uri fileUri, this.scope, this.exportScope)
: fileUri = fileUri,
relativeFileUri = relativizeUri(fileUri),
scopeBuilder = new ScopeBuilder(scope),
exportScopeBuilder = new ScopeBuilder(exports),
exportScopeBuilder = new ScopeBuilder(exportScope),
super(null, -1, fileUri);
Loader get loader;
@ -103,7 +103,7 @@ abstract class LibraryBuilder<T extends TypeBuilder, R> extends Builder {
if (name.startsWith("_")) return false;
if (member is PrefixBuilder) return false;
Map<String, Builder> map =
member.isSetter ? exports.setters : exports.local;
member.isSetter ? exportScope.setters : exportScope.local;
Builder existing = map[name];
if (existing == member) return false;
if (existing != null) {
@ -149,8 +149,8 @@ abstract class LibraryBuilder<T extends TypeBuilder, R> extends Builder {
-1,
null);
}
Builder cls =
(bypassLibraryPrivacy ? scope : exports).lookup(className, -1, null);
Builder cls = (bypassLibraryPrivacy ? scope : exportScope)
.lookup(className, -1, null);
if (cls is ClassBuilder) {
// TODO(ahe): This code is similar to code in `endNewExpression` in
// `body_builder.dart`, try to share it.

View file

@ -9,7 +9,7 @@ import 'builder.dart' show Builder, LibraryBuilder, Scope;
class PrefixBuilder extends Builder {
final String name;
final Scope exports = new Scope.top();
final Scope exportScope = new Scope.top();
final LibraryBuilder parent;
@ -24,7 +24,7 @@ class PrefixBuilder extends Builder {
super(parent, charOffset, parent.fileUri);
Builder lookup(String name, int charOffset, Uri fileUri) {
return exports.lookup(name, charOffset, fileUri);
return exportScope.lookup(name, charOffset, fileUri);
}
@override

View file

@ -44,13 +44,13 @@ class Import {
new PrefixBuilder(this.prefix, deferred, importer, prefixCharOffset);
add = (String name, Builder member) {
if (member.isSetter) {
prefix.exports.setters[name] = member;
prefix.exportScope.setters[name] = member;
} else {
prefix.exports.local[name] = member;
prefix.exportScope.local[name] = member;
}
};
}
imported.exports.forEach((String name, Builder member) {
imported.exportScope.forEach((String name, Builder member) {
if (combinators != null) {
for (Combinator combinator in combinators) {
if (combinator.isShow && !combinator.names.contains(name)) return;

View file

@ -1685,7 +1685,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
builder = scope.lookup(prefix, beginToken.charOffset, uri);
}
if (builder is PrefixBuilder) {
name = scopeLookup(builder.exports, suffix, beginToken,
name = scopeLookup(builder.exportScope, suffix, beginToken,
isQualified: true, prefix: builder);
} else {
push(const InvalidType());
@ -2137,7 +2137,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
var prefix = type[0];
identifier = type[1];
if (prefix is PrefixBuilder) {
type = scopeLookup(prefix.exports, identifier.name, start,
type = scopeLookup(prefix.exportScope, identifier.name, start,
isQualified: true, prefix: prefix);
identifier = null;
} else if (prefix is TypeDeclarationAccessor) {

View file

@ -511,7 +511,7 @@ class SendAccessor extends IncompleteSend {
"Library prefix '${prefix.name}' can't be used with null-aware "
"operator.\nTry removing '?'.");
}
receiver = helper.scopeLookup(prefix.exports, name.name, token,
receiver = helper.scopeLookup(prefix.exportScope, name.name, token,
isQualified: true, prefix: prefix);
return helper.finishSend(receiver, arguments, offsetForToken(token));
}
@ -583,7 +583,7 @@ class IncompletePropertyAccessor extends IncompleteSend {
"Library prefix '${prefix.name}' can't be used with null-aware "
"operator.\nTry removing '?'.");
}
return helper.scopeLookup(prefix.exports, name.name, token,
return helper.scopeLookup(prefix.exportScope, name.name, token,
isQualified: true, prefix: prefix);
}

View file

@ -5,6 +5,7 @@
library fasta.kernel_library_builder;
import 'package:front_end/src/fasta/dill/dill_library_builder.dart';
import 'package:front_end/src/fasta/export.dart';
import 'package:front_end/src/fasta/import.dart';
import 'package:kernel/ast.dart';
@ -731,6 +732,18 @@ class KernelLibraryBuilder
new LibraryDependency.import(importedLibrary, name: import.prefix));
}
}
for (Export import in exports) {
var exportedBuilder = import.exported;
Library exportedLibrary;
if (exportedBuilder is DillLibraryBuilder) {
exportedLibrary = exportedBuilder.library;
} else if (exportedBuilder is KernelLibraryBuilder) {
exportedLibrary = exportedBuilder.library;
}
if (exportedLibrary != null) {
library.addDependency(new LibraryDependency.export(exportedLibrary));
}
}
library.name = name;
library.procedures.sort(compareProcedures);
return library;
@ -794,7 +807,7 @@ class KernelLibraryBuilder
// Handles the case where the same prefix is used for different
// imports.
return builder
..exports.merge(other.exports,
..exportScope.merge(other.exportScope,
(String name, Builder existing, Builder member) {
return buildAmbiguousBuilder(name, existing, member, charOffset,
isExport: isExport, isImport: isImport);

View file

@ -68,6 +68,8 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R>
final List<Import> imports = <Import>[];
final List<Export> exports = <Export>[];
final Scope importScope;
final Uri fileUri;
@ -151,9 +153,9 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R>
void addExport(List<MetadataBuilder> metadata, String uri,
Unhandled conditionalUris, List<Combinator> combinators, int charOffset) {
loader
.read(resolve(uri), charOffset, accessor: this)
.addExporter(this, combinators, charOffset);
var exportedLibrary = loader.read(resolve(uri), charOffset, accessor: this);
exportedLibrary.addExporter(this, combinators, charOffset);
exports.add(new Export(this, exportedLibrary, combinators, charOffset));
}
void addImport(
@ -337,7 +339,7 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R>
fileUri);
}
return existing
..exports.merge(builder.exports,
..exportScope.merge(builder.exportScope,
(String name, Builder existing, Builder member) {
return buildAmbiguousBuilder(name, existing, member, charOffset);
});
@ -498,7 +500,7 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R>
import.finalizeImports(this);
}
if (!explicitCoreImport) {
loader.coreLibrary.exports.forEach((String name, Builder member) {
loader.coreLibrary.exportScope.forEach((String name, Builder member) {
addToScope(name, member, -1, true);
});
}

View file

@ -217,7 +217,7 @@ class SourceLoader<L> extends Loader<L> {
both.add(exported);
}
for (Export export in exported.exporters) {
exported.exports.forEach(export.addToExportScope);
exported.exportScope.forEach(export.addToExportScope);
}
}
bool wasChanged = false;
@ -226,7 +226,7 @@ class SourceLoader<L> extends Loader<L> {
for (SourceLibraryBuilder exported in both) {
for (Export export in exported.exporters) {
SourceLibraryBuilder exporter = export.exporter;
exported.exports.forEach((String name, Builder member) {
exported.exportScope.forEach((String name, Builder member) {
if (exporter.addToExportScope(name, member)) {
wasChanged = true;
}
@ -255,7 +255,7 @@ class SourceLoader<L> extends Loader<L> {
}
});
List<String> exports = <String>[];
library.exports.forEach((String name, Builder member) {
library.exportScope.forEach((String name, Builder member) {
while (member != null) {
if (!members.contains(member)) {
exports.add(name);

View file

@ -285,7 +285,7 @@ class KernelDriver {
DillLibraryBuilder exportedLibrary =
dillTarget.loader.read(export.library.uri, -1, accessor: library);
if (exportedLibrary != null) {
exportedLibrary.exports.forEach((name, member) {
exportedLibrary.exportScope.forEach((name, member) {
if (export.isExposed(name) &&
library.addToExportScope(name, member)) {
wasChanged = true;