Skip to content

Commit 6ef2dbc

Browse files
stereotype441Commit Queue
authored andcommitted
Introduce ExtensionResolutionResult for use by ExtensionMemberResolver.
Previously, `ExtensionMemberResolver` used `ResolutionResult` to return its results. This created unnecessary complexity, because `ResolutionResult` needs to be able to represent a lot of resolution results that aren't possible when resolving extensions (references to `Function.call`, references to record fields, and various complex error reporting scenarios). Conversely, `ExtensionResolutionResult` needs to be able to represent some scenarios that arent relevant when doing non-extension resolution (extension lookup resulting in no result or an ambiguous result). Splitting into two classes makes both classes simpler. In a few cases, code needs to be able to handle either a `ResolutionResult` or an `ExtensionResolutionResult`; for these cases, I've added a common base class `SimpleResolutionResult`. This change paves the way for some clean-up work I'm doing on `TypePropertyResolver` (which uses `ResolutionResult`). Change-Id: I205251e43d7263cd2df7c729d1550dbb55980f62 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/393442 Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Paul Berry <[email protected]>
1 parent 86ec883 commit 6ef2dbc

File tree

5 files changed

+62
-59
lines changed

5 files changed

+62
-59
lines changed

pkg/analyzer/lib/src/dart/resolver/applicable_extensions.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
1111
import 'package:analyzer/src/dart/element/member.dart';
1212
import 'package:analyzer/src/dart/element/type.dart';
1313
import 'package:analyzer/src/dart/element/type_algebra.dart';
14+
import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
1415
import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
15-
import 'package:analyzer/src/dart/resolver/resolution_result.dart';
1616
import 'package:analyzer/src/generated/inference_log.dart';
1717

