CQ. Use public types as inputs, cast inside on entry.

Refactor `applicable_extensions.dart` so its public entry points accept
`DartType` and `ExtensionElement`, and perform implementation casts
internally at the analyzer boundary.

Remove the `strictCasts` parameter as well. Extension applicability
always ignores casts, so the parameter only added noise to the API and
to every call site.

Update completion and fix code in analysis_server to pass public types
directly and drop imports of internal analyzer type classes. Also
centralize the cast from `ExtensionElement` to `ExtensionElementImpl`
inside the helper instead of repeating it in multiple loops.

This makes the API cleaner, keeps the public/internal split in one
place, and reduces accidental coupling to analyzer implementation types.

Change-Id: I770ee5d8788f4c4a7004a0ad18a00cc52552e3b5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/494802
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
This commit is contained in:
Konstantin Shcheglov
2026-04-13 13:48:24 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent 1d69180201
commit bec97e984e
6 changed files with 29 additions and 75 deletions
@@ -549,12 +549,9 @@ class DeclarationHelper {
.applicableTo(
targetLibrary: libraryElement,
// Ignore nullability, consistent with non-extension members.
targetType:
(type.isDartCoreNull
? type
: library.typeSystem.promoteToNonNull(type))
as TypeImpl,
strictCasts: false,
targetType: type.isDartCoreNull
? type
: library.typeSystem.promoteToNonNull(type),
);
var importData = ImportData(
libraryUri: library.uri,
@@ -835,12 +832,9 @@ class DeclarationHelper {
var applicableExtensions = accessibleExtensions.applicableTo(
targetLibrary: libraryElement,
// Ignore nullability, consistent with non-extension members.
targetType:
(type.isDartCoreNull
? type
: libraryElement.typeSystem.promoteToNonNull(type))
as TypeImpl,
strictCasts: false,
targetType: type.isDartCoreNull
? type
: libraryElement.typeSystem.promoteToNonNull(type),
);
for (var instantiatedExtension in applicableExtensions) {
var extension = instantiatedExtension.extension;
@@ -7,7 +7,6 @@ import 'package:analysis_server_plugin/edit/dart/correction_producer.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/resolver/applicable_extensions.dart';
import 'package:analyzer/src/utilities/extensions/ast.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
@@ -45,10 +44,7 @@ class AddExtensionOverride extends MultiCorrectionProducer {
var nodeName = Name(libraryElement.uri, node.name);
var extensions = libraryFragment.accessibleExtensions
.havingMemberWithBaseName(nodeName)
.applicableTo(
targetLibrary: libraryElement,
targetType: targetType as TypeImpl,
);
.applicableTo(targetLibrary: libraryElement, targetType: targetType);
var producers = <ResolvedCorrectionProducer>[];
for (var extension in extensions) {
var name = extension.extension.name;
@@ -730,8 +730,7 @@ abstract class _CreateExtensionMember extends ResolvedCorrectionProducer {
}
var instantiated = [extension].applicableTo(
targetLibrary: libraryElement2,
targetType: extension.thisType as TypeImpl,
strictCasts: true,
targetType: extension.thisType,
);
if (instantiated.isNotEmpty) {
return (unit.path, existingExtension);
@@ -19,7 +19,6 @@ import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/resolver/applicable_extensions.dart';
import 'package:analyzer/utilities/extensions/element.dart';
import 'package:analyzer/utilities/extensions/uri.dart';
@@ -393,10 +392,7 @@ class ImportLibrary extends MultiCorrectionProducer {
foundImport = true;
extensionsInLibrary[import] = importedLibrary.exportedExtensions
.havingMemberWithBaseName(memberName)
.applicableTo(
targetLibrary: libraryElement2,
targetType: targetType as TypeImpl,
);
.applicableTo(targetLibrary: libraryElement2, targetType: targetType);
}
// If the library at the URI is not already imported, we return a correction
@@ -405,10 +401,7 @@ class ImportLibrary extends MultiCorrectionProducer {
if (!foundImport) {
extensionsInLibrary[null] = libraryToImport.exportedExtensions
.havingMemberWithBaseName(memberName)
.applicableTo(
targetLibrary: libraryElement2,
targetType: targetType as TypeImpl,
);
.applicableTo(targetLibrary: libraryElement2, targetType: targetType);
}
for (var entry in extensionsInLibrary.entries) {
var extensionsInLibrary = entry.value;
@@ -8,7 +8,6 @@ import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/resolver/applicable_extensions.dart';
import 'package:analyzer/utilities/extensions/element.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
@@ -110,7 +109,7 @@ class _UseDifferentDivisionOperator extends ResolvedCorrectionProducer {
.havingMemberWithBaseName(name)
.applicableTo(
targetLibrary: libraryElement2,
targetType: leftType! as TypeImpl,
targetType: leftType!,
)
.isNotEmpty;
}).isEmpty;
@@ -80,8 +80,8 @@ abstract class _NotInstantiatedExtension<R> {
class _NotInstantiatedExtensionWithMember
extends _NotInstantiatedExtension<InstantiatedExtensionWithMember> {
final ExecutableElement? getter;
final ExecutableElement? setter;
final InternalExecutableElement? getter;
final InternalExecutableElement? setter;
_NotInstantiatedExtensionWithMember(
super.extension, {
@@ -120,17 +120,12 @@ extension ExtensionsExtensions on Iterable<ExtensionElement> {
/// Extensions that can be applied, within [targetLibrary], to [targetType].
List<InstantiatedExtensionWithoutMember> applicableTo({
required LibraryElement targetLibrary,
required TypeImpl targetType,
required bool strictCasts,
required DartType targetType,
}) {
targetLibrary as LibraryElementImpl;
return map(
(e) => _NotInstantiatedExtensionWithoutMember(
// TODO(paulberry): eliminate this cast by changing the extension to
// apply only to `Iterable<ExtensionElementImpl>`.
e as ExtensionElementImpl,
),
).applicableTo(targetLibrary: targetLibrary, targetType: targetType);
return cast<ExtensionElementImpl>()
.map((e) => _NotInstantiatedExtensionWithoutMember(e))
.applicableTo(targetLibrary: targetLibrary, targetType: targetType);
}
/// Returns the sublist of [ExtensionElement]s that have an instance member
@@ -139,7 +134,7 @@ extension ExtensionsExtensions on Iterable<ExtensionElement> {
Name baseName,
) {
var result = <_NotInstantiatedExtensionWithMember>[];
for (var extension in this) {
for (var extension in cast<ExtensionElementImpl>()) {
if (!baseName.isAccessibleFor(extension.library.uri)) {
continue;
}
@@ -150,9 +145,7 @@ extension ExtensionsExtensions on Iterable<ExtensionElement> {
if (getter != null || setter != null) {
result.add(
_NotInstantiatedExtensionWithMember(
// TODO(paulberry): eliminate this cast by changing the extension
// to apply only to `Iterable<ExtensionElementImpl>`.
extension as ExtensionElementImpl,
extension,
getter: getter,
setter: setter,
),
@@ -163,9 +156,7 @@ extension ExtensionsExtensions on Iterable<ExtensionElement> {
if (field != null && !field.isStatic) {
result.add(
_NotInstantiatedExtensionWithMember(
// TODO(paulberry): eliminate this cast by changing the
// extension to apply only to `Iterable<ExtensionElementImpl>`.
extension as ExtensionElementImpl,
extension,
getter: field.getter,
setter: field.setter,
),
@@ -175,12 +166,7 @@ extension ExtensionsExtensions on Iterable<ExtensionElement> {
var method = extension.getMethod(baseName.name);
if (method != null && !method.isStatic) {
result.add(
_NotInstantiatedExtensionWithMember(
// TODO(paulberry): eliminate this cast by changing the
// extension to apply only to `Iterable<ExtensionElementImpl>`.
extension as ExtensionElementImpl,
getter: method,
),
_NotInstantiatedExtensionWithMember(extension, getter: method),
);
}
}
@@ -192,7 +178,7 @@ extension ExtensionsExtensions on Iterable<ExtensionElement> {
/// with name [name].
List<_ExtensionWithMemberWithName> havingStaticMemberWithName(Name name) {
var result = <_ExtensionWithMemberWithName>[];
for (var extension in this) {
for (var extension in cast<ExtensionElementImpl>()) {
if (!name.isAccessibleFor(extension.library.uri)) {
continue;
}
@@ -200,36 +186,21 @@ extension ExtensionsExtensions on Iterable<ExtensionElement> {
var getter = extension.getGetter(name.name);
if (getter != null && getter.isStatic) {
result.add(
_ExtensionWithMemberWithName(
// TODO(paulberry): eliminate this cast by changing the
// extension to apply only to `Iterable<ExtensionElementImpl>`.
extension: extension as ExtensionElementImpl,
member: getter as GetterElementImpl,
),
_ExtensionWithMemberWithName(extension: extension, member: getter),
);
}
var setter = extension.getSetter(name.name);
if (setter != null && setter.isStatic) {
result.add(
_ExtensionWithMemberWithName(
// TODO(paulberry): eliminate this cast by changing the
// extension to apply only to `Iterable<ExtensionElementImpl>`.
extension: extension as ExtensionElementImpl,
member: setter as SetterElementImpl,
),
_ExtensionWithMemberWithName(extension: extension, member: setter),
);
}
var method = extension.getMethod(name.name);
if (method != null && method.isStatic) {
result.add(
_ExtensionWithMemberWithName(
// TODO(paulberry): eliminate this cast by changing the
// extension to apply only to `Iterable<ExtensionElementImpl>`.
extension: extension as ExtensionElementImpl,
member: method as MethodElementImpl,
),
_ExtensionWithMemberWithName(extension: extension, member: method),
);
}
}
@@ -242,13 +213,15 @@ extension NotInstantiatedExtensionsExtensions<R>
/// Extensions that can be applied, within [targetLibrary], to [targetType].
List<R> applicableTo({
required LibraryElement targetLibrary,
required TypeImpl targetType,
required DartType targetType,
}) {
targetLibrary as LibraryElementImpl;
targetType as TypeImpl;
if (identical(targetType, NeverTypeImpl.instance)) {
return <R>[];
}
targetLibrary as LibraryElementImpl;
var typeSystem = targetLibrary.typeSystem;
var genericMetadataIsEnabled = targetLibrary.featureSet.isEnabled(
Feature.generic_metadata,