Chromium Code Reviews| 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 59359c19e033baa505730e881a6fa2a963e29a0b..66f6fc4235e2cb8221d8b650429184a141b0ce89 100644 |
| --- a/pkg/analyzer/lib/src/generated/resolver.dart |
| +++ b/pkg/analyzer/lib/src/generated/resolver.dart |
| @@ -206,6 +206,7 @@ class BestPracticesVerifier extends RecursiveAstVisitor<Object> { |
| @override |
| Object visitMethodInvocation(MethodInvocation node) { |
| _checkForCanBeNullAfterNullAware(node.realTarget, node.operator); |
| + _checkForInvalidProtectedMethodCalls(node); |
| return super.visitMethodInvocation(node); |
| } |
| @@ -608,6 +609,38 @@ class BestPracticesVerifier extends RecursiveAstVisitor<Object> { |
| } |
| /** |
| + * Produces a hint if the given invocation is of a protected method outside |
| + * a subclass instance method. |
| + */ |
| + void _checkForInvalidProtectedMethodCalls(MethodInvocation node) { |
| + Element element = node.methodName.staticElement; |
|
Brian Wilkerson
2016/02/23 17:45:56
Given that this is a hint, I suspect that we want
pquitslund
2016/02/23 22:59:07
Done.
|
| + if (element == null || !element.isProtected) { |
| + return; |
| + } |
| + |
| + ClassElement definingClass = element.enclosingElement; |
| + |
| + MethodDeclaration decl = |
| + node.getAncestor((AstNode node) => node is MethodDeclaration); |
| + if (decl == null) { |
| + _errorReporter.reportErrorForNode( |
| + HintCode.INVALID_USE_OF_PROTECTED_MEMBER, |
| + node, |
| + [node.methodName.toString(), definingClass.name]); |
| + return; |
| + } |
| + |
| + ClassElement invokingClass = decl.element?.enclosingElement; |
| + if (invokingClass != null && |
| + !invokingClass.type.isSubtypeOf(definingClass.type)) { |
|
Brian Wilkerson
2016/02/23 17:45:56
The comment for the annotation says "extend or mix
pquitslund
2016/02/23 22:59:07
Fixed.
|
| + _errorReporter.reportErrorForNode( |
| + HintCode.INVALID_USE_OF_PROTECTED_MEMBER, |
| + node, |
| + [node.methodName.toString(), definingClass.name]); |
| + } |
| + } |
| + |
| + /** |
| * Check that the imported library does not define a loadLibrary function. The import has already |
| * been determined to be deferred when this is called. |
| * |
| @@ -8387,26 +8420,6 @@ class ResolverVisitor extends ScopedVisitor { |
| return null; |
| } |
| - void _inferArgumentTypesFromContext(InvocationExpression node) { |
| - DartType contextType = node.staticInvokeType; |
| - if (contextType is FunctionType) { |
| - DartType originalType = node.function.staticType; |
| - DartType returnContextType = InferenceContext.getType(node); |
| - TypeSystem ts = typeSystem; |
| - if (returnContextType != null && |
| - node.typeArguments == null && |
| - originalType is FunctionType && |
| - originalType.typeFormals.isNotEmpty && |
| - ts is StrongTypeSystemImpl) { |
| - |
| - contextType = ts.inferGenericFunctionCall(typeProvider, originalType, |
| - DartType.EMPTY_LIST, DartType.EMPTY_LIST, returnContextType); |
| - } |
| - |
| - InferenceContext.setType(node.argumentList, contextType); |
| - } |
| - } |
| - |
| @override |
| Object visitNamedExpression(NamedExpression node) { |
| InferenceContext.setType(node.expression, InferenceContext.getType(node)); |
| @@ -8734,6 +8747,25 @@ class ResolverVisitor extends ScopedVisitor { |
| return null; |
| } |
| + void _inferArgumentTypesFromContext(InvocationExpression node) { |
| + DartType contextType = node.staticInvokeType; |
| + if (contextType is FunctionType) { |
| + DartType originalType = node.function.staticType; |
| + DartType returnContextType = InferenceContext.getType(node); |
| + TypeSystem ts = typeSystem; |
| + if (returnContextType != null && |
| + node.typeArguments == null && |
| + originalType is FunctionType && |
| + originalType.typeFormals.isNotEmpty && |
| + ts is StrongTypeSystemImpl) { |
| + contextType = ts.inferGenericFunctionCall(typeProvider, originalType, |
| + DartType.EMPTY_LIST, DartType.EMPTY_LIST, returnContextType); |
| + } |
| + |
| + InferenceContext.setType(node.argumentList, contextType); |
| + } |
| + } |
| + |
| void _inferFormalParameterList(FormalParameterList node, DartType type) { |
| if (typeAnalyzer.inferFormalParameterList(node, type)) { |
| // TODO(leafp): This gets dropped on the floor if we're in the field |