blob: 3df95f68781f4b1183fbdfbcad0ef8fb67223e21 [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/src/dart/analysis/experiments.dart';
import 'package:meta/meta.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'context_collection_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(LibraryElementTest);
});
}
@reflectiveTest
class LibraryElementTest extends PubPackageResolutionTest {
test_languageVersion() async {
newFile('$testPackageRootPath/.dart_tool/package_config.json', content: '''
{
"configVersion": 2,
"packages": [
{
"name": "test",
"rootUri": "../",
"packageUri": "lib/",
"languageVersion": "2.7"
},
{
"name": "aaa",
"rootUri": "${toUriStr('/aaa')}",
"packageUri": "lib/"
}
]
}
''');
newFile('$testPackageLibPath/a.dart', content: r'''
class A {}
''');
newFile('$testPackageLibPath/b.dart', content: r'''
// @dart = 2.6
class A {}
''');
newFile('$testPackageLibPath/c.dart', content: r'''
// @dart = 2.9
class A {}
''');
newFile('$testPackageLibPath/d.dart', content: r'''
// @dart = 2.99
class A {}
''');
newFile('$testPackageLibPath/e.dart', content: r'''
// @dart = 3.0
class A {}
''');
newFile('$workspaceRootPath/aaa/lib/a.dart', content: r'''
class A {}
''');
newFile('$workspaceRootPath/aaa/lib/b.dart', content: r'''
// @dart = 2.99
class A {}
''');
newFile('$workspaceRootPath/aaa/lib/c.dart', content: r'''
// @dart = 3.0
class A {}
''');
// No override.
await _assertLanguageVersion(
path: '$testPackageLibPath/a.dart',
package: Version.parse('2.7.0'),
override: null,
);
// Valid override, less than the latest supported language version.
await _assertLanguageVersion(
path: '$testPackageLibPath/b.dart',
package: Version.parse('2.7.0'),
override: Version.parse('2.6.0'),
);
// Valid override, even if greater than the package language version.
await _assertLanguageVersion(
path: '$testPackageLibPath/c.dart',
package: Version.parse('2.7.0'),
override: Version.parse('2.9.0'),
);
// Invalid override: minor is greater than the latest minor.
await _assertLanguageVersion(
path: '$testPackageLibPath/d.dart',
package: Version.parse('2.7.0'),
override: null,
);
// Invalid override: major is greater than the latest major.
await _assertLanguageVersion(
path: '$testPackageLibPath/e.dart',
package: Version.parse('2.7.0'),
override: null,
);
await _assertLanguageVersionCurrent('$workspaceRootPath/aaa/lib/a.dart');
await _assertLanguageVersionCurrent('$workspaceRootPath/aaa/lib/b.dart');
await _assertLanguageVersionCurrent('$workspaceRootPath/aaa/lib/c.dart');
}
test_scope_lookup2() async {
await assertNoErrorsInCode(r'''
int foo;
''');
var scope = result.libraryElement.scope;
assertElement(
scope.lookup2('foo').getter,
findElement.topGet('foo'),
);
assertElement(
scope.lookup2('foo').setter,
findElement.topSet('foo'),
);
}
test_scope_lookup2_implicitCoreImport() async {
await assertNoErrorsInCode('');
var scope = result.libraryElement.scope;
assertElement(
scope.lookup2('int').getter,
intElement,
);
}
test_scope_lookup2_notFound() async {
await assertNoErrorsInCode('');
var scope = result.libraryElement.scope;
assertElementNull(
scope.lookup2('noSuchGetter').getter,
);
assertElementNull(
scope.lookup2('noSuchSetter').setter,
);
}
test_scope_lookup2_prefersLocal() async {
await assertNoErrorsInCode(r'''
// ignore:unused_import
import 'dart:math';
int sin() => 3;
''');
var scope = result.libraryElement.scope;
assertElement(
scope.lookup2('sin').getter,
findElement.topFunction('sin'),
);
assertElement(
scope.lookup2('cos').getter,
findElement.importFind('dart:math').topFunction('cos'),
);
}
test_scope_lookup2_prefix() async {
await assertNoErrorsInCode(r'''
// ignore:unused_import
import 'dart:math' as math;
''');
var scope = result.libraryElement.scope;
assertElement(
scope.lookup2('math').getter,
findElement.prefix('math'),
);
}
test_scope_lookup2_respectsCombinator_hide() async {
await assertNoErrorsInCode(r'''
// ignore:unused_import
import 'dart:math' hide sin;
''');
var scope = result.libraryElement.scope;
assertElementNull(
scope.lookup2('sin').getter,
);
var mathFind = findElement.importFind('dart:math');
assertElement(
scope.lookup2('cos').getter,
mathFind.topFunction('cos'),
);
assertElement(
scope.lookup2('tan').getter,
mathFind.topFunction('tan'),
);
}
test_scope_lookup2_respectsCombinator_show() async {
await assertNoErrorsInCode(r'''
// ignore:unused_import
import 'dart:math' show sin;
''');
var scope = result.libraryElement.scope;
assertElement(
scope.lookup2('sin').getter,
findElement.importFind('dart:math').topFunction('sin'),
);
assertElementNull(
scope.lookup2('cos').getter,
);
}
test_scope_lookup_implicitCoreImport() async {
await assertNoErrorsInCode('');
var scope = result.libraryElement.scope;
assertElement(
// ignore: deprecated_member_use_from_same_package
scope.lookup(id: 'int', setter: false),
intElement,
);
}
test_scope_lookup_lookup() async {
await assertNoErrorsInCode(r'''
int foo;
''');
var scope = result.libraryElement.scope;
assertElement(
// ignore: deprecated_member_use_from_same_package
scope.lookup(id: 'foo', setter: false),
findElement.topGet('foo'),
);
assertElement(
// ignore: deprecated_member_use_from_same_package
scope.lookup(id: 'foo', setter: true),
findElement.topSet('foo'),
);
}
test_scope_lookup_notFound() async {
await assertNoErrorsInCode('');
var scope = result.libraryElement.scope;
assertElementNull(
// ignore: deprecated_member_use_from_same_package
scope.lookup(id: 'noSuchGetter', setter: false),
);
assertElementNull(
// ignore: deprecated_member_use_from_same_package
scope.lookup(id: 'noSuchSetter', setter: true),
);
}
test_scope_lookup_prefersLocal() async {
await assertNoErrorsInCode(r'''
// ignore:unused_import
import 'dart:math';
int sin() => 3;
''');
var scope = result.libraryElement.scope;
assertElement(
// ignore: deprecated_member_use_from_same_package
scope.lookup(id: 'sin', setter: false),
findElement.topFunction('sin'),
);
assertElement(
// ignore: deprecated_member_use_from_same_package
scope.lookup(id: 'cos', setter: false),
findElement.importFind('dart:math').topFunction('cos'),
);
}
test_scope_lookup_prefix() async {
await assertNoErrorsInCode(r'''
// ignore:unused_import
import 'dart:math' as math;
''');
var scope = result.libraryElement.scope;
assertElement(
// ignore: deprecated_member_use_from_same_package
scope.lookup(id: 'math', setter: false),
findElement.prefix('math'),
);
}
test_scope_lookup_respectsCombinator_hide() async {
await assertNoErrorsInCode(r'''
// ignore:unused_import
import 'dart:math' hide sin;
''');
var scope = result.libraryElement.scope;
assertElementNull(
// ignore: deprecated_member_use_from_same_package
scope.lookup(id: 'sin', setter: false),
);
var mathFind = findElement.importFind('dart:math');
assertElement(
// ignore: deprecated_member_use_from_same_package
scope.lookup(id: 'cos', setter: false),
mathFind.topFunction('cos'),
);
assertElement(
// ignore: deprecated_member_use_from_same_package
scope.lookup(id: 'tan', setter: false),
mathFind.topFunction('tan'),
);
}
test_scope_lookup_respectsCombinator_show() async {
await assertNoErrorsInCode(r'''
// ignore:unused_import
import 'dart:math' show sin;
''');
var scope = result.libraryElement.scope;
assertElement(
// ignore: deprecated_member_use_from_same_package
scope.lookup(id: 'sin', setter: false),
findElement.importFind('dart:math').topFunction('sin'),
);
assertElementNull(
// ignore: deprecated_member_use_from_same_package
scope.lookup(id: 'cos', setter: false),
);
}
Future<void> _assertLanguageVersion({
@required String path,
@required Version package,
@required Version override,
}) async {
path = convertPath(path);
var session = contextFor(path).currentSession;
var file = session.getFile(path);
var element = await session.getLibraryByUri('${file.uri}');
expect(element.languageVersion.package, package);
expect(element.languageVersion.override, override);
}
Future<void> _assertLanguageVersionCurrent(String path) async {
await _assertLanguageVersion(
path: path,
package: ExperimentStatus.currentVersion,
override: null,
);
}
}