Skip to content

Commit

Permalink
Version 3.5.0-262.0.dev
Browse files Browse the repository at this point in the history
Merge 50e4c57 into dev
  • Loading branch information
Dart CI committed Jun 14, 2024
2 parents e90b0a5 + 50e4c57 commit 17e5d68
Show file tree
Hide file tree
Showing 44 changed files with 1,624 additions and 2,648 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@

[#44876]: https://github.com/dart-lang/sdk/issues/44876

#### `dart:typed_data`

- **BREAKING CHANGE** [#53785][]: The unmodifiable view classes for typed data
have been removed. These classes were deprecated in Dart 3.4.

To create an unmodifiable view of a typed-data object, use the
`asUnmodifiableView()` methods added in Dart 3.3.

[#53785]: https://github.com/dart-lang/sdk/issues/53785

### Tools

#### Linter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class AddExtensionOverride extends MultiCorrectionProducer {
if (target == null) return const [];

var extensions =
libraryElement.accessibleExtensions.hasMemberWithBaseName(node.name);
libraryElement.accessibleExtensions.havingMemberWithBaseName(node.name);
var producers = <ResolvedCorrectionProducer>[];
for (var extension in extensions) {
var name = extension.extension.name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ class ImportLibrary extends MultiCorrectionProducer {
}
foundImport = true;
var instantiatedExtensions = importedLibrary.exportedExtensions
.hasMemberWithBaseName(memberName)
.havingMemberWithBaseName(memberName)
.applicableTo(targetLibrary: libraryElement, targetType: targetType);
for (var instantiatedExtension in instantiatedExtensions) {
// If the import has a combinator that needs to be updated, then offer
Expand Down Expand Up @@ -482,7 +482,7 @@ class _ImportLibraryContainingExtension extends ResolvedCorrectionProducer {
@override
Future<void> compute(ChangeBuilder builder) async {
var instantiatedExtensions = library.exportedExtensions
.hasMemberWithBaseName(memberName)
.havingMemberWithBaseName(memberName)
.applicableTo(targetLibrary: libraryElement, targetType: targetType);
if (instantiatedExtensions.isNotEmpty) {
await builder.addDartFileEdit(file, (builder) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,25 +38,6 @@ void f(A a) {
''');
}

Future<void> test_method_extension() async {
await resolveTestCode('''
extension E on int {
static void foo() {}
}
void f() {
0.foo();
}
''');
await assertHasFix('''
extension E on int {
static void foo() {}
}
void f() {
E.foo();
}
''');
}

Future<void> test_method_importType() async {
newFile('$testPackageLibPath/a.dart', r'''
class A {
Expand Down
1 change: 1 addition & 0 deletions pkg/analyzer/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## 6.7.0-dev
* Deprecated `File.createSource()`, it violates levels of abstraction.
You can get `Source` instances from `AnalysisResult`s.
* Deprecated unused static members of `AnalysisError`.

## 6.6.0
* Stop exporting `src/file_system/file_system.dart`
Expand Down
4 changes: 4 additions & 0 deletions pkg/analyzer/lib/error/error.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,19 @@ HashMap<String, ErrorCode> _computeUniqueNameToCodeMap() {
/// See `AnalysisErrorListener`.
class AnalysisError implements Diagnostic {
/// An empty array of errors used when no errors are expected.
@Deprecated('Not used')
static const List<AnalysisError> NO_ERRORS = <AnalysisError>[];

/// A [Comparator] that sorts by the name of the file that the [AnalysisError]
/// was found.
@Deprecated('Not used')
static Comparator<AnalysisError> FILE_COMPARATOR =
(AnalysisError o1, AnalysisError o2) =>
o1.source.shortName.compareTo(o2.source.shortName);

/// A [Comparator] that sorts error codes first by their severity (errors
/// first, warnings second), and then by the error code type.
@Deprecated('Not used')
static Comparator<AnalysisError> ERROR_CODE_COMPARATOR =
(AnalysisError o1, AnalysisError o2) {
ErrorCode errorCode1 = o1.errorCode;
Expand Down Expand Up @@ -267,6 +270,7 @@ class AnalysisError implements Diagnostic {

/// Merge all of the errors in the lists in the given list of [errorLists]
/// into a single list of errors.
@Deprecated('Not used')
static List<AnalysisError> mergeLists(List<List<AnalysisError>> errorLists) {
Set<AnalysisError> errors = HashSet<AnalysisError>();
for (List<AnalysisError> errorList in errorLists) {
Expand Down
10 changes: 9 additions & 1 deletion pkg/analyzer/lib/src/dart/resolver/applicable_extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ extension ExtensionsExtensions on Iterable<ExtensionElement> {
.applicableTo(targetLibrary: targetLibrary, targetType: targetType);
}

List<_NotInstantiatedExtensionWithMember> hasMemberWithBaseName(
/// Returns the sublist of [ExtensionElement]s that have an instance member
/// named [baseName].
List<_NotInstantiatedExtensionWithMember> havingMemberWithBaseName(
String baseName,
) {
var result = <_NotInstantiatedExtensionWithMember>[];
Expand All @@ -140,6 +142,9 @@ extension ExtensionsExtensions on Iterable<ExtensionElement> {
}
} else {
for (var field in extension.augmented.fields) {
if (field.isStatic) {
continue;
}
if (field.name == baseName) {
result.add(
_NotInstantiatedExtensionWithMember(
Expand All @@ -152,6 +157,9 @@ extension ExtensionsExtensions on Iterable<ExtensionElement> {
}
}
for (var method in extension.augmented.methods) {
if (method.isStatic) {
continue;
}
if (method.name == baseName) {
result.add(
_NotInstantiatedExtensionWithMember(
Expand Down
80 changes: 36 additions & 44 deletions pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import 'package:analyzer/src/dart/resolver/applicable_extensions.dart';
import 'package:analyzer/src/dart/resolver/resolution_result.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/util/either.dart';
import 'package:analyzer/src/utilities/extensions/string.dart';

class ExtensionMemberResolver {
Expand Down Expand Up @@ -74,20 +73,17 @@ class ExtensionMemberResolver {
).substituteType(element.extendedType);
}

/// Return the most specific extension in the current scope for this [type],
/// Returns the most specific accessible extension, applicable to [type],
/// that defines the member with the given [name].
///
/// If no applicable extensions, return [ResolutionResult.none].
/// If no applicable extensions are found, returns [ResolutionResult.none].
///
/// If the match is ambiguous, report an error on the [nameEntity], and
/// return [ResolutionResult.ambiguous].
/// If the match is ambiguous, reports an error on the [nameEntity], and
/// returns [ResolutionResult.ambiguous].
ResolutionResult findExtension(
DartType type,
SyntacticEntity nameEntity,
String name,
) {
DartType type, SyntacticEntity nameEntity, String name) {
var extensions = _resolver.definingLibrary.accessibleExtensions
.hasMemberWithBaseName(name)
.havingMemberWithBaseName(name)
.applicableTo(
targetLibrary: _resolver.definingLibrary,
targetType: type,
Expand All @@ -102,29 +98,27 @@ class ExtensionMemberResolver {
}

var mostSpecific = _chooseMostSpecific(extensions);
return mostSpecific.map(
(extension) {
return extension.asResolutionResult;
},
(noneMoreSpecific) {
_errorReporter.atEntity(
nameEntity,
CompileTimeErrorCode.AMBIGUOUS_EXTENSION_MEMBER_ACCESS,
arguments: [
name,
noneMoreSpecific.map((e) {
var name = e.extension.name;
if (name != null) {
return "extension '$name'";
}
var type = e.extension.extendedType.getDisplayString();
return "unnamed extension on '$type'";
}).commaSeparatedWithAnd,
],
);
return ResolutionResult.ambiguous;
},
if (mostSpecific.length == 1) {
return mostSpecific.first.asResolutionResult;
}

// The most specific extension is ambiguous.
_errorReporter.atEntity(
nameEntity,
CompileTimeErrorCode.AMBIGUOUS_EXTENSION_MEMBER_ACCESS,
arguments: [
name,
mostSpecific.map((e) {
var name = e.extension.name;
if (name != null) {
return "extension '$name'";
}
var type = e.extension.extendedType.getDisplayString();
return "unnamed extension on '$type'";
}).commaSeparatedWithAnd,
],
);
return ResolutionResult.ambiguous;
}

/// Resolve the [name] (without `=`) to the corresponding getter and setter
Expand Down Expand Up @@ -260,11 +254,10 @@ class ExtensionMemberResolver {
}
}

/// Return either the most specific extension, or a list of the extensions
/// that are ambiguous.
Either2<InstantiatedExtensionWithMember,
List<InstantiatedExtensionWithMember>>
_chooseMostSpecific(List<InstantiatedExtensionWithMember> extensions) {
/// Returns a list with either the most specific extension, or, if the most
/// specific is ambiguous, then the extensions that are ambiguous.
List<InstantiatedExtensionWithMember> _chooseMostSpecific(
List<InstantiatedExtensionWithMember> extensions) {
InstantiatedExtensionWithMember? bestSoFar;
var noneMoreSpecific = <InstantiatedExtensionWithMember>[];
for (var candidate in extensions) {
Expand Down Expand Up @@ -299,18 +292,17 @@ class ExtensionMemberResolver {
}

if (bestSoFar != null) {
return Either2.t1(bestSoFar);
} else {
return Either2.t2(noneMoreSpecific);
return [bestSoFar];
}

return noneMoreSpecific;
}

/// Given the generic [element] element, either return types specified
/// explicitly in [typeArguments], or infer type arguments from the given
/// [receiverType].
/// Given the generic [node], either returns types specified explicitly in its
/// type arguments, or infer type arguments from the given [receiverType].
///
/// If the number of explicit type arguments is different than the number
/// of extension's type parameters, or inference fails, return `dynamic`
/// of extension's type parameters, or inference fails, returns `dynamic`
/// for all type parameters.
List<DartType>? _inferTypeArguments(
ExtensionOverride node, DartType receiverType,
Expand Down
33 changes: 33 additions & 0 deletions pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,39 @@ class MethodInvocationResolver with ScopeHelpers {
return null;
}

element = scopeLookupResult.setter;
if (element != null) {
// If the scope lookup reveals a setter, but no getter, then we may still
// find the getter by looking up the inheritence chain (via
// TypePropertyResolver, via `_resolveReceiverType`). However, if the
// setter that was found is either top-level, or declared in an extension,
// or is static, then we do not keep searching for the getter; this
// setter represents the property being accessed (erroneously).
var noGetterIsPossible =
element.enclosingElement is CompilationUnitElement ||
element.enclosingElement is ExtensionElement ||
(element is ExecutableElement && element.isStatic);
if (noGetterIsPossible) {
nameNode.staticElement = element;

_setInvalidTypeResolution(node,
setNameTypeToDynamic: false,
whyNotPromotedList: whyNotPromotedList,
contextType: contextType);
var receiverTypeName = switch (receiverType) {
InterfaceType() => receiverType.element.name,
FunctionType() => 'Function',
_ => '<unknown>',
};
_resolver.errorReporter.atNode(
nameNode,
CompileTimeErrorCode.UNDEFINED_METHOD,
arguments: [name, receiverTypeName],
);
return null;
}
}

return _resolveReceiverType(
node: node,
receiver: null,
Expand Down
4 changes: 2 additions & 2 deletions pkg/analyzer/test/src/dart/analysis/index_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2203,8 +2203,8 @@ extension E on int {
}
void f() {
0.foo;
0.foo = 0;
E.foo;
E.foo = 0;
}
''');
var getter = findElement.getter('foo');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,36 @@ FunctionExpressionInvocation
''');
}

test_getter_functionTyped_withSetterDeclaredLocally() async {
await assertNoErrorsInCode('''
class A {
Function get foo => () {};
}
class B extends A {
set foo(Function _) {}
void f() {
foo();
}
}
''');

var node = findNode.singleFunctionExpressionInvocation;
assertResolvedNodeText(node, r'''
FunctionExpressionInvocation
function: SimpleIdentifier
token: foo
staticElement: self::@class::A::@getter::foo
staticType: Function
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
staticElement: <null>
staticInvokeType: dynamic
staticType: dynamic
''');
}

test_invalidConst_topLevelVariable() async {
await assertErrorsInCode(r'''
const id = identical;
Expand Down
20 changes: 7 additions & 13 deletions pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1030,15 +1030,11 @@ void bar() {
foo.m<int>;
}
extension on Function {
extension E on Function {
static void m<T>(T t) {}
}
''', [
error(
CompileTimeErrorCode
.INSTANCE_ACCESS_TO_STATIC_MEMBER_OF_UNNAMED_EXTENSION,
40,
1),
error(CompileTimeErrorCode.UNDEFINED_GETTER, 40, 1),
]);

assertResolvedNodeText(findNode.functionReference('foo.m<int>;'), r'''
Expand All @@ -1051,10 +1047,10 @@ FunctionReference
period: .
identifier: SimpleIdentifier
token: m
staticElement: self::@extension::0::@method::m
staticType: null
staticElement: self::@extension::0::@method::m
staticType: void Function<T>(T)
staticElement: <null>
staticType: InvalidType
staticElement: <null>
staticType: InvalidType
typeArguments: TypeArgumentList
leftBracket: <
arguments
Expand All @@ -1063,9 +1059,7 @@ FunctionReference
element: dart:core::@class::int
type: int
rightBracket: >
staticType: void Function(int)
typeArgumentTypes
int
staticType: InvalidType
''');
}

Expand Down
Loading

0 comments on commit 17e5d68

Please sign in to comment.