OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library linter.src.rules.public_member_api_docs; | 5 library linter.src.rules.public_member_api_docs; |
6 | 6 |
7 import 'package:analyzer/src/generated/ast.dart'; | 7 import 'package:analyzer/src/generated/ast.dart'; |
| 8 import 'package:analyzer/src/generated/element.dart'; |
| 9 import 'package:analyzer/src/generated/resolver.dart'; |
8 import 'package:linter/src/ast.dart'; | 10 import 'package:linter/src/ast.dart'; |
9 import 'package:linter/src/linter.dart'; | 11 import 'package:linter/src/linter.dart'; |
10 | 12 |
11 const desc = r'Document all public members'; | 13 const desc = r'Document all public members'; |
12 | 14 |
13 const details = r''' | 15 const details = r''' |
14 **DO** document all public members. | 16 **DO** document all public members. |
15 | 17 |
16 All public members should be documented with `///` doc-style comments. | 18 All non-overriding public members should be documented with `///` doc-style |
| 19 comments. |
17 | 20 |
18 **Good:** | 21 **Good:** |
19 ``` | 22 ``` |
20 /// A good thing. | 23 /// A good thing. |
21 abstract class Good { | 24 abstract class Good { |
22 /// Start doing your thing. | 25 /// Start doing your thing. |
23 void start() => _start(); | 26 void start() => _start(); |
24 | 27 |
25 _start(); | 28 _start(); |
26 } | 29 } |
27 ``` | 30 ``` |
28 | 31 |
29 **Bad:** | 32 **Bad:** |
30 ``` | 33 ``` |
31 class Bad { | 34 class Bad { |
32 void meh(); | 35 void meh() { } |
| 36 } |
| 37 ``` |
| 38 |
| 39 In case a public member overrides a member it is up to the declaring member |
| 40 to provide documentation. For example, in the following, `Sub` needn't |
| 41 document `init` (though it certainly may, if there's need). |
| 42 |
| 43 **Good:** |
| 44 ``` |
| 45 /// Base of all things. |
| 46 abstract class Base { |
| 47 /// Initialize the base. |
| 48 void init(); |
| 49 } |
| 50 |
| 51 /// A sub base. |
| 52 class Sub extends Base { |
| 53 @override |
| 54 void init() { ... } |
33 } | 55 } |
34 ``` | 56 ``` |
35 '''; | 57 '''; |
36 | 58 |
37 class PublicMemberApiDocs extends LintRule { | 59 class PublicMemberApiDocs extends LintRule { |
38 PublicMemberApiDocs() | 60 PublicMemberApiDocs() |
39 : super( | 61 : super( |
40 name: 'public_member_api_docs', | 62 name: 'public_member_api_docs', |
41 description: desc, | 63 description: desc, |
42 details: details, | 64 details: details, |
43 group: Group.style); | 65 group: Group.style); |
44 | 66 |
45 @override | 67 @override |
46 AstVisitor getVisitor() => new Visitor(this); | 68 AstVisitor getVisitor() => new Visitor(this); |
47 } | 69 } |
48 | 70 |
49 class Visitor extends GeneralizingAstVisitor { | 71 class Visitor extends GeneralizingAstVisitor { |
| 72 InheritanceManager manager; |
| 73 |
50 final LintRule rule; | 74 final LintRule rule; |
51 Visitor(this.rule); | 75 Visitor(this.rule); |
52 | 76 |
53 void check(Declaration node) { | 77 void check(Declaration node) { |
54 if (node.documentationComment == null && !hasOverrideAnnotation(node)) { | 78 if (node.documentationComment == null && !isOverridingMember(node)) { |
55 rule.reportLint(getNodeToAnnotate(node)); | 79 rule.reportLint(getNodeToAnnotate(node)); |
56 } | 80 } |
57 } | 81 } |
58 | 82 |
| 83 bool isOverridingMember(Declaration node) => |
| 84 getOverriddenMember(node.element) != null; |
| 85 |
| 86 ExecutableElement getOverriddenMember(Element member) { |
| 87 if (member == null || manager == null) { |
| 88 return null; |
| 89 } |
| 90 |
| 91 ClassElement classElement = |
| 92 member.getAncestor((element) => element is ClassElement); |
| 93 if (classElement == null) { |
| 94 return null; |
| 95 } |
| 96 return manager.lookupInheritance(classElement, member.name); |
| 97 } |
| 98 |
59 @override | 99 @override |
60 visitClassDeclaration(ClassDeclaration node) { | 100 visitClassDeclaration(ClassDeclaration node) { |
61 if (!isPrivate(node.name)) { | 101 if (!isPrivate(node.name)) { |
62 check(node); | 102 check(node); |
63 } | 103 } |
64 } | 104 } |
65 | 105 |
66 @override | 106 @override |
67 visitClassTypeAlias(ClassTypeAlias node) { | 107 visitClassTypeAlias(ClassTypeAlias node) { |
68 if (!isPrivate(node.name)) { | 108 if (!isPrivate(node.name)) { |
69 check(node); | 109 check(node); |
70 } | 110 } |
71 } | 111 } |
72 | 112 |
73 @override | 113 @override |
| 114 visitCompilationUnit(CompilationUnit node) { |
| 115 LibraryElement library = node?.element?.library; |
| 116 manager = library == null ? null : new InheritanceManager(library); |
| 117 super.visitCompilationUnit(node); |
| 118 } |
| 119 |
| 120 @override |
74 visitConstructorDeclaration(ConstructorDeclaration node) { | 121 visitConstructorDeclaration(ConstructorDeclaration node) { |
75 if (!inPrivateMember(node) && !isPrivate(node.name)) { | 122 if (!inPrivateMember(node) && !isPrivate(node.name)) { |
76 check(node); | 123 check(node); |
77 } | 124 } |
78 } | 125 } |
79 | 126 |
80 @override | 127 @override |
81 visitEnumConstantDeclaration(EnumConstantDeclaration node) { | 128 visitEnumConstantDeclaration(EnumConstantDeclaration node) { |
82 if (!inPrivateMember(node) && !isPrivate(node.name)) { | 129 if (!inPrivateMember(node) && !isPrivate(node.name)) { |
83 check(node); | 130 check(node); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 | 175 |
129 @override | 176 @override |
130 visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { | 177 visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { |
131 for (VariableDeclaration decl in node.variables.variables) { | 178 for (VariableDeclaration decl in node.variables.variables) { |
132 if (!isPrivate(decl.name)) { | 179 if (!isPrivate(decl.name)) { |
133 check(decl); | 180 check(decl); |
134 } | 181 } |
135 } | 182 } |
136 } | 183 } |
137 } | 184 } |
OLD | NEW |