blob: 0b0b4b974d9169f1bc2d7e52938b58885a715d75 [file] [log] [blame]
// Copyright (c) 2022, 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:test_reflective_loader/test_reflective_loader.dart';
import '../rule_test_support.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(PublicMemberApiDocsTest);
defineReflectiveTests(PublicMemberApiDocsTestDirTest);
defineReflectiveTests(PublicMemberApiDocsExtensionTypesTest);
defineReflectiveTests(PublicMemberApiDocsTestPackageTest);
});
}
@reflectiveTest
class PublicMemberApiDocsExtensionTypesTest extends LintRuleTest {
@override
bool get addMetaPackageDep => true;
@override
String get lintRule => 'public_member_api_docs';
test_extensionTypeDeclaration() async {
await assertDiagnostics(r'''
extension type E(int i) { }
''', [
lint(15, 1),
]);
}
test_field_instance() async {
await assertDiagnostics(r'''
/// Doc.
extension type E(int i) {
int? f;
}
''', [
// No lint.
error(CompileTimeErrorCode.EXTENSION_TYPE_DECLARES_INSTANCE_FIELD, 42, 1),
]);
}
test_field_static() async {
await assertDiagnostics(r'''
/// Doc.
extension type E(int i) {
static int? f;
}
''', [
lint(49, 1),
]);
}
test_method() async {
await assertDiagnostics(r'''
/// Doc.
extension type E(int i) {
void m() { }
}
''', [
lint(42, 1),
]);
}
test_method_private() async {
await assertDiagnostics(r'''
/// Doc.
extension type E(int i) {
void _m() { }
}
''', [
// No lint
error(WarningCode.UNUSED_ELEMENT, 42, 2),
]);
}
}
@reflectiveTest
class PublicMemberApiDocsTest extends LintRuleTest {
@override
bool get addMetaPackageDep => true;
@override
String get lintRule => 'public_member_api_docs';
/// https://github.com/dart-lang/linter/issues/4526
test_abstractFinalConstructor() async {
await assertDiagnostics(r'''
abstract final class S {
S();
}
final class A extends S {}
''', [
lint(21, 1),
// No lint on `S()` declaration
lint(47, 1),
]);
}
/// https://github.com/dart-lang/linter/issues/4526
test_abstractInterfaceConstructor() async {
await assertDiagnostics(r'''
abstract interface class S {
S();
}
final class A extends S {}
''', [
lint(25, 1),
// No lint on `S()` declaration
lint(51, 1),
]);
}
test_annotatedEnumValue() async {
await assertNoDiagnostics(r'''
/// Documented.
enum A {
/// This represents 'a'.
@Deprecated("Use 'b'")
a,
/// This represents 'b'.
b;
}
''');
}
test_constructor_namedGenerative() async {
await assertDiagnostics(r'''
class C {
C.c();
}
''', [
lint(6, 1),
lint(14, 1),
]);
}
test_constructor_unnamedFactory() async {
await assertDiagnostics(r'''
class C {
C._();
factory C() => C._();
}
''', [
lint(6, 1),
lint(30, 1),
]);
}
test_constructor_unnamedGenerative() async {
await assertDiagnostics(r'''
class C {
C();
}
''', [
lint(6, 1),
lint(12, 1),
]);
}
test_enum() async {
await assertDiagnostics(r'''
enum A {
a,b,c;
int x() => 0;
int get y => 1;
}
''', [
lint(5, 1),
lint(11, 1),
lint(13, 1),
lint(15, 1),
lint(24, 1),
lint(44, 1),
]);
}
test_enum_privateConstant() async {
await assertDiagnostics(r'''
/// Documented.
enum A {
_a;
}
''', [
// No lint.
error(WarningCode.UNUSED_FIELD, 27, 2),
]);
}
test_enumConstructor() async {
await assertNoDiagnostics(r'''
/// Documented.
enum A {
/// This represents 'a'.
a(),
/// This represents 'b'.
b();
const A();
}
''');
}
/// https://github.com/dart-lang/linter/issues/3525
test_extension() async {
await assertDiagnostics(r'''
extension E on Object {
void f() { }
}
''', [
lint(10, 1),
lint(31, 1),
]);
}
/// https://github.com/dart-lang/linter/issues/4521
test_internalClass() async {
await assertDiagnostics(r'''
import 'package:meta/meta.dart';
@internal
class C {
int? f;
int get i => 0;
C();
void m() {}
}
''', [
// Technically not in the private API but we can ignore that for testing.
error(WarningCode.INVALID_INTERNAL_ANNOTATION, 35, 8),
]);
}
/// https://github.com/dart-lang/linter/issues/4521
test_internalEnum() async {
await assertDiagnostics(r'''
import 'package:meta/meta.dart';
@internal
enum E {
a, b, c;
int get i => 0;
void m() {}
const E();
}
''', [
// Technically not in the private API but we can ignore that for testing.
error(WarningCode.INVALID_INTERNAL_ANNOTATION, 35, 8),
]);
}
/// https://github.com/dart-lang/linter/issues/4521
test_internalExtension() async {
await assertDiagnostics(r'''
import 'package:meta/meta.dart';
@internal
extension X on Object {
static int? f;
static int get i => 0;
void e() {}
}
''', [
// Technically not in the private API but we can ignore that for testing.
error(WarningCode.INVALID_INTERNAL_ANNOTATION, 35, 8),
]);
}
/// https://github.com/dart-lang/linter/issues/5030
test_internalFunction() async {
await assertDiagnostics(r'''
import 'package:meta/meta.dart';
@internal
void f() {}
''', [
// Technically not in the private API but we can ignore that for testing.
error(WarningCode.INVALID_INTERNAL_ANNOTATION, 35, 8),
]);
}
/// https://github.com/dart-lang/linter/issues/4521
test_internalMixin() async {
await assertDiagnostics(r'''
import 'package:meta/meta.dart';
@internal
mixin M {
int? f;
int get i => 0;
void m() {}
}
''', [
// Technically not in the private API but we can ignore that for testing.
error(WarningCode.INVALID_INTERNAL_ANNOTATION, 35, 8),
]);
}
test_mixin_method() async {
await assertDiagnostics(r'''
/// A mixin M.
mixin M {
String m() => '';
}''', [
lint(34, 1),
]);
}
test_mixin_overridingMethod_OK() async {
await assertNoDiagnostics(r'''
/// A mixin M.
mixin M {
@override
String toString() => '';
}''');
}
test_partFile() async {
newFile('$testPackageRootPath/test/a.dart', r'''
part 'test.dart';
''');
await assertDiagnostics(r'''
part of 'a.dart';
class A { }
''', [
lint(25, 1),
]);
}
/// https://github.com/dart-lang/linter/issues/4526
test_sealedConstructor() async {
await assertDiagnostics(r'''
sealed class S {
S();
}
final class A extends S {}
''', [
lint(13, 1),
// No lint on `S()` declaration
lint(39, 1),
]);
}
test_topLevelMembers() async {
await assertDiagnostics(r'''
int g = 1;
typedef T = void Function();
int get z => 0;
''', [
lint(4, 1),
lint(19, 1),
lint(48, 1),
]);
}
test_topLevelMembers_private() async {
await assertDiagnostics(r'''
int _h = 1;
typedef _T = void Function();
int get _z => 0;
''', [
// No lint
error(WarningCode.UNUSED_ELEMENT, 4, 2),
error(WarningCode.UNUSED_ELEMENT, 20, 2),
error(WarningCode.UNUSED_ELEMENT, 50, 2),
]);
}
}
@reflectiveTest
class PublicMemberApiDocsTestDirTest extends LintRuleTest {
@override
String get lintRule => 'public_member_api_docs';
@override
String get testPackageLibPath => '$testPackageRootPath/test';
test_inTestDir() async {
await assertNoDiagnostics(r'''
String? b;
typedef T = void Function();
''');
}
}
@reflectiveTest
class PublicMemberApiDocsTestPackageTest extends LintRuleTest {
String get filePath => '$fixturePackageLibPath/a.dart';
String get fixturePackageLibPath => '$myPackageRootPath/test/fixture/lib';
@override
String get lintRule => 'public_member_api_docs';
String get myPackageRootPath => '$workspaceRootPath/myPackage';
@override
void setUp() {
super.setUp();
writePackageConfig(
'$myPackageRootPath/.dart_tool/package_config.json',
PackageConfigFileBuilder(),
);
newPubspecYamlFile(myPackageRootPath,
PubspecYamlFileConfig(name: 'myPackage').toContent());
newAnalysisOptionsYamlFile(
myPackageRootPath,
AnalysisOptionsFileConfig(
experiments: experiments,
lints: lintRules,
propagateLinterExceptions: true,
).toContent(),
);
newFolder(fixturePackageLibPath);
writePackageConfig(
'$myPackageRootPath/test/fixture/.dart_tool/package_config.json',
PackageConfigFileBuilder()..add(name: 'fixture', rootPath: '../lib'));
}
test_inTestLibDir() async {
newFile(filePath, '''
String? b;
typedef T = void Function();
''');
await assertNoDiagnosticsInFile(filePath);
}
}