Merge pull request #1756 from dart-lang/fix_diagnosticables
lint when no debug methods are defined
diff --git a/lib/src/rules/diagnostic_describe_all_properties.dart b/lib/src/rules/diagnostic_describe_all_properties.dart
index 201b18d..eaec832 100644
--- a/lib/src/rules/diagnostic_describe_all_properties.dart
+++ b/lib/src/rules/diagnostic_describe_all_properties.dart
@@ -71,7 +71,7 @@
name: 'diagnostic_describe_all_properties',
description: _desc,
details: _details,
- maturity: Maturity.experimental,
+ maturity: Maturity.stable,
group: Group.errors,
);
@@ -79,119 +79,16 @@
void registerNodeProcessors(
NodeLintRegistry registry, LinterContext context) {
final visitor = _Visitor(this, context);
- registry.addCompilationUnit(this, visitor);
registry.addClassDeclaration(this, visitor);
}
}
-// for experiments and book-keeping
-//int fileCount = 0;
-//int debugPropertyCount = 0;
-//int classesWithPropertiesButNoDebugFill = 0;
-
class _Visitor extends SimpleAstVisitor {
final LintRule rule;
final LinterContext context;
_Visitor(this.rule, this.context);
- // todo (pq): for experiments and book-keeping; remove before landing
- LineInfo lineInfo;
-
- @override
- visitCompilationUnit(CompilationUnit node) {
- lineInfo = node.lineInfo;
- }
-
-// static int noMethods = 0;
-// static int totalClasses = 0;
-
- bool _isOverridingMember(Element member) {
- if (member == null) {
- return false;
- }
-
- ClassElement classElement =
- member.getAncestor((element) => element is ClassElement);
- if (classElement == null) {
- return false;
- }
- Uri libraryUri = classElement.library.source.uri;
- return context.inheritanceManager.getInherited(
- classElement.thisType, Name(libraryUri, member.name)) !=
- null;
- }
-
- @override
- visitClassDeclaration(ClassDeclaration node) {
-// ++totalClasses;
-
- // We only care about Diagnosticables.
- var type = node.declaredElement.thisType;
- if (!DartTypeUtilities.implementsInterface(type, 'Diagnosticable', '')) {
- return;
- }
-
- var properties = <SimpleIdentifier>[];
- for (var member in node.members) {
- if (member is MethodDeclaration && member.isGetter) {
- if (!member.isStatic &&
- !skipForDiagnostic(
- element: member.declaredElement,
- name: member.name,
- type: member.returnType?.type,
- )) {
- properties.add(member.name);
- }
- } else if (member is FieldDeclaration) {
- for (var v in member.fields.variables) {
- if (!v.declaredElement.isStatic &&
- !skipForDiagnostic(
- element: v.declaredElement,
- name: v.name,
- type: v.declaredElement.type,
- )) {
- properties.add(v.name);
- }
- }
- }
- }
-
- if (properties.isEmpty) {
- return;
- }
-
- // todo (pq): move up to top when we're not counting anymore.
- var debugFillProperties = node.getMethod('debugFillProperties');
-// if (debugFillProperties == null) {
-// ++classesWithPropertiesButNoDebugFill;
-// }
-
- var debugDescribeChildren = node.getMethod('debugDescribeChildren');
- if (debugFillProperties == null && debugDescribeChildren == null) {
- return;
- }
-
- // Remove any defined in debugFillProperties.
- removeReferences(debugFillProperties, properties);
-
- // Remove any defined in debugDescribeChildren.
- removeReferences(debugDescribeChildren, properties);
-
- // Flag the rest.
- properties.forEach(rule.reportLint);
-
-// uncomment for data gathering
-// for (var prop in properties) {
-// var line = lineInfo.getLocation(prop.offset).lineNumber;
-// var prefix =
-// 'https://github.com/flutter/flutter/blob/master/packages/flutter/';
-// var path = node.element.source.fullName.split('packages/flutter/')[1];
-// print('| [$path:$line]($prefix$path#L$line) | ${node.name}.$prop |');
-// ++debugPropertyCount;
-// }
- }
-
void removeReferences(
MethodDeclaration method, List<SimpleIdentifier> properties) {
if (method == null) {
@@ -221,4 +118,70 @@
bool skipForDiagnostic(
{Element element, DartType type, SimpleIdentifier name}) =>
isPrivate(name) || _isOverridingMember(element) || isWidgetProperty(type);
+
+ @override
+ visitClassDeclaration(ClassDeclaration node) {
+ // We only care about Diagnosticables.
+ final type = node.declaredElement.thisType;
+ if (!DartTypeUtilities.implementsInterface(type, 'Diagnosticable', '')) {
+ return;
+ }
+
+ final properties = <SimpleIdentifier>[];
+ for (var member in node.members) {
+ if (member is MethodDeclaration && member.isGetter) {
+ if (!member.isStatic &&
+ !skipForDiagnostic(
+ element: member.declaredElement,
+ name: member.name,
+ type: member.returnType?.type,
+ )) {
+ properties.add(member.name);
+ }
+ } else if (member is FieldDeclaration) {
+ for (var v in member.fields.variables) {
+ if (!v.declaredElement.isStatic &&
+ !skipForDiagnostic(
+ element: v.declaredElement,
+ name: v.name,
+ type: v.declaredElement.type,
+ )) {
+ properties.add(v.name);
+ }
+ }
+ }
+ }
+
+ if (properties.isEmpty) {
+ return;
+ }
+
+ final debugFillProperties = node.getMethod('debugFillProperties');
+ final debugDescribeChildren = node.getMethod('debugDescribeChildren');
+
+ // Remove any defined in debugFillProperties.
+ removeReferences(debugFillProperties, properties);
+
+ // Remove any defined in debugDescribeChildren.
+ removeReferences(debugDescribeChildren, properties);
+
+ // Flag the rest.
+ properties.forEach(rule.reportLint);
+ }
+
+ bool _isOverridingMember(Element member) {
+ if (member == null) {
+ return false;
+ }
+
+ ClassElement classElement =
+ member.getAncestor((element) => element is ClassElement);
+ if (classElement == null) {
+ return false;
+ }
+ Uri libraryUri = classElement.library.source.uri;
+ return context.inheritanceManager.getInherited(
+ classElement.thisType, Name(libraryUri, member.name)) !=
+ null;
+ }
}
diff --git a/test/rules/diagnostic_describe_all_properties.dart b/test/rules/diagnostic_describe_all_properties.dart
index 6e88fd8..a002088 100644
--- a/test/rules/diagnostic_describe_all_properties.dart
+++ b/test/rules/diagnostic_describe_all_properties.dart
@@ -25,9 +25,9 @@
}
abstract class Diagnosticable {
- void debugFillProperties(DiagnosticPropertiesBuilder properties);
+ void debugFillProperties(DiagnosticPropertiesBuilder properties) { }
- List<DiagnosticsNode> debugDescribeChildren();
+ List<DiagnosticsNode> debugDescribeChildren() => <DiagnosticsNode>[];
}
class DiagnosticsNode {}
@@ -67,3 +67,7 @@
return null;
}
}
+
+class MyWidget2 extends Diagnosticable {
+ bool property; //LINT
+}