Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(548)

Unified Diff: pkg/analyzer/lib/src/generated/resolver.dart

Issue 2096103002: Analyzer support for `@factory` methods (linter#253). (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Allow decls w/o a return type. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/analyzer/lib/src/generated/error.dart ('k') | pkg/analyzer/test/generated/hint_code_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/generated/resolver.dart
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index cfb6b8990b4d311c1b85e87220b9e6e9462fa186..474642ae4338266461ab1140774d7ff043a4056b 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -91,6 +91,20 @@ class BestPracticesVerifier extends RecursiveAstVisitor<Object> {
_typeSystem = typeSystem ?? new TypeSystemImpl();
@override
+ Object visitAnnotation(Annotation node) {
+ if (node.elementAnnotation?.isFactory == true) {
+ AstNode parent = node.parent;
+ if (parent is MethodDeclaration) {
+ _checkForInvalidFactory(parent);
+ } else {
+ _errorReporter
+ .reportErrorForNode(HintCode.INVALID_FACTORY_ANNOTATION, node, []);
+ }
+ }
+ return super.visitAnnotation(node);
+ }
+
+ @override
Object visitArgumentList(ArgumentList node) {
for (Expression argument in node.arguments) {
ParameterElement parameter = argument.bestParameterElement;
@@ -674,6 +688,44 @@ class BestPracticesVerifier extends RecursiveAstVisitor<Object> {
return false;
}
+ void _checkForInvalidFactory(MethodDeclaration decl) {
+ // Check declaration.
+ // Note that null return types are expected to be flagged by other analyses.
+ DartType returnType = decl.returnType?.type;
+ if (returnType is VoidType) {
+ _errorReporter.reportErrorForNode(HintCode.INVALID_FACTORY_METHOD_DECL,
+ decl.name, [decl.name.toString()]);
+ return;
+ }
+
+ // Check implementation.
+
+ FunctionBody body = decl.body;
+ if (body is EmptyFunctionBody) {
+ // Abstract methods are OK.
+ return;
+ }
+
+ // `new Foo()` or `null`.
+ bool factoryExpression(Expression expression) =>
+ expression is InstanceCreationExpression || expression is NullLiteral;
+
+ if (body is ExpressionFunctionBody && factoryExpression(body.expression)) {
+ return;
+ } else if (body is BlockFunctionBody) {
+ NodeList<Statement> statements = body.block.statements;
+ if (statements.isNotEmpty) {
+ Statement last = statements.last;
+ if (last is ReturnStatement && factoryExpression(last.expression)) {
+ return;
+ }
+ }
+ }
+
+ _errorReporter.reportErrorForNode(HintCode.INVALID_FACTORY_METHOD_IMPL,
+ decl.name, [decl.name.toString()]);
+ }
+
/**
* Produces a hint if the given identifier is a protected closure, field or
* getter/setter, method closure or invocation accessed outside a subclass.
« no previous file with comments | « pkg/analyzer/lib/src/generated/error.dart ('k') | pkg/analyzer/test/generated/hint_code_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698