mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 22:59:47 +00:00
Include 'invokesSuperSelf' flag into unlinked API signature.
We will add this flag as a property of MethodElement. So, it will affect the semantics, and should be a part of unlinked signature. Change-Id: If24b09fcd000364a2ddb3737baa69af3d1c6fbd5 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/240641 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
7f8bf79ad8
commit
6b6e6da943
|
@ -83,7 +83,7 @@ import 'package:meta/meta.dart';
|
|||
/// TODO(scheglov) Clean up the list of implicitly analyzed files.
|
||||
class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
/// The version of data format, should be incremented on every format change.
|
||||
static const int DATA_VERSION = 212;
|
||||
static const int DATA_VERSION = 213;
|
||||
|
||||
/// The number of exception contexts allowed to write. Once this field is
|
||||
/// zero, we stop writing any new exception contexts in this process.
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'dart:typed_data';
|
|||
|
||||
import 'package:analyzer/dart/ast/ast.dart';
|
||||
import 'package:analyzer/dart/ast/token.dart';
|
||||
import 'package:analyzer/src/dart/ast/invokes_super_self.dart';
|
||||
import 'package:analyzer/src/dart/ast/token.dart';
|
||||
import 'package:analyzer/src/summary/api_signature.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
|
@ -140,6 +141,7 @@ class _UnitApiSignatureComputer {
|
|||
);
|
||||
signature.addBool(node.body is EmptyFunctionBody);
|
||||
_addFunctionBodyModifiers(node.body);
|
||||
signature.addBool(node.invokesSuperSelf);
|
||||
}
|
||||
|
||||
void _addNode(AstNode? node) {
|
||||
|
|
62
pkg/analyzer/lib/src/dart/ast/invokes_super_self.dart
Normal file
62
pkg/analyzer/lib/src/dart/ast/invokes_super_self.dart
Normal file
|
@ -0,0 +1,62 @@
|
|||
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:analyzer/dart/ast/ast.dart';
|
||||
import 'package:analyzer/dart/ast/visitor.dart';
|
||||
|
||||
class _SuperVisitor extends RecursiveAstVisitor<void> {
|
||||
final String name;
|
||||
|
||||
/// Set to `true` if a super invocation with the [name] is found.
|
||||
bool hasSuperInvocation = false;
|
||||
|
||||
_SuperVisitor(this.name);
|
||||
|
||||
@override
|
||||
void visitAssignmentExpression(AssignmentExpression node) {
|
||||
var left = node.leftHandSide;
|
||||
if (left is PropertyAccess) {
|
||||
if (left.target is SuperExpression && left.propertyName.name == name) {
|
||||
hasSuperInvocation = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.visitAssignmentExpression(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitBinaryExpression(BinaryExpression node) {
|
||||
if (node.leftOperand is SuperExpression && node.operator.lexeme == name) {
|
||||
hasSuperInvocation = true;
|
||||
return;
|
||||
}
|
||||
super.visitBinaryExpression(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitMethodInvocation(MethodInvocation node) {
|
||||
if (node.target is SuperExpression && node.methodName.name == name) {
|
||||
hasSuperInvocation = true;
|
||||
return;
|
||||
}
|
||||
super.visitMethodInvocation(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitPropertyAccess(PropertyAccess node) {
|
||||
if (node.target is SuperExpression && node.propertyName.name == name) {
|
||||
hasSuperInvocation = true;
|
||||
return;
|
||||
}
|
||||
super.visitPropertyAccess(node);
|
||||
}
|
||||
}
|
||||
|
||||
extension MethodDeclarationExtension on MethodDeclaration {
|
||||
bool get invokesSuperSelf {
|
||||
var visitor = _SuperVisitor(name.name);
|
||||
body.accept(visitor);
|
||||
return visitor.hasSuperInvocation;
|
||||
}
|
||||
}
|
|
@ -1,3 +1,7 @@
|
|||
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:analyzer/dart/ast/ast.dart';
|
||||
import 'package:analyzer/dart/ast/token.dart';
|
||||
import 'package:analyzer/dart/ast/visitor.dart';
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
import 'dart:collection';
|
||||
|
||||
import 'package:analyzer/dart/ast/ast.dart';
|
||||
import 'package:analyzer/dart/ast/visitor.dart';
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:analyzer/error/listener.dart';
|
||||
import 'package:analyzer/src/dart/ast/invokes_super_self.dart';
|
||||
import 'package:analyzer/src/dart/error/hint_codes.dart';
|
||||
|
||||
class MustCallSuperVerifier {
|
||||
|
@ -133,9 +133,7 @@ class MustCallSuperVerifier {
|
|||
|
||||
void _verifySuperIsCalled(MethodDeclaration node, String methodName,
|
||||
String? overriddenEnclosingName) {
|
||||
_SuperCallVerifier verifier = _SuperCallVerifier(methodName);
|
||||
node.accept(verifier);
|
||||
if (!verifier.superIsCalled) {
|
||||
if (!node.invokesSuperSelf) {
|
||||
// Overridable elements are always enclosed in named elements, so it is
|
||||
// safe to assume [overriddenEnclosingName] is non-`null`.
|
||||
_errorReporter.reportErrorForNode(
|
||||
|
@ -144,51 +142,3 @@ class MustCallSuperVerifier {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// Recursively visits an AST, looking for method invocations.
|
||||
class _SuperCallVerifier extends RecursiveAstVisitor<void> {
|
||||
bool superIsCalled = false;
|
||||
|
||||
final String name;
|
||||
|
||||
_SuperCallVerifier(this.name);
|
||||
|
||||
@override
|
||||
void visitAssignmentExpression(AssignmentExpression node) {
|
||||
var lhs = node.leftHandSide;
|
||||
if (lhs is PropertyAccess) {
|
||||
if (lhs.target is SuperExpression && lhs.propertyName.name == name) {
|
||||
superIsCalled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.visitAssignmentExpression(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitBinaryExpression(BinaryExpression node) {
|
||||
if (node.leftOperand is SuperExpression && node.operator.lexeme == name) {
|
||||
superIsCalled = true;
|
||||
return;
|
||||
}
|
||||
super.visitBinaryExpression(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitMethodInvocation(MethodInvocation node) {
|
||||
if (node.target is SuperExpression && node.methodName.name == name) {
|
||||
superIsCalled = true;
|
||||
return;
|
||||
}
|
||||
super.visitMethodInvocation(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitPropertyAccess(PropertyAccess node) {
|
||||
if (node.target is SuperExpression && node.propertyName.name == name) {
|
||||
superIsCalled = true;
|
||||
return;
|
||||
}
|
||||
super.visitPropertyAccess(node);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -457,6 +457,83 @@ static const int a = 2;
|
|||
''');
|
||||
}
|
||||
|
||||
test_classLike_method_body_block_invokesSuperSelf_false_differentName() {
|
||||
_assertSameSignature_classLike(r'''
|
||||
void foo() {
|
||||
super.bar();
|
||||
}
|
||||
''', r'''
|
||||
void foo() {
|
||||
super.bar2();
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_classLike_method_body_block_invokesSuperSelf_falseToTrue() {
|
||||
_assertNotSameSignature_classLike(r'''
|
||||
void foo() {}
|
||||
''', r'''
|
||||
void foo() {
|
||||
super.foo();
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_classLike_method_body_block_invokesSuperSelf_trueToFalse_assignmentExpression() {
|
||||
_assertNotSameSignature_classLike(r'''
|
||||
void foo() {
|
||||
super.foo = 0;
|
||||
}
|
||||
''', r'''
|
||||
void foo() {}
|
||||
''');
|
||||
}
|
||||
|
||||
test_classLike_method_body_block_invokesSuperSelf_trueToFalse_binaryExpression() {
|
||||
_assertNotSameSignature_classLike(r'''
|
||||
int operator +() {
|
||||
super + 2;
|
||||
return 0;
|
||||
}
|
||||
''', r'''
|
||||
int operator +() {
|
||||
return 0;
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_classLike_method_body_block_invokesSuperSelf_trueToFalse_differentName() {
|
||||
_assertNotSameSignature_classLike(r'''
|
||||
void foo() {
|
||||
super.foo();
|
||||
}
|
||||
''', r'''
|
||||
void foo() {
|
||||
super.bar();
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_classLike_method_body_block_invokesSuperSelf_trueToFalse_methodInvocation() {
|
||||
_assertNotSameSignature_classLike(r'''
|
||||
void foo() {
|
||||
super.foo();
|
||||
}
|
||||
''', r'''
|
||||
void foo() {}
|
||||
''');
|
||||
}
|
||||
|
||||
test_classLike_method_body_block_invokesSuperSelf_trueToFalse_propertyAccess() {
|
||||
_assertNotSameSignature_classLike(r'''
|
||||
void foo() {
|
||||
super.foo;
|
||||
}
|
||||
''', r'''
|
||||
void foo() {}
|
||||
''');
|
||||
}
|
||||
|
||||
test_classLike_method_body_block_to_empty() {
|
||||
_assertNotSameSignature_classLike(r'''
|
||||
void foo() {}
|
||||
|
@ -481,6 +558,14 @@ int foo() => 0;
|
|||
''');
|
||||
}
|
||||
|
||||
test_classLike_method_body_expression_invokesSuperSelf_trueToFalse_methodInvocation() {
|
||||
_assertNotSameSignature_classLike(r'''
|
||||
void foo() => super.foo();
|
||||
''', r'''
|
||||
void foo() => 0;
|
||||
''');
|
||||
}
|
||||
|
||||
test_classLike_method_getter_body_block_to_empty() {
|
||||
_assertNotSameSignature_classLike(r'''
|
||||
int get foo {
|
||||
|
|
Loading…
Reference in a new issue