From 0993e406685961d9bd41664df78b448472078c4a Mon Sep 17 00:00:00 2001 From: pq Date: Thu, 10 Aug 2023 13:09:36 -0700 Subject: [PATCH 1/2] extension type support for `library_private_types_in_public_api` --- .../library_private_types_in_public_api.dart | 9 ++ lib/src/rules/public_member_api_docs.dart | 14 +- ...rary_private_types_in_public_api_test.dart | 128 ++++++++++++++++++ 3 files changed, 144 insertions(+), 7 deletions(-) diff --git a/lib/src/rules/library_private_types_in_public_api.dart b/lib/src/rules/library_private_types_in_public_api.dart index 050a327fe..a3f6ae4e8 100644 --- a/lib/src/rules/library_private_types_in_public_api.dart +++ b/lib/src/rules/library_private_types_in_public_api.dart @@ -80,6 +80,14 @@ class Validator extends SimpleAstVisitor { node.members.accept(this); } + @override + void visitExtensionTypeDeclaration(ExtensionTypeDeclaration node) { + if (Identifier.isPrivateName(node.name.lexeme)) return; + node.typeParameters?.accept(this); + node.representation.fieldType.accept(this); + node.members.accept(this); + } + @override void visitClassTypeAlias(ClassTypeAlias node) { if (Identifier.isPrivateName(node.name.lexeme)) { @@ -134,6 +142,7 @@ class Validator extends SimpleAstVisitor { @override void visitFieldDeclaration(FieldDeclaration node) { + if (node.isInvalidExtensionTypeField) return; if (node.fields.variables .any((field) => !Identifier.isPrivateName(field.name.lexeme))) { node.fields.type?.accept(this); diff --git a/lib/src/rules/public_member_api_docs.dart b/lib/src/rules/public_member_api_docs.dart index a8d21477d..1d433d76f 100644 --- a/lib/src/rules/public_member_api_docs.dart +++ b/lib/src/rules/public_member_api_docs.dart @@ -172,13 +172,6 @@ class _Visitor extends SimpleAstVisitor { _visitMembers(node, node.name, node.members); } - @override - void visitExtensionTypeDeclaration(ExtensionTypeDeclaration node) { - var element = node.declaredElement; - if (element == null || element.hasInternal) return; - _visitMembers(node, node.name, node.members); - } - @override void visitClassTypeAlias(ClassTypeAlias node) { if (!isPrivate(node.name)) { @@ -272,6 +265,13 @@ class _Visitor extends SimpleAstVisitor { checkMethods(node.members); } + @override + void visitExtensionTypeDeclaration(ExtensionTypeDeclaration node) { + var element = node.declaredElement; + if (element == null || element.hasInternal) return; + _visitMembers(node, node.name, node.members); + } + @override void visitFieldDeclaration(FieldDeclaration node) { // todo(pq): update this to be called from the parent (like with visitMembers) diff --git a/test/rules/library_private_types_in_public_api_test.dart b/test/rules/library_private_types_in_public_api_test.dart index f65f08d5a..f52896b78 100644 --- a/test/rules/library_private_types_in_public_api_test.dart +++ b/test/rules/library_private_types_in_public_api_test.dart @@ -9,6 +9,7 @@ import '../rule_test_support.dart'; main() { defineReflectiveSuite(() { defineReflectiveTests(LibraryPrivateTypesInPublicApiEnumTest); + defineReflectiveTests(LibraryPrivateTypesInPublicApiExtensionTypeTest); defineReflectiveTests(LibraryPrivateTypesInPublicApiSuperParamTest); }); } @@ -84,6 +85,133 @@ sealed class E { } } +@reflectiveTest +class LibraryPrivateTypesInPublicApiExtensionTypeTest extends LintRuleTest { + @override + List get experiments => ['inline-class']; + + @override + String get lintRule => 'library_private_types_in_public_api'; + + test_constructorParam() async { + await assertDiagnostics(r''' +class _C {} +extension type E(Object o) { + E.e(_C c) : o = c; +} +''', [ + lint(47, 2), + ]); + } + + test_extensionTypeDeclaration_representation() async { + await assertDiagnostics(r''' +class _C {} +extension type E(_C c) {} +''', [ + lint(29, 2), + ]); + } + + test_extensionTypeDeclaration_typeParam() async { + await assertDiagnostics(r''' +class _C {} +extension type E(Object o) {} +''', [ + lint(39, 2), + ]); + } + + test_field_instance() async { + await assertDiagnostics(r''' +class _C {} +extension type E(Object o) { + _C? c; +} +''', [ + // No lint. + // todo(pq): add compilation error once reported + ]); + } + + test_field_static() async { + await assertDiagnostics(r''' +class _C {} +extension type E(Object o) { + static _C? c; +} +''', [ + lint(50, 2), + ]); + } + + test_method_instance_param() async { + await assertDiagnostics(r''' +class _C {} +extension type E(Object o) { + m(_C c){} +} +''', [ + lint(45, 2), + ]); + } + + test_method_instance_private_param() async { + await assertDiagnostics(r''' +class _C {} +extension type E(Object o) { + _m(_C c){} +} +''', [ + error(WarningCode.UNUSED_ELEMENT, 43, 2), + ]); + } + + test_method_instance_returnType() async { + await assertDiagnostics(r''' +class _C {} +extension type E(Object o) { + _C? m() => null; +} +''', [ + lint(43, 2), + ]); + } + + test_method_static_param() async { + await assertDiagnostics(r''' +class _C {} +extension type E(Object o) { + static m(_C c){} +} +''', [ + lint(52, 2), + ]); + } + + test_method_static_private_returnType() async { + await assertDiagnostics(r''' +class _C {} +extension type E(Object o) { + static _C? _m() => null; +} +''', [ + error(WarningCode.UNUSED_ELEMENT, 54, 2), + ]); + } + + test_method_static_returnType() async { + await assertDiagnostics(r''' +class _C {} +extension type E(Object o) { + static _C? m() => null; +} +''', [ + lint(50, 2), + ]); + } +} + @reflectiveTest class LibraryPrivateTypesInPublicApiSuperParamTest extends LintRuleTest { @override From e5a1523f50918533270e53cc4d2d9e5091409961 Mon Sep 17 00:00:00 2001 From: pq Date: Thu, 10 Aug 2023 13:41:31 -0700 Subject: [PATCH 2/2] ++ --- .../library_private_types_in_public_api.dart | 19 +++++++++++-------- ...rary_private_types_in_public_api_test.dart | 7 +++++++ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/lib/src/rules/library_private_types_in_public_api.dart b/lib/src/rules/library_private_types_in_public_api.dart index a3f6ae4e8..26043d78e 100644 --- a/lib/src/rules/library_private_types_in_public_api.dart +++ b/lib/src/rules/library_private_types_in_public_api.dart @@ -80,14 +80,6 @@ class Validator extends SimpleAstVisitor { node.members.accept(this); } - @override - void visitExtensionTypeDeclaration(ExtensionTypeDeclaration node) { - if (Identifier.isPrivateName(node.name.lexeme)) return; - node.typeParameters?.accept(this); - node.representation.fieldType.accept(this); - node.members.accept(this); - } - @override void visitClassTypeAlias(ClassTypeAlias node) { if (Identifier.isPrivateName(node.name.lexeme)) { @@ -140,6 +132,17 @@ class Validator extends SimpleAstVisitor { node.members.accept(this); } + @override + void visitExtensionTypeDeclaration(ExtensionTypeDeclaration node) { + if (Identifier.isPrivateName(node.name.lexeme)) return; + node.typeParameters?.accept(this); + var representation = node.representation; + if (!Identifier.isPrivateName(representation.fieldName.lexeme)) { + representation.fieldType.accept(this); + } + node.members.accept(this); + } + @override void visitFieldDeclaration(FieldDeclaration node) { if (node.isInvalidExtensionTypeField) return; diff --git a/test/rules/library_private_types_in_public_api_test.dart b/test/rules/library_private_types_in_public_api_test.dart index f52896b78..ecc17da4a 100644 --- a/test/rules/library_private_types_in_public_api_test.dart +++ b/test/rules/library_private_types_in_public_api_test.dart @@ -113,6 +113,13 @@ extension type E(_C c) {} ]); } + test_extensionTypeDeclaration_representation_private() async { + await assertNoDiagnostics(r''' +class _C {} +extension type E(_C _c) {} +'''); + } + test_extensionTypeDeclaration_typeParam() async { await assertDiagnostics(r''' class _C {}