Skip to content

Commit 3c2f59d

Browse files
johnniwintherCommit Queue
authored andcommitted
[cfe] Improve predicate helper for extension (type) members
This adds support for computing the qualified name for all extension and extension type members. The `lowering_predicates_test.dart` is removed and testing is performed through `predicate_test.dart`. Change-Id: I334bb85d48b6b1fd8fa01de6576f61168b3e96fa Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/424443 Reviewed-by: Jens Johansen <[email protected]> Commit-Queue: Johnni Winther <[email protected]>
1 parent 10c579c commit 3c2f59d

16 files changed

+243
-95
lines changed

pkg/front_end/lib/src/api_prototype/lowering_predicates.dart

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import 'package:kernel/ast.dart';
66

77
import '../kernel/late_lowering.dart';
8+
import '../source/name_scheme.dart';
89

910
export '../kernel/constructor_tearoff_lowering.dart'
1011
show
@@ -845,10 +846,78 @@ String createJoinedIntermediateName(String variableName, int index) {
845846
return '$variableName$joinedIntermediateInfix$index';
846847
}
847848

848-
/// This turns Foo|bar into Foo.bar.
849+
const String unnamedExtensionSentinel = '<unnamed extension>';
850+
851+
/// Returns the qualified name of an extension or extension type member.
852+
///
853+
/// This turns `Foo|bar` and `Foo|get#bar` into `Foo.bar`.
854+
///
855+
/// For members of unnamed extensions, the extension name
856+
/// [unnamedExtensionSentinel] is used.
857+
///
858+
/// No-name extension type constructors use `new` as the name.
859+
///
860+
/// DartDocTest(
861+
/// extractQualifiedNameFromExtensionMethodName(null),
862+
/// null)
863+
/// DartDocTest(
864+
/// extractQualifiedNameFromExtensionMethodName('Foo'),
865+
/// null)
866+
/// DartDocTest(
867+
/// extractQualifiedNameFromExtensionMethodName('Foo|bar'),
868+
/// 'Foo.bar')
869+
/// DartDocTest(
870+
/// extractQualifiedNameFromExtensionMethodName('Foo|get#bar'),
871+
/// 'Foo.bar')
872+
/// DartDocTest(
873+
/// extractQualifiedNameFromExtensionMethodName('Foo|set#bar'),
874+
/// 'Foo.bar')
875+
/// DartDocTest(
876+
/// extractQualifiedNameFromExtensionMethodName('Foo|constructor#bar'),
877+
/// 'Foo.bar')
878+
/// DartDocTest(
879+
/// extractQualifiedNameFromExtensionMethodName('_extension#1|bar'),
880+
/// '<unnamed extension>.bar')
881+
/// DartDocTest(
882+
/// extractQualifiedNameFromExtensionMethodName('_extension#2|get#bar'),
883+
/// '<unnamed extension>.bar')
884+
/// DartDocTest(
885+
/// extractQualifiedNameFromExtensionMethodName('_extension#3|set#bar'),
886+
/// '<unnamed extension>.bar')
849887
///
850-
/// This only works for normal methods and operators, but for getters and
851-
/// setters.
852888
String? extractQualifiedNameFromExtensionMethodName(String? methodName) {
853-
return methodName?.replaceFirst('|', '.');
889+
if (methodName == null) return null;
890+
int delimiterIndex = methodName.indexOf(NameScheme.extensionNameDelimiter);
891+
if (delimiterIndex == -1) return null;
892+
String extensionName = methodName.substring(0, delimiterIndex);
893+
if (extensionName.startsWith(NameScheme.unnamedExtensionNamePrefix)) {
894+
extensionName = unnamedExtensionSentinel;
895+
}
896+
String memberName = methodName
897+
.substring(delimiterIndex + NameScheme.extensionNameDelimiter.length);
898+
if (memberName.startsWith(NameScheme.extensionTypeConstructorPrefix)) {
899+
memberName =
900+
memberName.substring(NameScheme.extensionTypeConstructorPrefix.length);
901+
}
902+
if (memberName.startsWith(NameScheme.extensionGetterPrefix)) {
903+
memberName = memberName.substring(NameScheme.extensionGetterPrefix.length);
904+
}
905+
if (memberName.startsWith(NameScheme.extensionSetterPrefix)) {
906+
// Coverage-ignore-block(suite): Not run.
907+
memberName = memberName.substring(NameScheme.extensionSetterPrefix.length);
908+
}
909+
if (memberName.isEmpty) {
910+
memberName = 'new';
911+
}
912+
return '$extensionName.$memberName';
913+
}
914+
915+
// Coverage-ignore(suite): Not run.
916+
/// Returns the qualified name of [member] if it is an extension or extension
917+
/// type member, and otherwise `null`.
918+
String? extractQualifiedNameFromExtensionMember(Member member) {
919+
if (member.isExtensionMember || member.isExtensionTypeMember) {
920+
return extractQualifiedNameFromExtensionMethodName(member.name.text);
921+
}
922+
return null;
854923
}