1818
class InstantiatedExtensionWithMember {
@@ -26,8 +26,8 @@ class InstantiatedExtensionWithMember {
2626
this.extendedType,
2727
);
2828

29-
ResolutionResult get asResolutionResult {
30-
return ResolutionResult(getter: getter, setter: setter);
29+
ExtensionResolutionResult get asResolutionResult {
30+
return SingleExtensionResolutionResult(getter: getter, setter: setter);
3131
}
3232

3333
ExtensionElement get extension => candidate.extension;

pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,12 @@ class ExtensionMemberResolver {
7878
/// Returns the most specific accessible extension, applicable to [type],
7979
/// that defines the member with the given [name].
8080
///
81-
/// If no applicable extensions are found, returns [ResolutionResult.none].
81+
/// If no applicable extensions are found, returns
82+
/// [ExtensionResolutionResult.none].
8283
///
8384
/// If the match is ambiguous, reports an error on the [nameEntity], and
84-
/// returns [ResolutionResult.ambiguous].
85-
ResolutionResult findExtension(
85+
/// returns [ExtensionResolutionResult.ambiguous].
86+
ExtensionResolutionResult findExtension(
8687
DartType type, SyntacticEntity nameEntity, Name name) {
8788
var extensions = _resolver.libraryFragment.accessibleExtensions
8889
.havingMemberWithBaseName(name)
@@ -92,7 +93,7 @@ class ExtensionMemberResolver {
9293
);
9394

9495
if (extensions.isEmpty) {
95-
return ResolutionResult.none;
96+
return ExtensionResolutionError.none;
9697
}
9798

9899
if (extensions.length == 1) {
@@ -140,14 +141,15 @@ class ExtensionMemberResolver {
140141
],
141142
);
142143
}
143-
return ResolutionResult.ambiguous;
144+
return ExtensionResolutionError.ambiguous;
144145
}
145146

146147
/// Resolve the [name] (without `=`) to the corresponding getter and setter
147148
/// members of the extension [node].
148149
///
149150
/// The [node] is fully resolved, and its type arguments are set.
150-
ResolutionResult getOverrideMember(ExtensionOverride node, String name) {
151+
ExtensionResolutionResult getOverrideMember(
152+
ExtensionOverride node, String name) {
151153
var element = node.element;
152154

153155
ExecutableElement? getter;
@@ -161,7 +163,7 @@ class ExtensionMemberResolver {
161163
}
162164

163165
if (getter == null && setter == null) {
164-
return ResolutionResult.none;
166+
return ExtensionResolutionError.none;
165167
}
166168

167169
var substitution = Substitution.fromPairs(
@@ -174,7 +176,8 @@ class ExtensionMemberResolver {
174176
var setterMember =
175177
setter != null ? ExecutableMember.from2(setter, substitution) : null;
176178

177-
return ResolutionResult(getter: getterMember, setter: setterMember);
179+
return SingleExtensionResolutionResult(
180+
getter: getterMember, setter: setterMember);
178181
}
179182

180183
/// Perform upward inference for the override.
@@ -450,3 +453,32 @@ class ExtensionMemberResolver {
450453
parent is PropertyAccess && parent.target == node;
451454
}
452455
}
456+
457+
/// The result of a failed attempt to resolve an identifier to elements, where
458+
/// the result is expected to come from an extension.
459+
enum ExtensionResolutionError implements ExtensionResolutionResult {
460+
/// Resolution failed because no elements were found.
461+
none,
462+
463+
/// Resolution failed because multiple elements were found.
464+
ambiguous;
465+
466+
@override
467+
ExecutableElement? get getter => null;
468+
469+
@override
470+
ExecutableElement? get setter => null;
471+
}
472+
473+
/// The result of attempting to resolve an identifier to elements, where the
474+
/// result (if any) is known to come from an extension.
475+
sealed class ExtensionResolutionResult implements SimpleResolutionResult {}
476+
477+
/// The result of a successful attempt to resolve an identifier to elements,
478+
/// where the result (if any) is known to come from an extension.
479+
class SingleExtensionResolutionResult extends SimpleResolutionResult
480+
implements ExtensionResolutionResult {
481+
SingleExtensionResolutionResult(
482+
{required super.getter, required super.setter})
483+
: assert(getter != null || setter != null);
484+
}

pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ class PropertyElementResolver with ScopeHelpers {
4949
var result = _extensionResolver.getOverrideMember(target, '[]');
5050

5151
// TODO(scheglov): Change ExtensionResolver to set `needsGetterError`.
52-
if (hasRead && result.getter == null && !result.isAmbiguous) {
52+
if (hasRead &&
53+
result.getter == null &&
54+
result != ExtensionResolutionError.ambiguous) {
5355
// Extension overrides can only refer to named extensions, so it is safe
5456
// to assume that `target.staticElement!.name` is non-`null`.
5557
_reportUnresolvedIndex(
@@ -59,7 +61,9 @@ class PropertyElementResolver with ScopeHelpers {
5961
);
6062
}
6163

62-
if (hasWrite && result.setter == null && !result.isAmbiguous) {
64+
if (hasWrite &&
65+
result.setter == null &&
66+
result != ExtensionResolutionError.ambiguous) {
6367
// Extension overrides can only refer to named extensions, so it is safe
6468
// to assume that `target.staticElement!.name` is non-`null`.
6569
_reportUnresolvedIndex(
@@ -889,7 +893,7 @@ class PropertyElementResolver with ScopeHelpers {
889893
}
890894

891895
PropertyElementResolverResult _toIndexResult(
892-
ResolutionResult result, {
896+
SimpleResolutionResult result, {
893897
required bool atDynamicTarget,
894898
required bool hasRead,
895899
required bool hasWrite,

pkg/analyzer/lib/src/dart/resolver/resolution_result.dart

Lines changed: 10 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,7 @@ import 'package:analyzer/dart/element/element.dart';
66
import 'package:analyzer/dart/element/type.dart';
77

88
/// The result of attempting to resolve an identifier to elements.
9-
class ResolutionResult {
10-
/// An instance that can be used anywhere that no element was found.
11-
static const ResolutionResult none =
12-
ResolutionResult._(_ResolutionResultState.none);
13-
14-
/// An instance that can be used anywhere that multiple elements were found.
15-
static const ResolutionResult ambiguous =
16-
ResolutionResult._(_ResolutionResultState.ambiguous);
17-
18-
/// The state of the result.
19-
final _ResolutionResultState state;
20-
21-
/// Return the element that is invoked for reading.
22-
final ExecutableElement? getter;
23-
9+
class ResolutionResult extends SimpleResolutionResult {
2410
/// If `true`, then the [getter] is `null`, and this is an error that has
2511
/// not yet been reported, and the client should report it.
2612
///
@@ -34,9 +20,6 @@ class ResolutionResult {
3420
/// If `true`, the result type must be invalid.
3521
final bool isGetterInvalid;
3622

37-
/// Return the element that is invoked for writing.
38-
final ExecutableElement? setter;
39-
4023
/// If `true`, then the [setter] is `null`, and this is an error that has
4124
/// not yet been reported, and the client should report it.
4225
///
@@ -56,38 +39,22 @@ class ResolutionResult {
5639
/// Initialize a newly created result to represent resolving a single
5740
/// reading and / or writing result.
5841
ResolutionResult({
59-
this.getter,
42+
super.getter,
6043
this.needsGetterError = true,
6144
this.isGetterInvalid = false,
62-
this.setter,
45+
super.setter,
6346
this.needsSetterError = true,
6447
this.callFunctionType,
6548
this.recordField,
66-
}) : state = _ResolutionResultState.single;
67-
68-
/// Initialize a newly created result with no elements and the given [state].
69-
const ResolutionResult._(this.state)
70-
: getter = null,
71-
needsGetterError = true,
72-
isGetterInvalid = false,
73-
setter = null,
74-
needsSetterError = true,
75-
callFunctionType = null,
76-
recordField = null;
77-
78-
/// Return `true` if this result represents the case where multiple ambiguous
79-
/// elements were found.
80-
bool get isAmbiguous => state == _ResolutionResultState.ambiguous;
49+
});
8150
}
8251

83-
/// The state of a [ResolutionResult].
84-
enum _ResolutionResultState {
85-
/// Indicates that no element was found.
86-
none,
52+
class SimpleResolutionResult {
53+
/// Return the element that is invoked for reading.
54+
final ExecutableElement? getter;
8755

88-
/// Indicates that a single element was found.
89-
single,
56+
/// Return the element that is invoked for writing.
57+
final ExecutableElement? setter;
9058

91-
/// Indicates that multiple ambiguous elements were found.
92-
ambiguous
59+
const SimpleResolutionResult({this.getter, this.setter});
9360
}

pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,8 @@ class TypePropertyResolver {
234234
var getterName = Name(_definingLibrary.source.uri, _name);
235235
var result =
236236
_extensionResolver.findExtension(type, _nameErrorEntity, getterName);
237-
_reportedGetterError = result.isAmbiguous;
238-
_reportedSetterError = result.isAmbiguous;
237+
_reportedGetterError = result == ExtensionResolutionError.ambiguous;
238+
_reportedSetterError = result == ExtensionResolutionError.ambiguous;
239239

240240
if (result.getter != null) {
241241
_needsGetterError = false;

0 commit comments

Comments
 (0)