mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:58:29 +00:00
Compute exported top-level declarations.
R=brianwilkerson@google.com, paulberry@google.com BUG= Review URL: https://codereview.chromium.org/2542883003 .
This commit is contained in:
parent
1ff09b431f
commit
038cd32326
|
@ -102,6 +102,7 @@ class FileState {
|
||||||
String _transitiveSignature;
|
String _transitiveSignature;
|
||||||
|
|
||||||
List<TopLevelDeclaration> _topLevelDeclarations;
|
List<TopLevelDeclaration> _topLevelDeclarations;
|
||||||
|
List<TopLevelDeclaration> _exportedTopLevelDeclarations;
|
||||||
|
|
||||||
FileState._(this._fsState, this.path, this.uri, this.source);
|
FileState._(this._fsState, this.path, this.uri, this.source);
|
||||||
|
|
||||||
|
@ -131,6 +132,55 @@ class FileState {
|
||||||
*/
|
*/
|
||||||
List<FileState> get exportedFiles => _exportedFiles;
|
List<FileState> get exportedFiles => _exportedFiles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return [TopLevelDeclaration]s exported from the this library file.
|
||||||
|
*/
|
||||||
|
List<TopLevelDeclaration> get exportedTopLevelDeclarations {
|
||||||
|
if (_exportedTopLevelDeclarations == null) {
|
||||||
|
_exportedTopLevelDeclarations = <TopLevelDeclaration>[];
|
||||||
|
|
||||||
|
Set<FileState> seenLibraries = new Set<FileState>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute [TopLevelDeclaration]s exported from the [library].
|
||||||
|
*/
|
||||||
|
List<TopLevelDeclaration> computeExported(FileState library) {
|
||||||
|
var declarations = <String, TopLevelDeclaration>{};
|
||||||
|
if (seenLibraries.add(library)) {
|
||||||
|
// Append the library declarations.
|
||||||
|
for (TopLevelDeclaration t in library.topLevelDeclarations) {
|
||||||
|
declarations[t.name] = t;
|
||||||
|
}
|
||||||
|
for (FileState part in library.partedFiles) {
|
||||||
|
for (TopLevelDeclaration t in part.topLevelDeclarations) {
|
||||||
|
declarations[t.name] = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append the exported declarations.
|
||||||
|
for (int i = 0; i < library._exportedFiles.length; i++) {
|
||||||
|
List<TopLevelDeclaration> exported =
|
||||||
|
computeExported(library._exportedFiles[i]);
|
||||||
|
for (TopLevelDeclaration t in exported) {
|
||||||
|
if (!declarations.containsKey(t.name) &&
|
||||||
|
library._exportFilters[i].accepts(t.name)) {
|
||||||
|
declarations[t.name] = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're done with this library.
|
||||||
|
seenLibraries.remove(library);
|
||||||
|
}
|
||||||
|
|
||||||
|
return declarations.values.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
_exportedTopLevelDeclarations = computeExported(this);
|
||||||
|
}
|
||||||
|
return _exportedTopLevelDeclarations;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => uri.hashCode;
|
int get hashCode => uri.hashCode;
|
||||||
|
|
||||||
|
@ -353,18 +403,24 @@ class FileState {
|
||||||
_referencedNames = new Set<String>.from(driverUnlinkedUnit.referencedNames);
|
_referencedNames = new Set<String>.from(driverUnlinkedUnit.referencedNames);
|
||||||
_unlinked = driverUnlinkedUnit.unit;
|
_unlinked = driverUnlinkedUnit.unit;
|
||||||
_lineInfo = new LineInfo(_unlinked.lineStarts);
|
_lineInfo = new LineInfo(_unlinked.lineStarts);
|
||||||
|
_topLevelDeclarations = null;
|
||||||
|
|
||||||
|
// Prepare API signature.
|
||||||
List<int> newApiSignature = _unlinked.apiSignature;
|
List<int> newApiSignature = _unlinked.apiSignature;
|
||||||
bool apiSignatureChanged = _apiSignature != null &&
|
bool apiSignatureChanged = _apiSignature != null &&
|
||||||
!_equalByteLists(_apiSignature, newApiSignature);
|
!_equalByteLists(_apiSignature, newApiSignature);
|
||||||
_apiSignature = newApiSignature;
|
_apiSignature = newApiSignature;
|
||||||
|
|
||||||
// If the API signature changed, flush transitive signatures.
|
// The API signature changed.
|
||||||
|
// Flush transitive signatures of affected files.
|
||||||
|
// Flush exported top-level declarations of all files.
|
||||||
if (apiSignatureChanged) {
|
if (apiSignatureChanged) {
|
||||||
for (FileState file in _fsState._uriToFile.values) {
|
for (FileState file in _fsState._uriToFile.values) {
|
||||||
if (file._transitiveFiles != null &&
|
if (file._transitiveFiles != null &&
|
||||||
file._transitiveFiles.contains(this)) {
|
file._transitiveFiles.contains(this)) {
|
||||||
file._transitiveSignature = null;
|
file._transitiveSignature = null;
|
||||||
}
|
}
|
||||||
|
file._exportedTopLevelDeclarations = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,199 @@ class FileSystemStateTest {
|
||||||
provider, sourceFactory, analysisOptions, new Uint32List(0), '');
|
provider, sourceFactory, analysisOptions, new Uint32List(0), '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_exportedTopLevelDeclarations_export() {
|
||||||
|
String a = _p('/aaa/lib/a.dart');
|
||||||
|
String b = _p('/aaa/lib/b.dart');
|
||||||
|
provider.newFile(
|
||||||
|
a,
|
||||||
|
r'''
|
||||||
|
class A {}
|
||||||
|
''');
|
||||||
|
provider.newFile(
|
||||||
|
b,
|
||||||
|
r'''
|
||||||
|
export 'a.dart';
|
||||||
|
class B {}
|
||||||
|
''');
|
||||||
|
FileState file = fileSystemState.getFileForPath(b);
|
||||||
|
List<TopLevelDeclaration> declarations = file.exportedTopLevelDeclarations;
|
||||||
|
expect(declarations.map((t) => t.name), unorderedEquals(['A', 'B']));
|
||||||
|
}
|
||||||
|
|
||||||
|
test_exportedTopLevelDeclarations_export2_show() {
|
||||||
|
String a = _p('/aaa/lib/a.dart');
|
||||||
|
String b = _p('/aaa/lib/b.dart');
|
||||||
|
String c = _p('/aaa/lib/c.dart');
|
||||||
|
provider.newFile(
|
||||||
|
a,
|
||||||
|
r'''
|
||||||
|
class A1 {}
|
||||||
|
class A2 {}
|
||||||
|
class A3 {}
|
||||||
|
''');
|
||||||
|
provider.newFile(
|
||||||
|
b,
|
||||||
|
r'''
|
||||||
|
export 'a.dart' show A1, A2;
|
||||||
|
class B1 {}
|
||||||
|
class B2 {}
|
||||||
|
''');
|
||||||
|
provider.newFile(
|
||||||
|
c,
|
||||||
|
r'''
|
||||||
|
export 'b.dart' show A2, A3, B1;
|
||||||
|
class C {}
|
||||||
|
''');
|
||||||
|
_assertExportedTopLevelDeclarations(c, ['A2', 'B1', 'C']);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_exportedTopLevelDeclarations_export_flushOnChange() {
|
||||||
|
String a = _p('/aaa/lib/a.dart');
|
||||||
|
String b = _p('/aaa/lib/b.dart');
|
||||||
|
provider.newFile(
|
||||||
|
a,
|
||||||
|
r'''
|
||||||
|
class A {}
|
||||||
|
''');
|
||||||
|
provider.newFile(
|
||||||
|
b,
|
||||||
|
r'''
|
||||||
|
export 'a.dart';
|
||||||
|
class B {}
|
||||||
|
''');
|
||||||
|
|
||||||
|
// Initial exported declarations.
|
||||||
|
_assertExportedTopLevelDeclarations(b, ['A', 'B']);
|
||||||
|
|
||||||
|
// Update a.dart, so a.dart and b.dart exported declarations are flushed.
|
||||||
|
provider.newFile(a, 'class A {} class A2 {}');
|
||||||
|
fileSystemState.getFileForPath(a).refresh();
|
||||||
|
_assertExportedTopLevelDeclarations(b, ['A', 'A2', 'B']);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_exportedTopLevelDeclarations_export_hide() {
|
||||||
|
String a = _p('/aaa/lib/a.dart');
|
||||||
|
String b = _p('/aaa/lib/b.dart');
|
||||||
|
provider.newFile(
|
||||||
|
a,
|
||||||
|
r'''
|
||||||
|
class A1 {}
|
||||||
|
class A2 {}
|
||||||
|
class A3 {}
|
||||||
|
''');
|
||||||
|
provider.newFile(
|
||||||
|
b,
|
||||||
|
r'''
|
||||||
|
export 'a.dart' hide A2;
|
||||||
|
class B {}
|
||||||
|
''');
|
||||||
|
_assertExportedTopLevelDeclarations(b, ['A1', 'A3', 'B']);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_exportedTopLevelDeclarations_export_preferLocal() {
|
||||||
|
String a = _p('/aaa/lib/a.dart');
|
||||||
|
String b = _p('/aaa/lib/b.dart');
|
||||||
|
provider.newFile(
|
||||||
|
a,
|
||||||
|
r'''
|
||||||
|
class V {}
|
||||||
|
''');
|
||||||
|
provider.newFile(
|
||||||
|
b,
|
||||||
|
r'''
|
||||||
|
export 'a.dart';
|
||||||
|
int V;
|
||||||
|
''');
|
||||||
|
FileState file = fileSystemState.getFileForPath(b);
|
||||||
|
List<TopLevelDeclaration> declarations = file.exportedTopLevelDeclarations;
|
||||||
|
expect(declarations.map((t) => t.name), unorderedEquals(['V']));
|
||||||
|
expect(declarations.single.kind, TopLevelDeclarationKind.variable);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_exportedTopLevelDeclarations_export_show() {
|
||||||
|
String a = _p('/aaa/lib/a.dart');
|
||||||
|
String b = _p('/aaa/lib/b.dart');
|
||||||
|
provider.newFile(
|
||||||
|
a,
|
||||||
|
r'''
|
||||||
|
class A1 {}
|
||||||
|
class A2 {}
|
||||||
|
''');
|
||||||
|
provider.newFile(
|
||||||
|
b,
|
||||||
|
r'''
|
||||||
|
export 'a.dart' show A2;
|
||||||
|
class B {}
|
||||||
|
''');
|
||||||
|
_assertExportedTopLevelDeclarations(b, ['A2', 'B']);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_exportedTopLevelDeclarations_export_show2() {
|
||||||
|
String a = _p('/aaa/lib/a.dart');
|
||||||
|
String b = _p('/aaa/lib/b.dart');
|
||||||
|
String c = _p('/aaa/lib/c.dart');
|
||||||
|
String d = _p('/aaa/lib/d.dart');
|
||||||
|
provider.newFile(
|
||||||
|
a,
|
||||||
|
r'''
|
||||||
|
export 'b.dart' show Foo;
|
||||||
|
export 'c.dart' show Bar;
|
||||||
|
''');
|
||||||
|
provider.newFile(
|
||||||
|
b,
|
||||||
|
r'''
|
||||||
|
export 'd.dart';
|
||||||
|
''');
|
||||||
|
provider.newFile(
|
||||||
|
c,
|
||||||
|
r'''
|
||||||
|
export 'd.dart';
|
||||||
|
''');
|
||||||
|
provider.newFile(
|
||||||
|
d,
|
||||||
|
r'''
|
||||||
|
class Foo {}
|
||||||
|
class Bar {}
|
||||||
|
''');
|
||||||
|
_assertExportedTopLevelDeclarations(a, ['Foo', 'Bar']);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_exportedTopLevelDeclarations_import() {
|
||||||
|
String a = _p('/aaa/lib/a.dart');
|
||||||
|
String b = _p('/aaa/lib/b.dart');
|
||||||
|
provider.newFile(
|
||||||
|
a,
|
||||||
|
r'''
|
||||||
|
class A {}
|
||||||
|
''');
|
||||||
|
provider.newFile(
|
||||||
|
b,
|
||||||
|
r'''
|
||||||
|
import 'a.dart';
|
||||||
|
class B {}
|
||||||
|
''');
|
||||||
|
_assertExportedTopLevelDeclarations(b, ['B']);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_exportedTopLevelDeclarations_parts() {
|
||||||
|
String a = _p('/aaa/lib/a.dart');
|
||||||
|
String a2 = _p('/aaa/lib/a2.dart');
|
||||||
|
provider.newFile(
|
||||||
|
a,
|
||||||
|
r'''
|
||||||
|
library lib;
|
||||||
|
part 'a2.dart';
|
||||||
|
class A1 {}
|
||||||
|
''');
|
||||||
|
provider.newFile(
|
||||||
|
a2,
|
||||||
|
r'''
|
||||||
|
part of lib;
|
||||||
|
class A2 {}
|
||||||
|
''');
|
||||||
|
_assertExportedTopLevelDeclarations(a, ['A1', 'A2']);
|
||||||
|
}
|
||||||
|
|
||||||
test_getFileForPath_doesNotExist() {
|
test_getFileForPath_doesNotExist() {
|
||||||
String path = _p('/aaa/lib/a.dart');
|
String path = _p('/aaa/lib/a.dart');
|
||||||
FileState file = fileSystemState.getFileForPath(path);
|
FileState file = fileSystemState.getFileForPath(path);
|
||||||
|
@ -441,6 +634,12 @@ set _V3(_) {}
|
||||||
_assertFilesWithoutTransitiveSignatures([fa, fb, fc]);
|
_assertFilesWithoutTransitiveSignatures([fa, fb, fc]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _assertExportedTopLevelDeclarations(String path, List<String> expected) {
|
||||||
|
FileState file = fileSystemState.getFileForPath(path);
|
||||||
|
List<TopLevelDeclaration> declarations = file.exportedTopLevelDeclarations;
|
||||||
|
expect(declarations.map((t) => t.name), unorderedEquals(expected));
|
||||||
|
}
|
||||||
|
|
||||||
void _assertFilesWithoutTransitiveFiles(List<FileState> expected) {
|
void _assertFilesWithoutTransitiveFiles(List<FileState> expected) {
|
||||||
var actual = fileSystemState.test.filesWithoutTransitiveFiles;
|
var actual = fileSystemState.test.filesWithoutTransitiveFiles;
|
||||||
expect(actual, unorderedEquals(expected));
|
expect(actual, unorderedEquals(expected));
|
||||||
|
|
Loading…
Reference in a new issue