blob: 46083a5c3ea185bd0b9f7b29bc2d3e392b7cf0b7 [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 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:analyzer/src/dart/micro/resolve_file.dart';
import 'package:analyzer/src/dart/micro/utils.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:linter/src/lint_codes.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../resolution/node_text_expectations.dart';
import 'file_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(FileResolver_changeFiles_Test);
defineReflectiveTests(FileResolverTest);
defineReflectiveTests(UpdateNodeTextExpectations);
});
}
@reflectiveTest
class FileResolver_changeFiles_Test extends FileResolutionTest {
test_changeFile_refreshedFiles() async {
var a = newFile('$testPackageLibPath/a.dart', r'''
class A {}
''');
newFile('$testPackageLibPath/b.dart', r'''
class B {}
''');
var c = newFile('$testPackageLibPath/c.dart', r'''
import 'a.dart';
import 'b.dart';
''');
// First time we refresh everything.
await resolveFile(c);
assertStateString(r'''
files
/workspace/dart/test/lib/a.dart
uri: package:dart.test/a.dart
current
id: file_0
kind: library_0
libraryImports
library_3 dart:core synthetic
fileKinds: library_0
cycle_0
dependencies: dart:core
libraries: library_0
apiSignature_0
users: cycle_2
referencingFiles: file_2
unlinkedKey: k00
unlinkedGet: []
unlinkedPut: [k00]
/workspace/dart/test/lib/b.dart
uri: package:dart.test/b.dart
current
id: file_1
kind: library_1
libraryImports
library_3 dart:core synthetic
fileKinds: library_1
cycle_1
dependencies: dart:core
libraries: library_1
apiSignature_1
users: cycle_2
referencingFiles: file_2
unlinkedKey: k01
unlinkedGet: []
unlinkedPut: [k01]
/workspace/dart/test/lib/c.dart
uri: package:dart.test/c.dart
current
id: file_2
kind: library_2
libraryImports
library_0
library_1
library_3 dart:core synthetic
fileKinds: library_2
cycle_2
dependencies: cycle_0 cycle_1 dart:core
libraries: library_2
apiSignature_2
unlinkedKey: k02
unlinkedGet: []
unlinkedPut: [k02]
libraryCycles
/workspace/dart/test/lib/a.dart
current: cycle_0
key: k03
get: []
put: [k03]
/workspace/dart/test/lib/b.dart
current: cycle_1
key: k04
get: []
put: [k04]
/workspace/dart/test/lib/c.dart
current: cycle_2
key: k05
get: []
put: [k05]
elementFactory
hasElement
package:dart.test/a.dart
package:dart.test/b.dart
package:dart.test/c.dart
unlinkedUnitStore
1: [k00, k01, k02, k06, k07, k08, k09, k10]
byteStore
1: [k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k10, k11]
''');
// Without changes we refresh nothing.
await resolveFile(c);
assertStateString(r'''
files
/workspace/dart/test/lib/a.dart
uri: package:dart.test/a.dart
current
id: file_0
kind: library_0
libraryImports
library_3 dart:core synthetic
fileKinds: library_0
cycle_0
dependencies: dart:core
libraries: library_0
apiSignature_0
users: cycle_2
referencingFiles: file_2
unlinkedKey: k00
unlinkedGet: []
unlinkedPut: [k00]
/workspace/dart/test/lib/b.dart
uri: package:dart.test/b.dart
current
id: file_1
kind: library_1
libraryImports
library_3 dart:core synthetic
fileKinds: library_1
cycle_1
dependencies: dart:core
libraries: library_1
apiSignature_1
users: cycle_2
referencingFiles: file_2
unlinkedKey: k01
unlinkedGet: []
unlinkedPut: [k01]
/workspace/dart/test/lib/c.dart
uri: package:dart.test/c.dart
current
id: file_2
kind: library_2
libraryImports
library_0
library_1
library_3 dart:core synthetic
fileKinds: library_2
cycle_2
dependencies: cycle_0 cycle_1 dart:core
libraries: library_2
apiSignature_2
unlinkedKey: k02
unlinkedGet: []
unlinkedPut: [k02]
libraryCycles
/workspace/dart/test/lib/a.dart
current: cycle_0
key: k03
get: []
put: [k03]
/workspace/dart/test/lib/b.dart
current: cycle_1
key: k04
get: []
put: [k04]
/workspace/dart/test/lib/c.dart
current: cycle_2
key: k05
get: []
put: [k05]
elementFactory
hasElement
package:dart.test/a.dart
package:dart.test/b.dart
package:dart.test/c.dart
unlinkedUnitStore
1: [k00, k01, k02, k06, k07, k08, k09, k10]
byteStore
1: [k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k10, k11]
''');
// We already know a.dart, refresh nothing.
await resolveFile(a);
assertStateString(r'''
files
/workspace/dart/test/lib/a.dart
uri: package:dart.test/a.dart
current
id: file_0
kind: library_0
libraryImports
library_3 dart:core synthetic
fileKinds: library_0
cycle_0
dependencies: dart:core
libraries: library_0
apiSignature_0
users: cycle_2
referencingFiles: file_2
unlinkedKey: k00
unlinkedGet: []
unlinkedPut: [k00]
/workspace/dart/test/lib/b.dart
uri: package:dart.test/b.dart
current
id: file_1
kind: library_1
libraryImports
library_3 dart:core synthetic
fileKinds: library_1
cycle_1
dependencies: dart:core
libraries: library_1
apiSignature_1
users: cycle_2
referencingFiles: file_2
unlinkedKey: k01
unlinkedGet: []
unlinkedPut: [k01]
/workspace/dart/test/lib/c.dart
uri: package:dart.test/c.dart
current
id: file_2
kind: library_2
libraryImports
library_0
library_1
library_3 dart:core synthetic
fileKinds: library_2
cycle_2
dependencies: cycle_0 cycle_1 dart:core
libraries: library_2
apiSignature_2
unlinkedKey: k02
unlinkedGet: []
unlinkedPut: [k02]
libraryCycles
/workspace/dart/test/lib/a.dart
current: cycle_0
key: k03
get: []
put: [k03]
/workspace/dart/test/lib/b.dart
current: cycle_1
key: k04
get: []
put: [k04]
/workspace/dart/test/lib/c.dart
current: cycle_2
key: k05
get: []
put: [k05]
elementFactory
hasElement
package:dart.test/a.dart
package:dart.test/b.dart
package:dart.test/c.dart
unlinkedUnitStore
1: [k00, k01, k02, k06, k07, k08, k09, k10]
byteStore
1: [k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k10, k11]
''');
// Change a.dart, discard data for a.dart and c.dart, but not b.dart
fileResolver.changeFiles([a.path]);
assertStateString(r'''
files
/workspace/dart/test/lib/a.dart
uri: package:dart.test/a.dart
unlinkedGet: []
unlinkedPut: [k00]
/workspace/dart/test/lib/b.dart
uri: package:dart.test/b.dart
current
id: file_1
kind: library_1
libraryImports
library_3 dart:core synthetic
fileKinds: library_1
cycle_1
dependencies: dart:core
libraries: library_1
apiSignature_1
unlinkedKey: k01
unlinkedGet: []
unlinkedPut: [k01]
/workspace/dart/test/lib/c.dart
uri: package:dart.test/c.dart
unlinkedGet: []
unlinkedPut: [k02]
libraryCycles
/workspace/dart/test/lib/a.dart
get: []
put: [k03]
/workspace/dart/test/lib/b.dart
current: cycle_1
key: k04
get: []
put: [k04]
/workspace/dart/test/lib/c.dart
get: []
put: [k05]
elementFactory
hasElement
package:dart.test/b.dart
unlinkedUnitStore
1: [k01, k06, k07, k08, k09, k10]
byteStore
1: [k01, k04, k06, k07, k08, k09, k10, k11]
''');
// Resolve, read again a.dart and c.dart
await resolveFile(c);
assertStateString(r'''
files
/workspace/dart/test/lib/a.dart
uri: package:dart.test/a.dart
current
id: file_8
kind: library_8
libraryImports
library_3 dart:core synthetic
fileKinds: library_8
cycle_4
dependencies: dart:core
libraries: library_8
apiSignature_0
users: cycle_5
referencingFiles: file_9
unlinkedKey: k00
unlinkedGet: []
unlinkedPut: [k00, k00]
/workspace/dart/test/lib/b.dart
uri: package:dart.test/b.dart
current
id: file_1
kind: library_1
libraryImports
library_3 dart:core synthetic
fileKinds: library_1
cycle_1
dependencies: dart:core
libraries: library_1
apiSignature_1
users: cycle_5
referencingFiles: file_9
unlinkedKey: k01
unlinkedGet: []
unlinkedPut: [k01]
/workspace/dart/test/lib/c.dart
uri: package:dart.test/c.dart
current
id: file_9
kind: library_9
libraryImports
library_8
library_1
library_3 dart:core synthetic
fileKinds: library_9
cycle_5
dependencies: cycle_1 cycle_4 dart:core
libraries: library_9
apiSignature_2
unlinkedKey: k02
unlinkedGet: []
unlinkedPut: [k02, k02]
libraryCycles
/workspace/dart/test/lib/a.dart
current: cycle_4
key: k03
get: []
put: [k03, k03]
/workspace/dart/test/lib/b.dart
current: cycle_1
key: k04
get: []
put: [k04]
/workspace/dart/test/lib/c.dart
current: cycle_5
key: k05
get: []
put: [k05, k05]
elementFactory
hasElement
package:dart.test/a.dart
package:dart.test/b.dart
package:dart.test/c.dart
unlinkedUnitStore
1: [k00, k01, k02, k06, k07, k08, k09, k10]
byteStore
1: [k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k10, k11]
''');
}
test_changeFile_resolution() async {
var a = newFile('/workspace/dart/test/lib/a.dart', r'''
class A {}
''');
var b = newFile('/workspace/dart/test/lib/b.dart', r'''
import 'a.dart';
void f(A a, B b) {}
''');
result = await resolveFile(b);
assertErrorsInResolvedUnit(result, [
error(CompileTimeErrorCode.UNDEFINED_CLASS, 29, 1),
]);
newFile(a.path, r'''
class A {}
class B {}
''');
fileResolver.changeFiles([a.path]);
result = await resolveFile(b);
assertErrorsInResolvedUnit(result, []);
}
test_changeFile_resolution_flushInheritanceManager() async {
var a = newFile('/workspace/dart/test/lib/a.dart', r'''
class A {
final int foo = 0;
}
''');
var b = newFile('/workspace/dart/test/lib/b.dart', r'''
import 'a.dart';
void f(A a) {
a.foo = 1;
}
''');
result = await resolveFile(b);
assertErrorsInResolvedUnit(result, [
error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 36, 3),
]);
newFile(a.path, r'''
class A {
int foo = 0;
}
''');
fileResolver.changeFiles([a.path]);
result = await resolveFile(b);
assertErrorsInResolvedUnit(result, []);
}
test_changeFile_resolution_missingChangeFileForPart() async {
var a = newFile('/workspace/dart/test/lib/a.dart', r'''
part 'b.dart';
var b = B(0);
''');
var b = newFile('/workspace/dart/test/lib/b.dart', r'''
part of 'a.dart';
''');
result = await resolveFile(a);
assertErrorsInResolvedUnit(result, [
error(CompileTimeErrorCode.UNDEFINED_FUNCTION, 24, 1),
]);
// Update a.dart, and notify the resolver. We need this to have at least
// one change, so that we decided to rebuild the library summary.
newFile(a.path, r'''
part 'b.dart';
var b = B(1);
''');
fileResolver.changeFiles([a.path]);
// Update b.dart, but do not notify the resolver.
// If we try to read it now, it will throw.
newFile(b.path, r'''
part of 'a.dart';
class B {
B(int _);
}
''');
try {
await resolveFile(a);
fail('Expected StateError');
} on StateError {
// OK
}
// Notify the resolver about b.dart, it is OK now.
fileResolver.changeFiles([b.path]);
result = await resolveFile(a);
assertErrorsInResolvedUnit(result, []);
}
test_changePartFile_refreshedFiles() async {
newFile('/workspace/dart/test/lib/a.dart', r'''
part 'b.dart';
class A {}
''');
var b = newFile('/workspace/dart/test/lib/b.dart', r'''
part of 'a.dart';
class B extends A {}
''');
// First time we refresh everything.
await resolveFile(b);
assertStateString(r'''
files
/workspace/dart/test/lib/a.dart
uri: package:dart.test/a.dart
current
id: file_0
kind: library_0
libraryImports
library_2 dart:core synthetic
partIncludes
partOfUriKnown_1
fileKinds: library_0 partOfUriKnown_1
cycle_0
dependencies: dart:core
libraries: library_0
apiSignature_0
unlinkedKey: k00
unlinkedGet: []
unlinkedPut: [k00]
/workspace/dart/test/lib/b.dart
uri: package:dart.test/b.dart
current
id: file_1
kind: partOfUriKnown_1
uriFile: file_0
library: library_0
referencingFiles: file_0
unlinkedKey: k01
unlinkedGet: []
unlinkedPut: [k01]
libraryCycles
/workspace/dart/test/lib/a.dart
current: cycle_0
key: k02
get: []
put: [k02]
elementFactory
hasElement
package:dart.test/a.dart
unlinkedUnitStore
1: [k00, k01, k03, k04, k05, k06, k07]
byteStore
1: [k00, k01, k02, k03, k04, k05, k06, k07, k08]
''');
// Change b.dart, discard both b.dart and a.dart
fileResolver.changeFiles([b.path]);
assertStateString(r'''
files
/workspace/dart/test/lib/a.dart
uri: package:dart.test/a.dart
unlinkedGet: []
unlinkedPut: [k00]
/workspace/dart/test/lib/b.dart
uri: package:dart.test/b.dart
unlinkedGet: []
unlinkedPut: [k01]
libraryCycles
/workspace/dart/test/lib/a.dart
get: []
put: [k02]
elementFactory
unlinkedUnitStore
1: [k03, k04, k05, k06, k07]
byteStore
1: [k03, k04, k05, k06, k07, k08]
''');
// Resolve, read a.dart and b.dart
await resolveFile(b);
assertStateString(r'''
files
/workspace/dart/test/lib/a.dart
uri: package:dart.test/a.dart
current
id: file_7
kind: library_7
libraryImports
library_2 dart:core synthetic
partIncludes
partOfUriKnown_8
fileKinds: library_7 partOfUriKnown_8
cycle_2
dependencies: dart:core
libraries: library_7
apiSignature_0
unlinkedKey: k00
unlinkedGet: []
unlinkedPut: [k00, k00]
/workspace/dart/test/lib/b.dart
uri: package:dart.test/b.dart
current
id: file_8
kind: partOfUriKnown_8
uriFile: file_7
library: library_7
referencingFiles: file_7
unlinkedKey: k01
unlinkedGet: []
unlinkedPut: [k01, k01]
libraryCycles
/workspace/dart/test/lib/a.dart
current: cycle_2
key: k02
get: []
put: [k02, k02]
elementFactory
hasElement
package:dart.test/a.dart
unlinkedUnitStore
1: [k00, k01, k03, k04, k05, k06, k07]
byteStore
1: [k00, k01, k02, k03, k04, k05, k06, k07, k08]
''');
}
test_changePartFile_refreshedFiles_transitive() async {
newFile('/workspace/dart/test/lib/a.dart', r'''
part 'b.dart';
class A {}
''');
var b = newFile('/workspace/dart/test/lib/b.dart', r'''
part of 'a.dart';
class B extends A {}
''');
var c = newFile('/workspace/dart/test/lib/c.dart', r'''
import 'a.dart';
''');
await resolveFile(c);
assertStateString(r'''
files
/workspace/dart/test/lib/a.dart
uri: package:dart.test/a.dart
current
id: file_0
kind: library_0
libraryImports
library_3 dart:core synthetic
partIncludes
partOfUriKnown_1
fileKinds: library_0 partOfUriKnown_1
cycle_0
dependencies: dart:core
libraries: library_0
apiSignature_0
users: cycle_1
referencingFiles: file_2
unlinkedKey: k00
unlinkedGet: []
unlinkedPut: [k00]
/workspace/dart/test/lib/b.dart
uri: package:dart.test/b.dart
current
id: file_1
kind: partOfUriKnown_1
uriFile: file_0
library: library_0
referencingFiles: file_0
unlinkedKey: k01
unlinkedGet: []
unlinkedPut: [k01]
/workspace/dart/test/lib/c.dart
uri: package:dart.test/c.dart
current
id: file_2
kind: library_2
libraryImports
library_0
library_3 dart:core synthetic
fileKinds: library_2
cycle_1
dependencies: cycle_0 dart:core
libraries: library_2
apiSignature_1
unlinkedKey: k02
unlinkedGet: []
unlinkedPut: [k02]
libraryCycles
/workspace/dart/test/lib/a.dart
current: cycle_0
key: k03
get: []
put: [k03]
/workspace/dart/test/lib/c.dart
current: cycle_1
key: k04
get: []
put: [k04]
elementFactory
hasElement
package:dart.test/a.dart
package:dart.test/c.dart
unlinkedUnitStore
1: [k00, k01, k02, k05, k06, k07, k08, k09]
byteStore
1: [k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k10]
''');
// Should invalidate a.dart, b.dart, c.dart
fileResolver.changeFiles([b.path]);
assertStateString(r'''
files
/workspace/dart/test/lib/a.dart
uri: package:dart.test/a.dart
unlinkedGet: []
unlinkedPut: [k00]
/workspace/dart/test/lib/b.dart
uri: package:dart.test/b.dart
unlinkedGet: []
unlinkedPut: [k01]
/workspace/dart/test/lib/c.dart
uri: package:dart.test/c.dart
unlinkedGet: []
unlinkedPut: [k02]
libraryCycles
/workspace/dart/test/lib/a.dart
get: []
put: [k03]
/workspace/dart/test/lib/c.dart
get: []
put: [k04]
elementFactory
unlinkedUnitStore
1: [k05, k06, k07, k08, k09]
byteStore
1: [k05, k06, k07, k08, k09, k10]
''');
// Read again a.dart, b.dart, c.dart
await resolveFile(c);
assertStateString(r'''
files
/workspace/dart/test/lib/a.dart
uri: package:dart.test/a.dart
current
id: file_8
kind: library_8
libraryImports
library_3 dart:core synthetic
partIncludes
partOfUriKnown_9
fileKinds: library_8 partOfUriKnown_9
cycle_3
dependencies: dart:core
libraries: library_8
apiSignature_0
users: cycle_4
referencingFiles: file_10
unlinkedKey: k00
unlinkedGet: []
unlinkedPut: [k00, k00]
/workspace/dart/test/lib/b.dart
uri: package:dart.test/b.dart
current
id: file_9
kind: partOfUriKnown_9
uriFile: file_8
library: library_8
referencingFiles: file_8
unlinkedKey: k01
unlinkedGet: []
unlinkedPut: [k01, k01]
/workspace/dart/test/lib/c.dart
uri: package:dart.test/c.dart
current
id: file_10
kind: library_10
libraryImports
library_8
library_3 dart:core synthetic
fileKinds: library_10
cycle_4
dependencies: cycle_3 dart:core
libraries: library_10
apiSignature_1
unlinkedKey: k02
unlinkedGet: []
unlinkedPut: [k02, k02]
libraryCycles
/workspace/dart/test/lib/a.dart
current: cycle_3
key: k03
get: []
put: [k03, k03]
/workspace/dart/test/lib/c.dart
current: cycle_4
key: k04
get: []
put: [k04, k04]
elementFactory
hasElement
package:dart.test/a.dart
package:dart.test/c.dart
unlinkedUnitStore
1: [k00, k01, k02, k05, k06, k07, k08, k09]
byteStore
1: [k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k10]
''');
}
}
@reflectiveTest
class FileResolverTest extends FileResolutionTest {
test_analysisOptions_default_fromPackageUri() async {
newFile('/workspace/dart/analysis_options/lib/default.yaml', r'''
analyzer:
strong-mode:
implicit-casts: false
''');
await assertErrorsInCode(
r'''
num a = 0;
int b = a;
''',
[error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 19, 1)],
);
}
test_analysisOptions_file_inPackage() async {
newAnalysisOptionsYamlFile('/workspace/dart/test', r'''
analyzer:
strong-mode:
implicit-casts: false
''');
await assertErrorsInCode(
r'''
num a = 0;
int b = a;
''',
[error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 19, 1)],
);
}
test_analysisOptions_file_inThirdParty() async {
newFile('/workspace/dart/analysis_options/lib/third_party.yaml', r'''
analyzer:
strong-mode:
implicit-casts: false
''');
newAnalysisOptionsYamlFile('/workspace/third_party/dart/aaa', r'''
analyzer:
strong-mode:
implicit-casts: true
''');
var aPath = convertPath('/workspace/third_party/dart/aaa/lib/a.dart');
await assertErrorsInFile(
aPath,
r'''
num a = 0;
int b = a;
''',
[error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 19, 1)],
);
}
test_analysisOptions_file_inThirdPartyDartLang() async {
newFile('/workspace/dart/analysis_options/lib/third_party.yaml', r'''
analyzer:
strong-mode:
implicit-casts: false
''');
newAnalysisOptionsYamlFile('/workspace/third_party/dart_lang/aaa', r'''
analyzer:
strong-mode:
implicit-casts: true
''');
var aPath = convertPath('/workspace/third_party/dart_lang/aaa/lib/a.dart');
await assertErrorsInFile(
aPath,
r'''
num a = 0;
int b = a;
''',
[error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 19, 1)],
);
}
test_analysisOptions_lints() async {
newFile('/workspace/dart/analysis_options/lib/default.yaml', r'''
linter:
rules:
- omit_local_variable_types
''');
await assertErrorsInCode(
r'''
main() {
int a = 0;
a;
}
''',
[error(LinterLintCode.omit_local_variable_types, 11, 3)],
);
}
test_basic() async {
await assertNoErrorsInCode(r'''
int a = 0;
var b = 1 + 2;
''');
assertType(findElement2.topVar('a').type, 'int');
assertElement(
findNode.namedType('int a').element,
declaration: intElement,
);
assertType(findElement2.topVar('b').type, 'int');
}
test_dispose() async {
var a = newFile('$testPackageLibPath/a.dart', r'''
class A {}
''');
// After resolution the byte store contains unlinked data for files,
// and linked data for loaded bundles.
await resolveFile(a);
assertStateString(r'''
files
/workspace/dart/test/lib/a.dart
uri: package:dart.test/a.dart
current
id: file_0
kind: library_0
libraryImports
library_1 dart:core synthetic
fileKinds: library_0
cycle_0
dependencies: dart:core
libraries: library_0
apiSignature_0
unlinkedKey: k00
unlinkedGet: []
unlinkedPut: [k00]
libraryCycles
/workspace/dart/test/lib/a.dart
current: cycle_0
key: k01
get: []
put: [k01]
elementFactory
hasElement
package:dart.test/a.dart
unlinkedUnitStore
1: [k00, k02, k03, k04, k05, k06]
byteStore
1: [k00, k01, k02, k03, k04, k05, k06, k07]
''');
fileResolver.dispose();
// After dispose() we don't have any loaded libraries or files.
// The byte store is empty - no unlinked or linked data.
assertStateString(r'''
files
/workspace/dart/test/lib/a.dart
uri: package:dart.test/a.dart
unlinkedGet: []
unlinkedPut: [k00]
libraryCycles
/workspace/dart/test/lib/a.dart
get: []
put: [k01]
elementFactory
unlinkedUnitStore
1: [k00, k02, k03, k04, k05, k06]
byteStore
''');
}
test_elements_export_dartCoreDynamic() async {
var a = newFile('/workspace/dart/test/lib/a.dart', r'''
export 'dart:core' show dynamic;
''');
// Analyze so that `dart:core` is linked.
var a_result = await resolveFile(a);
// Touch `dart:core` so that its element model is discarded.
var dartCorePath =
a_result.session.uriConverter.uriToPath(Uri.parse('dart:core'))!;
fileResolver.changeFiles([dartCorePath]);
// Analyze, this will read the element model for `dart:core`.
// There was a bug that `root::dart:core::dynamic` had no element set.
await assertNoErrorsInCode(r'''
import 'a.dart' as p;
p.dynamic f() {}
''');
}
Future<void> test_errors_hasNullSuffix() async {
await assertErrorsInCode(
r'''
String f(Map<int, String> a) {
return a[0];
}
''',
[
error(
CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION,
40,
4,
messageContains: ["'String'", 'String?'],
),
],
);
}
test_findReferences_class() async {
var a = newFile('/workspace/dart/test/lib/a.dart', r'''
class A {
int foo;
}
''');
var b = newFile('/workspace/dart/test/lib/b.dart', r'''
import 'a.dart';
void func() {
var a = A();
print(a.foo);
}
''');
await resolveFile(b);
var element = await _findElement(6, a);
var result = await fileResolver.findReferences(element);
var expected = <CiderSearchMatch>[
CiderSearchMatch(b.path, [
CiderSearchInfo(CharacterLocation(4, 11), 1, MatchKind.REFERENCE),
]),
];
expect(result, unorderedEquals(expected));
}
test_findReferences_field() async {
var a = newFile('/workspace/dart/test/lib/a.dart', r'''
class A {
int foo = 0;
void func(int bar) {
foo = bar;
}
}
''');
await resolveFile(a);
var element = await _findElement(16, a);
var result = await fileResolver.findReferences(element);
var expected = <CiderSearchMatch>[
CiderSearchMatch(a.path, [
CiderSearchInfo(CharacterLocation(5, 5), 3, MatchKind.WRITE),
]),
];
expect(result, expected);
}
test_findReferences_function() async {
var a = newFile('/workspace/dart/test/lib/a.dart', r'''
main() {
foo('Hello');
}
foo(String str) {}
''');
await resolveFile(a);
var element = await _findElement(11, a);
var result = await fileResolver.findReferences(element);
var expected = <CiderSearchMatch>[
CiderSearchMatch(a.path, [
CiderSearchInfo(CharacterLocation(2, 3), 3, MatchKind.REFERENCE),
]),
];
expect(result, unorderedEquals(expected));
}
test_findReferences_getter() async {
var a = newFile('/workspace/dart/test/lib/a.dart', r'''
class A {
int get foo => 6;
}
''');
var b = newFile('/workspace/dart/test/lib/b.dart', r'''
import 'a.dart';
main() {
var a = A();
var bar = a.foo;
}
''');
await resolveFile(b);
var element = await _findElement(20, a);
var result = await fileResolver.findReferences(element);
var expected = <CiderSearchMatch>[
CiderSearchMatch(b.path, [
CiderSearchInfo(CharacterLocation(5, 15), 3, MatchKind.REFERENCE),
]),
];
expect(result, unorderedEquals(expected));
}
test_findReferences_local_variable() async {
var aPath = convertPath('/workspace/dart/test/lib/a.dart');
var a = newFile(aPath, r'''
class A {
void func(int n) {
var foo = bar+1;
print(foo);
}
}
''');
await resolveFile(a);
var element = await _findElement(39, a);
var result = await fileResolver.findReferences(element);
var expected = <CiderSearchMatch>[
CiderSearchMatch(a.path, [
CiderSearchInfo(CharacterLocation(4, 11), 3, MatchKind.REFERENCE),
]),
];
expect(result, unorderedEquals(expected));
}
test_findReferences_method() async {
var a = newFile('/workspace/dart/test/lib/a.dart', r'''
class A {
void func() {
print('hello');
}
void func2() {
func();
}
}
''');
var b = newFile('/workspace/dart/test/lib/b.dart', r'''
import 'a.dart';
main() {
var a = A();
a.func();
}
''');
await resolveFile(a);
await resolveFile(b);
var element = await _findElement(17, a);
var result = await fileResolver.findReferences(element);
var expected = <CiderSearchMatch>[
CiderSearchMatch(b.path, [
CiderSearchInfo(CharacterLocation(5, 5), 4, MatchKind.REFERENCE),
]),
CiderSearchMatch(a.path, [
CiderSearchInfo(CharacterLocation(7, 4), 4, MatchKind.REFERENCE),
]),
];
expect(result, unorderedEquals(expected));
}
test_findReferences_setter() async {
var a = newFile('/workspace/dart/test/lib/a.dart', r'''
class A {
void set value(int m){ };
}
''');
var b = newFile('/workspace/dart/test/lib/b.dart', r'''
import 'a.dart';
main() {
var a = A();
a.value = 6;
}
''');
await resolveFile(b);
var element = await _findElement(21, a);
var result = await fileResolver.findReferences(element);
var expected = <CiderSearchMatch>[
CiderSearchMatch(b.path, [
CiderSearchInfo(CharacterLocation(5, 5), 5, MatchKind.WRITE),
]),
];
expect(result, unorderedEquals(expected));
}
test_findReferences_top_level_getter() async {
var a = newFile('/workspace/dart/test/lib/a.dart', r'''
int _foo;
int get foo => _foo;
''');
var b = newFile('/workspace/dart/test/lib/b.dart', r'''
import 'a.dart';
main() {
var bar = foo;
}
''');
await resolveFile(b);
var element = await _findElement(19, a);
var result = await fileResolver.findReferences(element);
var expected = <CiderSearchMatch>[
CiderSearchMatch(b.path, [
CiderSearchInfo(CharacterLocation(4, 13), 3, MatchKind.REFERENCE),
]),
];
expect(result, unorderedEquals(expected));
}
test_findReferences_top_level_setter() async {
var a = newFile('/workspace/dart/test/lib/a.dart', r'''
int _foo;
void set foo(int bar) { _foo = bar; }
''');
var b = newFile('/workspace/dart/test/lib/b.dart', r'''
import 'a.dart';
main() {
foo = 6;
}
''');
await resolveFile(b);
var element = await _findElement(20, a);
var result = await fileResolver.findReferences(element);
var expected = <CiderSearchMatch>[
CiderSearchMatch(b.path, [
CiderSearchInfo(CharacterLocation(4, 3), 3, MatchKind.WRITE),
]),
];
expect(result, unorderedEquals(expected));
}
test_findReferences_top_level_variable() async {
var a = newFile('/workspace/dart/test/lib/a.dart', r'''
const int C = 42;
void func() {
print(C);
}
''');
await resolveFile(a);
var element = await _findElement(10, a);
var result = await fileResolver.findReferences(element);
var expected = <CiderSearchMatch>[
CiderSearchMatch(a.path, [
CiderSearchInfo(CharacterLocation(4, 11), 1, MatchKind.READ),
]),
];
expect(result, unorderedEquals(expected));
}
test_findReferences_type_parameter() async {
var a = newFile('/workspace/dart/test/lib/a.dart', r'''
class Foo<T> {
List<T> l;
void bar(T t) {}
}
''');
await resolveFile(a);
var element = await _findElement(10, a);
var result = await fileResolver.findReferences(element);
var expected = <CiderSearchMatch>[
CiderSearchMatch(a.path, [
CiderSearchInfo(CharacterLocation(2, 8), 1, MatchKind.REFERENCE),
CiderSearchInfo(CharacterLocation(4, 12), 1, MatchKind.REFERENCE),
]),
];
expect(result, expected);
}
test_findReferences_typedef() async {
var a = newFile('/workspace/dart/test/lib/a.dart', r'''
typedef func = int Function(int);
''');
var b = newFile('/workspace/dart/test/lib/b.dart', r'''
import 'a.dart';
void f(func o) {}
''');
await resolveFile(b);
var element = await _findElement(8, a);
var result = await fileResolver.findReferences(element);
var expected = <CiderSearchMatch>[
CiderSearchMatch(b.path, [
CiderSearchInfo(CharacterLocation(3, 8), 4, MatchKind.REFERENCE),
]),
];
expect(result, unorderedEquals(expected));
}
test_formalParameter_promotion() async {
await assertNoErrorsInCode(r'''
void f(int? a) {
if (a != null) {
a.isEven;
}
}
''');
assertType(findElement2.parameter('a').type, 'int?');
}
test_getErrors() async {
addTestFile(r'''
var a = b;
var foo = 0;
''');
var result = await getTestErrors();
expect(result.path, convertPath('/workspace/dart/test/lib/test.dart'));
expect(result.uri.toString(), 'package:dart.test/test.dart');
assertErrorsInList(result.diagnostics, [
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 8, 1),
]);
expect(result.lineInfo.lineStarts, [0, 11, 24]);
}
test_getErrors_docImports() async {
newFile('$testPackageLibPath/a.dart', '');
var b = newFile('$testPackageLibPath/b.dart', r'''
/// @docImport 'a.dart';
library;
''');
var errorsResult = await fileResolver.getErrors2(path: b.path);
assertErrorsInList(errorsResult.diagnostics, []);
}
test_getErrors_library() async {
var a = newFile('$testPackageLibPath/a.dart', r'''
var a = 42
''');
var errorsResult = await fileResolver.getErrors2(path: a.path);
assertErrorsInList(errorsResult.diagnostics, [
error(ParserErrorCode.EXPECTED_TOKEN, 8, 2),
]);
}
test_getErrors_part_hasLibrary() async {
newFile('$testPackageLibPath/a.dart', r'''
part 'b.dart';
''');
var b = newFile('$testPackageLibPath/b.dart', r'''
part of 'a.dart';
var a = 42
''');
var errorsResult = await fileResolver.getErrors2(path: b.path);
assertErrorsInList(errorsResult.diagnostics, [
error(ParserErrorCode.EXPECTED_TOKEN, 26, 2),
]);
}
test_getErrors_reuse() async {
addTestFile('var a = b;');
// No resolved files yet.
_assertResolvedFiles([]);
// No cached, will resolve once.
expect((await getTestErrors()).diagnostics, hasLength(1));
_assertResolvedFiles([testFile]);
// Has cached, will be not resolved again.
expect((await getTestErrors()).diagnostics, hasLength(1));
_assertResolvedFiles([]);
// Change the file, will be resolved again.
addTestFile('var a = c;');
fileResolver.changeFiles([testFile.path]);
expect((await getTestErrors()).diagnostics, hasLength(1));
_assertResolvedFiles([testFile]);
}
test_getErrors_reuse_changeDependency() async {
var a = newFile('/workspace/dart/test/lib/a.dart', r'''
var a = 0;
''');
addTestFile(r'''
import 'a.dart';
var b = a.foo;
''');
// No resolved files yet.
_assertResolvedFiles([]);
// No cached, will resolve once.
expect((await getTestErrors()).diagnostics, hasLength(1));
_assertResolvedFiles([testFile]);
// Has cached, will be not resolved again.
expect((await getTestErrors()).diagnostics, hasLength(1));
_assertResolvedFiles([]);
// Change the dependency.
// The signature of the result is different.
// The previously cached result cannot be used.
newFile(a.path, r'''
var a = 4.2;
''');
fileResolver.changeFiles([a.path]);
expect((await getTestErrors()).diagnostics, hasLength(1));
_assertResolvedFiles([testFile]);
}
test_getFilesWithTopLevelDeclarations_cached() async {
await assertNoErrorsInCode(r'''
int a = 0;
var b = 1 + 2;
''');
void assertHasOneVariable() {
var files = fileResolver.getFilesWithTopLevelDeclarations('a');
expect(files, hasLength(1));
var file = files.single;
expect(file.path, result.path);
}
// Ask to check that it works when parsed.
assertHasOneVariable();
// Create a new resolved, but reuse the cache.
createFileResolver();
await resolveTestFile();
// Ask again, when unlinked information is read from the cache.
assertHasOneVariable();
}
test_getLibraryByUri() async {
newFile('/workspace/dart/my/lib/a.dart', r'''
class A {}
''');
var element = await fileResolver.getLibraryByUri2(
uriStr: 'package:dart.my/a.dart',
);
expect(element.classes, hasLength(1));
}
test_getLibraryByUri_notExistingFile() async {
var element = await fileResolver.getLibraryByUri2(
uriStr: 'package:dart.my/a.dart',
);
expect(element.classes, isEmpty);
}
test_getLibraryByUri_partOf() async {
newFile('/workspace/dart/my/lib/a.dart', r'''
part of 'b.dart';
''');
expect(() async {
await fileResolver.getLibraryByUri2(uriStr: 'package:dart.my/a.dart');
}, throwsArgumentError);
}
test_getLibraryByUri_unresolvedUri() async {
expect(() async {
await fileResolver.getLibraryByUri2(uriStr: 'my:unresolved');
}, throwsArgumentError);
}
test_hint_in_third_party() async {
var a = newFile('/workspace/third_party/dart/aaa/lib/a.dart', r'''
import 'dart:math';
''');
await resolveFile(a);
assertNoErrorsInResult();
}
test_linkLibraries() async {
var a = newFile('$testPackageLibPath/a.dart', r'''
final a = 0;
''');
var b = newFile('$testPackageLibPath/b.dart', r'''
import 'a.dart';
final b = a;
''');
await fileResolver.linkLibraries2(path: a.path);
assertStateString(r'''
files
/workspace/dart/test/lib/a.dart
uri: package:dart.test/a.dart
current
id: file_0
kind: library_0
libraryImports
library_1 dart:core synthetic
fileKinds: library_0
cycle_0
dependencies: dart:core
libraries: library_0
apiSignature_0
unlinkedKey: k00
unlinkedGet: []
unlinkedPut: [k00]
libraryCycles
/workspace/dart/test/lib/a.dart
current: cycle_0
key: k01
get: [k01]
put: [k01]
elementFactory
hasReader
package:dart.test/a.dart
unlinkedUnitStore
1: [k00, k02, k03, k04, k05, k06]
byteStore
1: [k00, k02, k03, k04, k05, k06]
''');
await fileResolver.getLibraryByUri2(uriStr: 'package:dart.test/a.dart');
assertStateString(r'''
files
/workspace/dart/test/lib/a.dart
uri: package:dart.test/a.dart
current
id: file_0
kind: library_0
libraryImports
library_1 dart:core synthetic
fileKinds: library_0
cycle_0
dependencies: dart:core
libraries: library_0
apiSignature_0
unlinkedKey: k00
unlinkedGet: []
unlinkedPut: [k00]
libraryCycles
/workspace/dart/test/lib/a.dart
current: cycle_0
key: k01
get: [k01]
put: [k01]
elementFactory
hasElement
package:dart.test/a.dart
hasReader
package:dart.test/a.dart
unlinkedUnitStore
1: [k00, k02, k03, k04, k05, k06]
byteStore
1: [k00, k02, k03, k04, k05, k06]
''');
await fileResolver.linkLibraries2(path: b.path);
// We discarded all libraries, so each one has `get` and `put`.
// We did not discard files, so only `unlinkedPut`.
// The reference count for each data is exactly `1`.
assertStateString(r'''
files
/workspace/dart/test/lib/a.dart
uri: package:dart.test/a.dart
current
id: file_0
kind: library_0
libraryImports
library_1 dart:core synthetic
fileKinds: library_0
cycle_0
dependencies: dart:core
libraries: library_0
apiSignature_0
users: cycle_2
referencingFiles: file_6
unlinkedKey: k00
unlinkedGet: []
unlinkedPut: [k00]
/workspace/dart/test/lib/b.dart
uri: package:dart.test/b.dart
current
id: file_6
kind: library_6
libraryImports
library_0
library_1 dart:core synthetic
fileKinds: library_6
cycle_2
dependencies: cycle_0 dart:core
libraries: library_6
apiSignature_1
unlinkedKey: k07
unlinkedGet: []
unlinkedPut: [k07]
libraryCycles
/workspace/dart/test/lib/a.dart
current: cycle_0
key: k01
get: [k01]
put: [k01, k01]
/workspace/dart/test/lib/b.dart
current: cycle_2
key: k08
get: [k08]
put: [k08]
elementFactory
hasElement
package:dart.test/a.dart
hasReader
package:dart.test/b.dart
unlinkedUnitStore
1: [k00, k02, k03, k04, k05, k06, k07]
byteStore
1: [k00, k02, k03, k04, k05, k06, k07]
''');
var b_library = await fileResolver.getLibraryByUri2(
uriStr: 'package:dart.test/b.dart',
);
// Ask types for top-level variables.
for (var topLevelVariable in b_library.topLevelVariables) {
topLevelVariable.type;
}
// All types are stored in the bundle for b.dart itself, we don't need to
// read a.dart to access them, so we keep it as a reader.
assertStateString(r'''
files
/workspace/dart/test/lib/a.dart
uri: package:dart.test/a.dart
current
id: file_0
kind: library_0
libraryImports
library_1 dart:core synthetic
fileKinds: library_0
cycle_0
dependencies: dart:core
libraries: library_0
apiSignature_0
users: cycle_2
referencingFiles: file_6
unlinkedKey: k00
unlinkedGet: []
unlinkedPut: [k00]
/workspace/dart/test/lib/b.dart
uri: package:dart.test/b.dart
current
id: file_6
kind: library_6
libraryImports
library_0
library_1 dart:core synthetic
fileKinds: library_6
cycle_2
dependencies: cycle_0 dart:core
libraries: library_6
apiSignature_1
unlinkedKey: k07
unlinkedGet: []
unlinkedPut: [k07]
libraryCycles
/workspace/dart/test/lib/a.dart
current: cycle_0
key: k01
get: [k01]
put: [k01, k01]
/workspace/dart/test/lib/b.dart
current: cycle_2
key: k08
get: [k08]
put: [k08]
elementFactory
hasElement
package:dart.test/a.dart
package:dart.test/b.dart
hasReader
package:dart.test/b.dart
unlinkedUnitStore
1: [k00, k02, k03, k04, k05, k06, k07]
byteStore
1: [k00, k02, k03, k04, k05, k06, k07]
''');
}
test_linkLibraries_getErrors() async {
addTestFile(r'''
var a = b;
var foo = 0;
''');
await fileResolver.linkLibraries2(path: testFile.path);
// We discarded all libraries, so each one has `get` and `put`.
// We did not discard files, so only `unlinkedPut`.
// The library for the test file has reader, but not the element yet.
// `dart:core` and `dart` have element because of `TypeProvider`.
// The reference count for each data is exactly `1`.
assertStateString(r'''
files
/workspace/dart/test/lib/test.dart
uri: package:dart.test/test.dart
current
id: file_0
kind: library_0
libraryImports
library_1 dart:core synthetic
fileKinds: library_0
cycle_0
dependencies: dart:core
libraries: library_0
apiSignature_0
unlinkedKey: k00
unlinkedGet: []
unlinkedPut: [k00]
libraryCycles
/workspace/dart/test/lib/test.dart
current: cycle_0
key: k01
get: [k01]
put: [k01]
elementFactory
hasReader
package:dart.test/test.dart
unlinkedUnitStore
1: [k00, k02, k03, k04, k05, k06]
byteStore
1: [k00, k02, k03, k04, k05, k06]
''');
var result = await getTestErrors();
expect(result.path, testFile.path);
expect(result.uri.toString(), 'package:dart.test/test.dart');
assertErrorsInList(result.diagnostics, [
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 8, 1),
]);
expect(result.lineInfo.lineStarts, [0, 11, 24]);
// We created the library element for the test file, using the reader.
assertStateString(r'''
files
/workspace/dart/test/lib/test.dart
uri: package:dart.test/test.dart
current
id: file_0
kind: library_0
libraryImports
library_1 dart:core synthetic
fileKinds: library_0
cycle_0
dependencies: dart:core
libraries: library_0
apiSignature_0
unlinkedKey: k00
unlinkedGet: []
unlinkedPut: [k00]
libraryCycles
/workspace/dart/test/lib/test.dart
current: cycle_0
key: k01
get: [k01]
put: [k01]
elementFactory
hasElement
package:dart.test/test.dart
hasReader
package:dart.test/test.dart
unlinkedUnitStore
1: [k00, k02, k03, k04, k05, k06]
byteStore
1: [k00, k02, k03, k04, k05, k06]
''');
}
test_nameOffset_class_method_fromBytes() async {
newFile('/workspace/dart/test/lib/a.dart', r'''
class A {
void foo() {}
}
''');
addTestFile(r'''
import 'a.dart';
void f(A a) {
a.foo();
}
''');
await resolveTestFile();
{
var element = findNode.simple('foo();').element!;
expect(element.firstFragment.nameOffset2, 17);
}
// New resolver.
// Element models will be loaded from the cache.
createFileResolver();
await resolveTestFile();
{
var element = findNode.simple('foo();').element!;
expect(element.firstFragment.nameOffset2, 17);
}
}
test_nameOffset_unit_variable_fromBytes() async {
newFile('/workspace/dart/test/lib/a.dart', r'''
var a = 0;
''');
addTestFile(r'''
import 'a.dart';
var b = a;
''');
await resolveTestFile();
{
var element = findNode.simple('a;').element!;
expect(element.nonSynthetic.firstFragment.nameOffset2, 4);
}
// New resolver.
// Element models will be loaded from the cache.
createFileResolver();
await resolveTestFile();
{
var element = findNode.simple('a;').element!;
expect(element.nonSynthetic.firstFragment.nameOffset2, 4);
}
}
test_part_notInLibrary_libraryDoesNotExist() async {
// TODO(scheglov): Should report CompileTimeErrorCode.URI_DOES_NOT_EXIST
await assertNoErrorsInCode(r'''
part of 'a.dart';
''');
}
test_removeFilesNotNecessaryForAnalysisOf() async {
newFile('/workspace/dart/aaa/lib/a.dart', r'''
class A {}
''');
var b = newFile('/workspace/dart/aaa/lib/b.dart', r'''
import 'a.dart';
class B {}
''');
var c = newFile('/workspace/dart/aaa/lib/c.dart', r'''
import 'a.dart';
class C {}
''');
await resolveFile(b);
await resolveFile(c);
assertStateString(r'''
files
/workspace/dart/aaa/lib/a.dart
uri: package:dart.aaa/a.dart
current
id: file_0
kind: library_0
libraryImports
library_3 dart:core synthetic
fileKinds: library_0
cycle_0
dependencies: dart:core
libraries: library_0
apiSignature_0
users: cycle_1 cycle_2
referencingFiles: file_1 file_2
unlinkedKey: k00
unlinkedGet: []
unlinkedPut: [k00]
/workspace/dart/aaa/lib/b.dart
uri: package:dart.aaa/b.dart
current
id: file_1
kind: library_1
libraryImports
library_0
library_3 dart:core synthetic
fileKinds: library_1
cycle_1
dependencies: cycle_0 dart:core
libraries: library_1
apiSignature_1
unlinkedKey: k01
unlinkedGet: []
unlinkedPut: [k01]
/workspace/dart/aaa/lib/c.dart
uri: package:dart.aaa/c.dart
current
id: file_2
kind: library_2
libraryImports
library_0
library_3 dart:core synthetic
fileKinds: library_2
cycle_2
dependencies: cycle_0 dart:core
libraries: library_2
apiSignature_2
unlinkedKey: k02
unlinkedGet: []
unlinkedPut: [k02]
libraryCycles
/workspace/dart/aaa/lib/a.dart
current: cycle_0
key: k03
get: []
put: [k03]
/workspace/dart/aaa/lib/b.dart
current: cycle_1
key: k04
get: []
put: [k04]
/workspace/dart/aaa/lib/c.dart
current: cycle_2
key: k05
get: []
put: [k05]
elementFactory
hasElement
package:dart.aaa/a.dart
package:dart.aaa/b.dart
package:dart.aaa/c.dart
unlinkedUnitStore
1: [k00, k01, k02, k06, k07, k08, k09, k10]
byteStore
1: [k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k10, k11]
''');
fileResolver.removeFilesNotNecessaryForAnalysisOf([c.path]);
// No data for b.dart anymore.
assertStateString(r'''
files
/workspace/dart/aaa/lib/a.dart
uri: package:dart.aaa/a.dart
current
id: file_0
kind: library_0
libraryImports
library_3 dart:core synthetic
fileKinds: library_0
cycle_0
dependencies: dart:core
libraries: library_0
apiSignature_0
users: cycle_2
referencingFiles: file_2
unlinkedKey: k00
unlinkedGet: []
unlinkedPut: [k00]
/workspace/dart/aaa/lib/b.dart
uri: package:dart.aaa/b.dart
unlinkedGet: []
unlinkedPut: [k01]
/workspace/dart/aaa/lib/c.dart
uri: package:dart.aaa/c.dart
current
id: file_2
kind: library_2
libraryImports
library_0
library_3 dart:core synthetic
fileKinds: library_2
cycle_2
dependencies: cycle_0 dart:core
libraries: library_2
apiSignature_2
unlinkedKey: k02
unlinkedGet: []
unlinkedPut: [k02]
libraryCycles
/workspace/dart/aaa/lib/a.dart
current: cycle_0
key: k03
get: []
put: [k03]
/workspace/dart/aaa/lib/b.dart
get: []
put: [k04]
/workspace/dart/aaa/lib/c.dart
current: cycle_2
key: k05
get: []
put: [k05]
elementFactory
hasElement
package:dart.aaa/a.dart
package:dart.aaa/c.dart
unlinkedUnitStore
1: [k00, k02, k06, k07, k08, k09, k10]
byteStore
1: [k00, k02, k03, k05, k06, k07, k08, k09, k10, k11]
''');
}
test_removeFilesNotNecessaryForAnalysisOf_multiple() async {
newFile('/workspace/dart/aaa/lib/a.dart', r'''
class A {}
''');
newFile('/workspace/dart/aaa/lib/b.dart', r'''
class B {}
''');
newFile('/workspace/dart/aaa/lib/c.dart', r'''
class C {}
''');
var d = newFile('/workspace/dart/aaa/lib/d.dart', r'''
import 'a.dart';
''');
var e = newFile('/workspace/dart/aaa/lib/e.dart', r'''
import 'a.dart';
import 'b.dart';
''');
var f = newFile('/workspace/dart/aaa/lib/f.dart', r'''
import 'c.dart';
''');
await resolveFile(d);
await resolveFile(e);
await resolveFile(f);
assertStateString(r'''
files
/workspace/dart/aaa/lib/a.dart
uri: package:dart.aaa/a.dart
current
id: file_0
kind: library_0
libraryImports
library_6 dart:core synthetic
fileKinds: library_0
cycle_0
dependencies: dart:core
libraries: library_0
apiSignature_0
users: cycle_3 cycle_4
referencingFiles: file_3 file_4
unlinkedKey: k00
unlinkedGet: []
unlinkedPut: [k00]
/workspace/dart/aaa/lib/b.dart
uri: package:dart.aaa/b.dart
current
id: file_1
kind: library_1
libraryImports
library_6 dart:core synthetic
fileKinds: library_1
cycle_1
dependencies: dart:core
libraries: library_1
apiSignature_1
users: cycle_4
referencingFiles: file_4
unlinkedKey: k01
unlinkedGet: []
unlinkedPut: [k01]
/workspace/dart/aaa/lib/c.dart
uri: package:dart.aaa/c.dart
current
id: file_2
kind: library_2
libraryImports
library_6 dart:core synthetic
fileKinds: library_2
cycle_2
dependencies: dart:core
libraries: library_2
apiSignature_2
users: cycle_5
referencingFiles: file_5
unlinkedKey: k02
unlinkedGet: []
unlinkedPut: [k02]
/workspace/dart/aaa/lib/d.dart
uri: package:dart.aaa/d.dart
current
id: file_3
kind: library_3
libraryImports
library_0
library_6 dart:core synthetic
fileKinds: library_3
cycle_3
dependencies: cycle_0 dart:core
libraries: library_3
apiSignature_3
unlinkedKey: k03
unlinkedGet: []
unlinkedPut: [k03]
/workspace/dart/aaa/lib/e.dart
uri: package:dart.aaa/e.dart
current
id: file_4
kind: library_4
libraryImports
library_0
library_1
library_6 dart:core synthetic
fileKinds: library_4
cycle_4
dependencies: cycle_0 cycle_1 dart:core
libraries: library_4
apiSignature_4
unlinkedKey: k04
unlinkedGet: []
unlinkedPut: [k04]
/workspace/dart/aaa/lib/f.dart
uri: package:dart.aaa/f.dart
current
id: file_5
kind: library_5
libraryImports
library_2
library_6 dart:core synthetic
fileKinds: library_5
cycle_5
dependencies: cycle_2 dart:core
libraries: library_5
apiSignature_5
unlinkedKey: k05
unlinkedGet: []
unlinkedPut: [k05]
libraryCycles
/workspace/dart/aaa/lib/a.dart
current: cycle_0
key: k06
get: []
put: [k06]
/workspace/dart/aaa/lib/b.dart
current: cycle_1
key: k07
get: []
put: [k07]
/workspace/dart/aaa/lib/c.dart
current: cycle_2
key: k08
get: []
put: [k08]
/workspace/dart/aaa/lib/d.dart
current: cycle_3
key: k09
get: []
put: [k09]
/workspace/dart/aaa/lib/e.dart
current: cycle_4
key: k10
get: []
put: [k10]
/workspace/dart/aaa/lib/f.dart
current: cycle_5
key: k11
get: []
put: [k11]
elementFactory
hasElement
package:dart.aaa/a.dart
package:dart.aaa/b.dart
package:dart.aaa/c.dart
package:dart.aaa/d.dart
package:dart.aaa/e.dart
package:dart.aaa/f.dart
unlinkedUnitStore
1: [k00, k01, k02, k03, k04, k05, k12, k13, k14, k15, k16]
byteStore
1: [k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k10, k11, k12, k13, k14, k15, k16, k17]
''');
fileResolver.removeFilesNotNecessaryForAnalysisOf([d.path, f.path]);
// No data for b.dart and e.dart anymore.
assertStateString(r'''
files
/workspace/dart/aaa/lib/a.dart
uri: package:dart.aaa/a.dart
current
id: file_0
kind: library_0
libraryImports
library_6 dart:core synthetic
fileKinds: library_0
cycle_0
dependencies: dart:core
libraries: library_0
apiSignature_0
users: cycle_3
referencingFiles: file_3
unlinkedKey: k00
unlinkedGet: []
unlinkedPut: [k00]
/workspace/dart/aaa/lib/b.dart
uri: package:dart.aaa/b.dart
unlinkedGet: []
unlinkedPut: [k01]
/workspace/dart/aaa/lib/c.dart
uri: package:dart.aaa/c.dart
current
id: file_2
kind: library_2
libraryImports
library_6 dart:core synthetic
fileKinds: library_2
cycle_2
dependencies: dart:core
libraries: library_2
apiSignature_2
users: cycle_5
referencingFiles: file_5
unlinkedKey: k02
unlinkedGet: []
unlinkedPut: [k02]
/workspace/dart/aaa/lib/d.dart
uri: package:dart.aaa/d.dart
current
id: file_3
kind: library_3
libraryImports
library_0
library_6 dart:core synthetic
fileKinds: library_3
cycle_3
dependencies: cycle_0 dart:core
libraries: library_3
apiSignature_3
unlinkedKey: k03
unlinkedGet: []
unlinkedPut: [k03]
/workspace/dart/aaa/lib/e.dart
uri: package:dart.aaa/e.dart
unlinkedGet: []
unlinkedPut: [k04]
/workspace/dart/aaa/lib/f.dart
uri: package:dart.aaa/f.dart
current
id: file_5
kind: library_5
libraryImports
library_2
library_6 dart:core synthetic
fileKinds: library_5
cycle_5
dependencies: cycle_2 dart:core
libraries: library_5
apiSignature_5
unlinkedKey: k05
unlinkedGet: []
unlinkedPut: [k05]
libraryCycles
/workspace/dart/aaa/lib/a.dart
current: cycle_0
key: k06
get: []
put: [k06]
/workspace/dart/aaa/lib/b.dart
get: []
put: [k07]
/workspace/dart/aaa/lib/c.dart
current: cycle_2
key: k08
get: []
put: [k08]
/workspace/dart/aaa/lib/d.dart
current: cycle_3
key: k09
get: []
put: [k09]
/workspace/dart/aaa/lib/e.dart
get: []
put: [k10]
/workspace/dart/aaa/lib/f.dart
current: cycle_5
key: k11
get: []
put: [k11]
elementFactory
hasElement
package:dart.aaa/a.dart
package:dart.aaa/c.dart
package:dart.aaa/d.dart
package:dart.aaa/f.dart
unlinkedUnitStore
1: [k00, k02, k03, k05, k12, k13, k14, k15, k16]
byteStore
1: [k00, k02, k03, k05, k06, k08, k09, k11, k12, k13, k14, k15, k16, k17]
''');
}
test_removeFilesNotNecessaryForAnalysisOf_unknown() async {
var a = newFile('/workspace/dart/aaa/lib/a.dart', r'''
class A {}
''');
var b = getFile('/workspace/dart/aaa/lib/b.dart');
await resolveFile(a);
fileResolver.removeFilesNotNecessaryForAnalysisOf([a.path, b.path]);
// No b.dart anywhere.
assertStateString(r'''
files
/workspace/dart/aaa/lib/a.dart
uri: package:dart.aaa/a.dart
current
id: file_0
kind: library_0
libraryImports
library_1 dart:core synthetic
fileKinds: library_0
cycle_0
dependencies: dart:core
libraries: library_0
apiSignature_0
unlinkedKey: k00
unlinkedGet: []
unlinkedPut: [k00]
libraryCycles
/workspace/dart/aaa/lib/a.dart
current: cycle_0
key: k01
get: []
put: [k01]
elementFactory
hasElement
package:dart.aaa/a.dart
unlinkedUnitStore
1: [k00, k02, k03, k04, k05, k06]
byteStore
1: [k00, k01, k02, k03, k04, k05, k06, k07]
''');
}
test_resolve_libraryWithPart_noLibraryDiscovery() async {
newFile('/workspace/dart/test/lib/a.dart', r'''
part of 'test.dart';
class A {}
''');
await assertNoErrorsInCode(r'''
part 'a.dart';
void f(A a) {}
''');
// We started resolution from the library, and then followed to the part.
// So, the part knows its library, there is no need to discover it.
// TODO(scheglov): Use textual dump
// _assertDiscoveredLibraryForParts([]);
}
test_resolve_part_of_name() async {
var a = newFile('/workspace/dart/test/lib/a.dart', r'''
library my.lib;
part 'test.dart';
class A {
int m;
}
''');
await assertNoErrorsInCode(r'''
part of my.lib;
void func() {
var a = A();
print(a.m);
}
''');
// TODO(scheglov): Use textual dump
var fsState = fileResolver.fsState!;
var testState = fsState.getExisting(testFile)!;
var testKind = testState.kind as PartFileKind;
expect(testKind.library?.file, fsState.getExisting(a));
}
test_resolve_part_of_uri() async {
var a = newFile('/workspace/dart/test/lib/a.dart', r'''
part 'test.dart';
class A {
int m;
}
''');
await assertNoErrorsInCode(r'''
part of 'a.dart';
void func() {
var a = A();
print(a.m);
}
''');
// TODO(scheglov): Use textual dump
var fsState = fileResolver.fsState!;
var testState = fsState.getExisting(testFile)!;
var testKind = testState.kind as PartFileKind;
expect(testKind.library?.file, fsState.getExisting(a));
}
test_resolveFile_cache() async {
addTestFile('var a = 0;');
// No resolved files yet.
_assertResolvedFiles([]);
await resolveFile2(testFile);
var result1 = result;
// The file was resolved.
_assertResolvedFiles([testFile]);
// The result is cached.
expect(fileResolver.cachedResults, contains(testFile.path));
// Ask again, no changes, not resolved.
await resolveFile2(testFile);
_assertResolvedFiles([]);
// The same result was returned.
expect(result, same(result1));
// Change a file.
var a_path = convertPath('/workspace/dart/test/lib/a.dart');
fileResolver.changeFiles([a_path]);
// The was a change to a file, no matter which, resolve again.
await resolveFile2(testFile);
_assertResolvedFiles([testFile]);
// Get should get a new result.
expect(result, isNot(same(result1)));
}
test_resolveLibrary() async {
var aPath = convertPath('/workspace/dart/test/lib/a.dart');
newFile(aPath, r'''
part 'test.dart';
class A {
int m;
}
''');
newFile('/workspace/dart/test/lib/test.dart', r'''
part of 'a.dart';
void func() {
var a = A();
print(a.m);
}
''');
var result = await fileResolver.resolveLibrary2(path: aPath);
expect(result.units.length, 2);
expect(result.units[0].path, aPath);
expect(result.units[0].uri, Uri.parse('package:dart.test/a.dart'));
}
test_reuse_compatibleOptions() async {
newFile('/workspace/dart/aaa/BUILD', '');
newFile('/workspace/dart/bbb/BUILD', '');
var aPath = '/workspace/dart/aaa/lib/a.dart';
var aResult = await assertErrorsInFile(aPath, '', []);
var bPath = '/workspace/dart/bbb/lib/a.dart';
var bResult = await assertErrorsInFile(bPath, '', []);
// Both files use the same (default) analysis options.
// So, when we resolve 'bbb', we can reuse the context after 'aaa'.
expect(
aResult.libraryElement2.session,
same(bResult.libraryElement2.session),
);
}
test_switchCase_implementsEquals_enum() async {
await assertNoErrorsInCode(r'''
enum MyEnum {a, b, c}
void f(MyEnum myEnum) {
switch (myEnum) {
case MyEnum.a:
break;
default:
break;
}
}
''');
}
test_switchCase_implementsEquals_enum_language219() async {
await assertNoErrorsInCode(r'''
// @dart = 2.19
enum MyEnum {a, b, c}
void f(MyEnum myEnum) {
switch (myEnum) {
case MyEnum.a:
break;
default:
break;
}
}
''');
}
test_unknown_uri() async {
await assertErrorsInCode(
r'''
import 'foo:bar';
''',
[error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 9)],
);
}
test_warning() async {
await assertErrorsInCode(
r'''
import 'dart:math';
''',
[error(WarningCode.UNUSED_IMPORT, 7, 11)],
);
}
void _assertResolvedFiles(List<File> expected, {bool andClear = true}) {
var actual = fileResolver.testData!.resolvedLibraries;
expect(actual, expected.map((e) => e.path).toList());
if (andClear) {
actual.clear();
}
}
Future<Element> _findElement(int offset, File file) async {
var resolvedUnit = await fileResolver.resolve(path: file.path);
var node = resolvedUnit.unit.nodeCovering(offset: offset);
var element = getElementOfNode2(node);
return element!;
}
}