blob: bd33642af717310973743cb490a380fef30f6249 [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/analysis/features.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/test_utilities/package_mixin.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../dart/resolution/driver_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(InvalidUseOfProtectedMemberTest);
defineReflectiveTests(InvalidUseOfProtectedMember_InExtensionTest);
});
}
@reflectiveTest
class InvalidUseOfProtectedMemberTest extends DriverResolutionTest
with PackageMixin {
test_closure() async {
addMetaPackage();
newFile('/lib1.dart', content: r'''
import 'package:meta/meta.dart';
class A {
@protected
int a() => 42;
}
''');
newFile('/lib2.dart', content: r'''
import 'lib1.dart';
void main() {
var leak = new A().a;
print(leak);
}
''');
await _resolveTestFile('/lib1.dart');
await _resolveTestFile('/lib2.dart');
assertTestErrorsWithCodes([HintCode.INVALID_USE_OF_PROTECTED_MEMBER]);
}
test_extendingSubclass() async {
addMetaPackage();
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart';
class A {
@protected
void a(){ }
}
class B extends A {
void b() => a();
}''');
}
test_field() async {
addMetaPackage();
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart';
class A {
@protected
int a = 42;
}
class B extends A {
int b() => a;
}
''');
}
test_field_outsideClassAndLibrary() async {
addMetaPackage();
newFile('/lib1.dart', content: r'''
import 'package:meta/meta.dart';
class A {
@protected
int a;
}
''');
newFile('/lib2.dart', content: r'''
import 'lib1.dart';
abstract class B {
int b() => new A().a;
}
''');
await _resolveTestFile('/lib1.dart');
await _resolveTestFile('/lib2.dart');
assertTestErrorsWithCodes([HintCode.INVALID_USE_OF_PROTECTED_MEMBER]);
}
test_field_subclassAndSameLibrary() async {
addMetaPackage();
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart';
class A {
@protected
int a;
}
abstract class B implements A {
int b() => a;
}''');
}
test_fromSuperclassConstraint() async {
addMetaPackage();
newFile('/lib1.dart', content: r'''
import 'package:meta/meta.dart';
abstract class A {
@protected
void foo() {}
}
''');
newFile('/lib2.dart', content: r'''
import 'lib1.dart';
mixin M on A {
@override
void foo() {
super.foo();
}
}
''');
await _resolveTestFile('/lib1.dart');
await _resolveTestFile('/lib2.dart');
assertNoTestErrors();
}
test_function_outsideClassAndLibrary() async {
addMetaPackage();
newFile('/lib1.dart', content: r'''
import 'package:meta/meta.dart';
class A {
@protected
void a(){ }
}
''');
newFile('/lib2.dart', content: r'''
import 'lib1.dart';
main() {
new A().a();
}
''');
await _resolveTestFile('/lib1.dart');
await _resolveTestFile('/lib2.dart');
assertTestErrorsWithCodes([HintCode.INVALID_USE_OF_PROTECTED_MEMBER]);
}
test_function_sameLibrary() async {
addMetaPackage();
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart';
class A {
@protected
void a(){ }
}
main() {
new A().a();
}''');
}
test_function_subclass() async {
addMetaPackage();
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart';
class A {
@protected
int a() => 0;
}
abstract class B implements A {
int b() => a();
}''');
}
test_getter() async {
addMetaPackage();
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart';
class A {
@protected
int get a => 42;
}
class B extends A {
int b() => a;
}
''');
}
test_getter_outsideClassAndLibrary() async {
addMetaPackage();
newFile('/lib1.dart', content: r'''
import 'package:meta/meta.dart';
class A {
@protected
int get a => 42;
}
''');
newFile('/lib2.dart', content: r'''
import 'lib1.dart';
class B {
A a;
int b() => a.a;
}
''');
await _resolveTestFile('/lib1.dart');
await _resolveTestFile('/lib2.dart');
assertTestErrorsWithCodes([HintCode.INVALID_USE_OF_PROTECTED_MEMBER]);
}
test_getter_subclass() async {
addMetaPackage();
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart';
class A {
@protected
int get a => 42;
}
abstract class B implements A {
int b() => a;
}''');
}
test_inDocs() async {
addMetaPackage();
newFile('/lib1.dart', content: r'''
import 'package:meta/meta.dart';
class A {
@protected
int c = 0;
@protected
int get b => 0;
@protected
int a() => 0;
}
''');
newFile('/lib2.dart', content: r'''
import 'lib1.dart';
/// OK: [A.a], [A.b], [A.c].
f() {}
''');
await _resolveTestFile('/lib1.dart');
await _resolveTestFile('/lib2.dart');
assertNoTestErrors();
}
test_method_outsideClassAndLibrary() async {
addMetaPackage();
newFile('/lib1.dart', content: r'''
import 'package:meta/meta.dart';
class A {
@protected
void a() {}
}
''');
newFile('/lib2.dart', content: r'''
import 'lib1.dart';
class B {
void b() => new A().a();
}
''');
await _resolveTestFile('/lib1.dart');
await _resolveTestFile('/lib2.dart');
assertTestErrorsWithCodes([HintCode.INVALID_USE_OF_PROTECTED_MEMBER]);
}
test_method_subclass() async {
// https://github.com/dart-lang/linter/issues/257
addMetaPackage();
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart';
typedef void VoidCallback();
class State<E> {
@protected
void setState(VoidCallback fn) {}
}
class Button extends State<Object> {
void handleSomething() {
setState(() {});
}
}
''');
}
test_mixingIn() async {
addMetaPackage();
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart';
class A {
@protected
void a(){ }
}
class B extends Object with A {
void b() => a();
}''');
}
test_mixingIn_asParameter() async {
// TODO(srawlins): This test verifies that the analyzer **allows**
// protected members to be called from static members, which violates the
// protected spec.
addMetaPackage();
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart';
class A {
@protected m1() {}
}
class B extends A {
static m2(A a) => a.m1();
}''');
}
test_sameLibrary() async {
addMetaPackage();
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart';
class A {
@protected
void a(){ }
}
class B extends A {
void a() => a();
}
main() {
new B().a();
}''');
}
test_setter_outsideClassAndFile() async {
// TODO(srawlins): This test verifies that the analyzer **allows**
// protected members to be called on objects other than `this`, which
// violates the protected spec.
addMetaPackage();
newFile('/lib1.dart', content: r'''
import 'package:meta/meta.dart';
class A {
@protected
void set a(int i) { }
}
''');
newFile('/lib2.dart', content: r'''
import 'lib1.dart';
class B {
A a;
b(int i) {
a.a = i;
}
}
''');
await _resolveTestFile('/lib1.dart');
await _resolveTestFile('/lib2.dart');
assertTestErrorsWithCodes([HintCode.INVALID_USE_OF_PROTECTED_MEMBER]);
}
test_setter_sameClass() async {
addMetaPackage();
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart';
class A {
int _a;
@protected
void set a(int a) { _a = a; }
A(int a) {
this.a = a;
}
}
''');
}
test_setter_subclass() async {
addMetaPackage();
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart';
class A {
@protected
void set a(int i) { }
}
class B extends A {
void b(int i) {
a = i;
}
}
''');
}
test_setter_subclassImplementing() async {
addMetaPackage();
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart';
class A {
@protected
void set a(int i) { }
}
abstract class B implements A {
b(int i) {
a = i;
}
}''');
}
test_topLevelVariable() async {
addMetaPackage();
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart';
@protected
int x = 0;
main() {
print(x);
}''');
// TODO(brianwilkerson) This should produce a hint because the
// annotation is being applied to the wrong kind of declaration.
}
/// Resolve the test file at [path].
///
/// Similar to ResolutionTest.resolveTestFile, but a custom path is supported.
Future<void> _resolveTestFile(String path) async {
result = await resolveFile(convertPath(path));
}
}
@reflectiveTest
class InvalidUseOfProtectedMember_InExtensionTest
extends InvalidUseOfProtectedMemberTest {
@override
AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
..contextFeatures = new FeatureSet.forTesting(
sdkVersion: '2.3.0', additionalFeatures: [Feature.extension_methods]);
test_extension_outsideClassAndFile() async {
addMetaPackage();
newFile('/lib1.dart', content: r'''
import 'package:meta/meta.dart';
class A {
@protected
void a(int i) {}
}
''');
newFile('/lib2.dart', content: r'''
import 'lib1.dart';
extension E on A {
e() {
a(7);
}
}
''');
await _resolveTestFile('/lib1.dart');
await _resolveTestFile('/lib2.dart');
assertTestErrorsWithCodes([HintCode.INVALID_USE_OF_PROTECTED_MEMBER]);
}
}