Skip to content

Commit 6b6e6da

Browse files
scheglovCommit Bot
authored andcommitted
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>
1 parent 7f8bf79 commit 6b6e6da

File tree

6 files changed

+156
-53
lines changed

6 files changed

+156
-53
lines changed

pkg/analyzer/lib/src/dart/analysis/driver.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ import 'package:meta/meta.dart';
8383
/// TODO(scheglov) Clean up the list of implicitly analyzed files.
8484
class AnalysisDriver implements AnalysisDriverGeneric {
8585
/// The version of data format, should be incremented on every format change.
86-
static const int DATA_VERSION = 212;
86+
static const int DATA_VERSION = 213;
8787

8888
/// The number of exception contexts allowed to write. Once this field is
8989
/// zero, we stop writing any new exception contexts in this process.

pkg/analyzer/lib/src/dart/analysis/unlinked_api_signature.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'dart:typed_data';
66

77
import 'package:analyzer/dart/ast/ast.dart';
88
import 'package:analyzer/dart/ast/token.dart';
9+
import 'package:analyzer/src/dart/ast/invokes_super_self.dart';
910
import 'package:analyzer/src/dart/ast/token.dart';
1011
import 'package:analyzer/src/summary/api_signature.dart';
1112
import 'package:collection/collection.dart';
@@ -140,6 +141,7 @@ class _UnitApiSignatureComputer {
140141
);
141142
signature.addBool(node.body is EmptyFunctionBody);
142143
_addFunctionBodyModifiers(node.body);
144+
signature.addBool(node.invokesSuperSelf);
143145
}
144146