pkg/front_end/lib/src/base/incremental_compiler.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2652,6 +2652,7 @@ class _ComponentProblems {
26522652
// Report old problems that wasn't reported again.
26532653
for (MapEntry<Uri, List<DiagnosticMessageFromJson>> entry
26542654
in _remainingComponentProblems.entries) {
2655+
// Coverage-ignore-block(suite): Not run.
26552656
List<DiagnosticMessageFromJson> messages = entry.value;
26562657
for (int i = 0; i < messages.length; i++) {
26572658
DiagnosticMessageFromJson message = messages[i];

pkg/front_end/lib/src/codes/type_labeler.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,9 @@ class TypeLabeler implements DartTypeVisitor<void>, ConstantVisitor<void> {
370370
result.add(">[");
371371
bool first = true;
372372
for (Constant constant in node.entries) {
373-
if (!first) result.add(", ");
373+
if (!first) {
374+
result.add(", ");
375+
}
374376
constant.accept(this);
375377
first = false;
376378
}

pkg/front_end/lib/src/source/name_scheme.dart

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -124,20 +124,11 @@ class NameScheme {
124124
}
125125
}
126126

127-
// Coverage-ignore(suite): Not run.
128-
static String createProcedureNameForTesting(
129-
{required ContainerName? containerName,
130-
required ContainerType containerType,
131-
required bool isStatic,
132-
required ProcedureKind kind,
133-
required String name}) {
134-
return _createProcedureName(
135-
containerName: containerName,
136-
containerType: containerType,
137-
isStatic: isStatic,
138-
kind: kind,
139-
name: name);
140-
}
127+
static const String extensionTypeConstructorPrefix = 'constructor#';
128+
static const String extensionGetterPrefix = 'get#';
129+
static const String extensionSetterPrefix = 'set#';
130+
static const String extensionNameDelimiter = '|';
131+
static const String unnamedExtensionNamePrefix = '_extension#';
141132

142133
static String _createProcedureName(
143134
{required ContainerName? containerName,
@@ -155,10 +146,10 @@ class NameScheme {
155146
// infix to make their names unique.
156147
switch (kind) {
157148
case ProcedureKind.Getter:
158-
kindInfix = 'get#';
149+
kindInfix = extensionGetterPrefix;
159150
break;
160151
case ProcedureKind.Setter:
161-
kindInfix = 'set#';
152+
kindInfix = extensionSetterPrefix;
162153
break;
163154
case ProcedureKind.Method:
164155
case ProcedureKind.Operator:
@@ -170,7 +161,7 @@ class NameScheme {
170161
'Unexpected extension method kind ${kind}');
171162
}
172163
}
173-
return '${extensionName}|${kindInfix}${name}';
164+
return '${extensionName}${extensionNameDelimiter}${kindInfix}${name}';
174165
// Coverage-ignore(suite): Not run.
175166
case ContainerType.Library:
176167
case ContainerType.Class:
@@ -512,7 +503,11 @@ class ExtensionTypeConstructorName extends UpdatableMemberName {
512503
name = _text;
513504
}
514505
return new Name.byReference(
515-
'${className}|constructor#${name}', _libraryName.reference);
506+
'${className}'
507+
'${NameScheme.extensionNameDelimiter}'
508+
'${NameScheme.extensionTypeConstructorPrefix}'
509+
'${name}',
510+
_libraryName.reference);
516511
}
517512
}
518513

pkg/front_end/lib/src/source/source_library_builder.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -913,7 +913,8 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
913913
if (!declaration.isDuplicate) {
914914
if (declaration.isUnnamedExtension) {
915915
declaration.extensionName.name =
916-
'_extension#${library.extensions.length}';
916+
'${NameScheme.unnamedExtensionNamePrefix}'
917+
'${library.extensions.length}';
917918
}
918919
library.addExtension(extension);
919920
}

pkg/front_end/lib/src/type_inference/object_access_target.dart

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -899,19 +899,22 @@ class FunctionAccessTarget extends ObjectAccessTarget {
899899
class DynamicAccessTarget extends ObjectAccessTarget {
900900
/// Creates an access on a dynamic receiver type with no known target.
901901
const DynamicAccessTarget.dynamic()
902-
: super.internal(ObjectAccessTargetKind.dynamic);
902+
: super // Coverage-ignore(suite): Not run.
903+
.internal(ObjectAccessTargetKind.dynamic);
903904

904905
/// Creates an access with no target due to an invalid receiver type.
905906
///
906907
/// This is not in itself an error but a consequence of another error.
907908
const DynamicAccessTarget.invalid()
908-
: super.internal(ObjectAccessTargetKind.invalid);
909+
: super // Coverage-ignore(suite): Not run.
910+
.internal(ObjectAccessTargetKind.invalid);
909911

910912
/// Creates an access with no target.
911913
///
912914
/// This is an error case.
913915
const DynamicAccessTarget.missing()
914-
: super.internal(ObjectAccessTargetKind.missing);
916+
: super // Coverage-ignore(suite): Not run.
917+
.internal(ObjectAccessTargetKind.missing);
915918

916919
@override
917920
// Coverage-ignore(suite): Not run.

pkg/front_end/test/coverage_suite_expected.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ const Map<String, ({int hitCount, int missCount})> _expect = {
4545
),
4646
// 100.0%.
4747
"package:front_end/src/api_prototype/lowering_predicates.dart": (
48-
hitCount: 15,
48+
hitCount: 31,
4949
missCount: 0,
5050
),
5151
// 100.0%.
@@ -150,7 +150,7 @@ const Map<String, ({int hitCount, int missCount})> _expect = {
150150
),
151151
// 100.0%.
152152
"package:front_end/src/base/incremental_compiler.dart": (
153-
hitCount: 829,
153+
hitCount: 819,
154154
missCount: 0,
155155
),
156156
// 100.0%.
@@ -1076,7 +1076,7 @@ const Map<String, ({int hitCount, int missCount})> _expect = {
10761076
),
10771077
// 100.0%.
10781078
"package:front_end/src/type_inference/object_access_target.dart": (
1079-
hitCount: 552,
1079+
hitCount: 549,
10801080
missCount: 0,
10811081
),
10821082
// 100.0%.

pkg/front_end/test/lowering_predicates_test.dart

Lines changed: 0 additions & 53 deletions
This file was deleted.

pkg/front_end/test/predicates/data/extension.dart

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,67 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
extension Extension on int {
6+
/*member: Extension|instanceMethod:extensionName=Extension.instanceMethod*/
7+
/*member: Extension|get#instanceMethod:extensionName=Extension.instanceMethod*/
68
int /*
79
extensionThis,
810
name=this
911
*/
1012
instanceMethod() => this;
1113

14+
/*member: Extension|get#instanceGetter:extensionName=Extension.instanceGetter*/
1215
int get /*
1316
extensionThis,
1417
name=this
1518
*/
1619
instanceGetter => this;
1720

21+
/*member: Extension|set#instanceSetter:extensionName=Extension.instanceSetter*/
1822
void set /*
1923
extensionThis,
2024
name=this
2125
*/
2226
instanceSetter(int value) {}
2327

28+
/*member: Extension|staticMethod:extensionName=Extension.staticMethod*/
2429
static int staticMethod() => 42;
2530

31+
/*member: Extension|staticGetter:extensionName=Extension.staticGetter*/
2632
static int get staticGetter => 42;
2733

34+
/*member: Extension|staticSetter=:extensionName=Extension.staticSetter*/
35+
static void set staticSetter(int value) {}
36+
}
37+
38+
extension on int {
39+
/*member: _extension#1|instanceMethod:extensionName=<unnamed extension>.instanceMethod*/
40+
/*member: _extension#1|get#instanceMethod:extensionName=<unnamed extension>.instanceMethod*/
41+
int /*
42+
extensionThis,
43+
name=this
44+
*/
45+
instanceMethod() => this;
46+
47+
/*member: _extension#1|get#instanceGetter:extensionName=<unnamed extension>.instanceGetter*/
48+
int get /*
49+
extensionThis,
50+
name=this
51+
*/
52+
instanceGetter => this;
53+
54+
/*member: _extension#1|set#instanceSetter:extensionName=<unnamed extension>.instanceSetter*/
55+
void set /*
56+
extensionThis,
57+
name=this
58+
*/
59+
instanceSetter(int value) {}
60+
61+
/*member: _extension#1|staticMethod:extensionName=<unnamed extension>.staticMethod*/
62+
static int staticMethod() => 42;
63+
64+
/*member: _extension#1|staticGetter:extensionName=<unnamed extension>.staticGetter*/
65+
static int get staticGetter => 42;
66+
67+
/*member: _extension#1|staticSetter=:extensionName=<unnamed extension>.staticSetter*/
2868
static void set staticSetter(int value) {}
2969
}

0 commit comments

Comments
 (0)