145147
void _addNode(AstNode? node) {
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
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.
4+
5+
import 'package:analyzer/dart/ast/ast.dart';
6+
import 'package:analyzer/dart/ast/visitor.dart';
7+
8+
class _SuperVisitor extends RecursiveAstVisitor<void> {
9+
final String name;
10+
11+
/// Set to `true` if a super invocation with the [name] is found.
12+
bool hasSuperInvocation = false;
13+
14+
_SuperVisitor(this.name);
15+
16+
@override
17+
void visitAssignmentExpression(AssignmentExpression node) {
18+
var left = node.leftHandSide;
19+
if (left is PropertyAccess) {
20+
if (left.target is SuperExpression && left.propertyName.name == name) {
21+
hasSuperInvocation = true;
22+
return;
23+
}
24+
}
25+
super.visitAssignmentExpression(node);
26+
}
27+
28+
@override
29+
void visitBinaryExpression(BinaryExpression node) {
30+
if (node.leftOperand is SuperExpression && node.operator.lexeme == name) {
31+
hasSuperInvocation = true;
32+
return;
33+
}
34+
super.visitBinaryExpression(node);
35+
}
36+
37+
@override
38+
void visitMethodInvocation(MethodInvocation node) {
39+
if (node.target is SuperExpression && node.methodName.name == name) {
40+
hasSuperInvocation = true;
41+
return;
42+
}
43+
super.visitMethodInvocation(node);
44+
}
45+
46+
@override
47+
void visitPropertyAccess(PropertyAccess node) {
48+
if (node.target is SuperExpression && node.propertyName.name == name) {
49+
hasSuperInvocation = true;
50+
return;
51+
}
52+
super.visitPropertyAccess(node);
53+
}
54+
}
55+
56+
extension MethodDeclarationExtension on MethodDeclaration {
57+
bool get invokesSuperSelf {
58+
var visitor = _SuperVisitor(name.name);
59+
body.accept(visitor);
60+
return visitor.hasSuperInvocation;
61+
}
62+
}

pkg/analyzer/lib/src/dart/ast/mixin_super_invoked_names.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
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.
4+
15
import 'package:analyzer/dart/ast/ast.dart';
26
import 'package:analyzer/dart/ast/token.dart';
37
import 'package:analyzer/dart/ast/visitor.dart';

pkg/analyzer/lib/src/error/must_call_super_verifier.dart

Lines changed: 2 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
import 'dart:collection';
66

77
import 'package:analyzer/dart/ast/ast.dart';
8-
import 'package:analyzer/dart/ast/visitor.dart';
98
import 'package:analyzer/dart/element/element.dart';
109
import 'package:analyzer/error/listener.dart';
10+
import 'package:analyzer/src/dart/ast/invokes_super_self.dart';
1111
import 'package:analyzer/src/dart/error/hint_codes.dart';
1212

1313
class MustCallSuperVerifier {
@@ -133,9 +133,7 @@ class MustCallSuperVerifier {
133133

134134
void _verifySuperIsCalled(MethodDeclaration node, String methodName,
135135
String? overriddenEnclosingName) {
136-
_SuperCallVerifier verifier = _SuperCallVerifier(methodName);
137-
node.accept(verifier);
138-
if (!verifier.superIsCalled) {
136+
if (!node.invokesSuperSelf) {
139137
// Overridable elements are always enclosed in named elements, so it is
140138
// safe to assume [overriddenEnclosingName] is non-`null`.
141139
_errorReporter.reportErrorForNode(
@@ -144,51 +142,3 @@ class MustCallSuperVerifier {
144142
return;
145143
}
146144
}
147-
148-
/// Recursively visits an AST, looking for method invocations.
149-
class _SuperCallVerifier extends RecursiveAstVisitor<void> {
150-
bool superIsCalled = false;
151-
152-
final String name;
153-
154-
_SuperCallVerifier(this.name);
155-
156-
@override
157-
void visitAssignmentExpression(AssignmentExpression node) {
158-
var lhs = node.leftHandSide;
159-
if (lhs is PropertyAccess) {
160-
if (lhs.target is SuperExpression && lhs.propertyName.name == name) {
161-
superIsCalled = true;
162-
return;
163-
}
164-
}
165-
super.visitAssignmentExpression(node);
166-
}
167-
168-
@override
169-
void visitBinaryExpression(BinaryExpression node) {
170-
if (node.leftOperand is SuperExpression && node.operator.lexeme == name) {
171-
superIsCalled = true;
172-
return;
173-
}
174-
super.visitBinaryExpression(node);
175-
}
176-
177-
@override
178-
void visitMethodInvocation(MethodInvocation node) {
179-
if (node.target is SuperExpression && node.methodName.name == name) {
180-
superIsCalled = true;
181-
return;
182-
}
183-
super.visitMethodInvocation(node);
184-
}
185-
186-
@override
187-
void visitPropertyAccess(PropertyAccess node) {
188-
if (node.target is SuperExpression && node.propertyName.name == name) {
189-
superIsCalled = true;
190-
return;
191-
}
192-
super.visitPropertyAccess(node);
193-
}
194-
}

pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,83 @@ static const int a = 2;
457457
''');
458458
}
459459

460+
test_classLike_method_body_block_invokesSuperSelf_false_differentName() {
461+
_assertSameSignature_classLike(r'''
462+
void foo() {
463+
super.bar();
464+
}
465+
''', r'''
466+
void foo() {
467+
super.bar2();
468+
}
469+
''');
470+
}
471+
472+
test_classLike_method_body_block_invokesSuperSelf_falseToTrue() {
473+
_assertNotSameSignature_classLike(r'''
474+
void foo() {}
475+
''', r'''
476+
void foo() {
477+
super.foo();
478+
}
479+
''');
480+
}
481+
482+
test_classLike_method_body_block_invokesSuperSelf_trueToFalse_assignmentExpression() {
483+
_assertNotSameSignature_classLike(r'''
484+
void foo() {
485+
super.foo = 0;
486+
}
487+
''', r'''
488+
void foo() {}
489+
''');
490+
}
491+
492+
test_classLike_method_body_block_invokesSuperSelf_trueToFalse_binaryExpression() {
493+
_assertNotSameSignature_classLike(r'''
494+
int operator +() {
495+
super + 2;
496+
return 0;
497+
}
498+
''', r'''
499+
int operator +() {
500+
return 0;
501+
}
502+
''');
503+
}
504+
505+
test_classLike_method_body_block_invokesSuperSelf_trueToFalse_differentName() {
506+
_assertNotSameSignature_classLike(r'''
507+
void foo() {
508+
super.foo();
509+
}
510+
''', r'''
511+
void foo() {
512+
super.bar();
513+
}
514+
''');
515+
}
516+
517+
test_classLike_method_body_block_invokesSuperSelf_trueToFalse_methodInvocation() {
518+
_assertNotSameSignature_classLike(r'''
519+
void foo() {
520+
super.foo();
521+
}
522+
''', r'''
523+
void foo() {}
524+
''');
525+
}
526+
527+
test_classLike_method_body_block_invokesSuperSelf_trueToFalse_propertyAccess() {
528+
_assertNotSameSignature_classLike(r'''
529+
void foo() {
530+
super.foo;
531+
}
532+
''', r'''
533+
void foo() {}
534+
''');
535+
}
536+
460537
test_classLike_method_body_block_to_empty() {
461538
_assertNotSameSignature_classLike(r'''
462539
void foo() {}
@@ -481,6 +558,14 @@ int foo() => 0;
481558
''');
482559
}
483560

561+
test_classLike_method_body_expression_invokesSuperSelf_trueToFalse_methodInvocation() {
562+
_assertNotSameSignature_classLike(r'''
563+
void foo() => super.foo();
564+
''', r'''
565+
void foo() => 0;
566+
''');
567+
}
568+
484569
test_classLike_method_getter_body_block_to_empty() {
485570
_assertNotSameSignature_classLike(r'''
486571
int get foo {

0 commit comments

Comments
 (0)