Skip to content

Commit

Permalink
Version 3.3.0-266.0.dev
Browse files Browse the repository at this point in the history
Merge 6a9b550 into dev
  • Loading branch information
Dart CI committed Dec 28, 2023
2 parents d95ec5b + 6a9b550 commit 93229b9
Show file tree
Hide file tree
Showing 10 changed files with 66 additions and 40 deletions.
10 changes: 0 additions & 10 deletions pkg/analysis_server/lib/plugin/edit/fix/fix_core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,3 @@ abstract class FixContext {
/// The error to fix.
AnalysisError get error;
}

/// An object used to produce fixes for a specific error. Fix contributors are
/// long-lived objects and must not retain any state between invocations of
/// [computeFixes].
///
/// Clients may implement this class when implementing plugins.
abstract class FixContributor {
/// Return a list of fixes for the given [context].
Future<List<Fix>> computeFixes(covariant FixContext context);
}
2 changes: 1 addition & 1 deletion pkg/analysis_server/lib/src/cider/fixes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class CiderFixesComputer {
error,
);

var fixes = await DartFixContributor().computeFixes(context);
var fixes = await computeFixes(context);
fixes.sort(Fix.compareFixes);

result.add(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ class EditGetFixesHandler extends LegacyHandler

List<Fix> fixes;
try {
fixes = await DartFixContributor().computeFixes(context);
fixes = await computeFixes(context);
} on InconsistentAnalysisException {
fixes = [];
} catch (exception, stackTrace) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,6 @@ class DartCodeActionsProducer extends AbstractCodeActionsProducer {

final lineInfo = unit.lineInfo;
final codeActions = <CodeActionWithPriority>[];
final fixContributor = DartFixContributor();

try {
final workspace = DartChangeWorkspace(await server.currentSessions);
Expand All @@ -169,7 +168,7 @@ class DartCodeActionsProducer extends AbstractCodeActionsProducer {
}
var context = DartFixContextImpl(
server.instrumentationService, workspace, unit, error);
final fixes = await fixContributor.computeFixes(context);
final fixes = await computeFixes(context);
if (fixes.isNotEmpty) {
final diagnostic = toDiagnostic(
server.pathContext,
Expand Down
28 changes: 11 additions & 17 deletions pkg/analysis_server/lib/src/services/correction/fix_internal.dart
Original file line number Diff line number Diff line change
Expand Up @@ -243,29 +243,23 @@ import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dar
import 'package:analyzer_plugin/utilities/change_builder/conflicting_edit_exception.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart' hide FixContributor;

Future<List<Fix>> computeFixes(DartFixContext context) async {
try {
return [
...await FixProcessor(context).compute(),
...await FixInFileProcessor(context).compute(),
];
} on CancelCorrectionException {
return const [];
}
}

/// A function that can be executed to create a multi-correction producer.
typedef MultiProducerGenerator = MultiCorrectionProducer Function();

/// A function that can be executed to create a correction producer.
typedef ProducerGenerator = CorrectionProducer Function();

/// A fix contributor that provides the default set of fixes for Dart files.
class DartFixContributor implements FixContributor {
@override
Future<List<Fix>> computeFixes(DartFixContext context) async {
try {
var processor = FixProcessor(context);
var fixes = await processor.compute();
var fixInFileProcessor = FixInFileProcessor(context);
var fixInFileFixes = await fixInFileProcessor.compute();
fixes.addAll(fixInFileFixes);
return fixes;
} on CancelCorrectionException {
return const <Fix>[];
}
}
}

/// Computer for Dart "fix all in file" fixes.
class FixInFileProcessor {
final DartFixContext context;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ abstract class FixProcessorTest extends BaseFixProcessorTest {
testAnalysisResult,
error,
);
return await DartFixContributor().computeFixes(context);
return await computeFixes(context);
}

List<Position> _findResultPositions(List<String> searchStrings) {
Expand Down
4 changes: 2 additions & 2 deletions pkg/compiler/lib/src/ssa/value_range_analyzer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ class NegateValue extends Value {
}
return info.newSubtractValue(other, value);
}
if (other is InstructionValue) {
if (other is VariableValue) {
return info.newSubtractValue(other, value);
}
return other - value;
Expand All @@ -548,7 +548,7 @@ class NegateValue extends Value {
}
return info.newSubtractValue(this, other);
}
if (other is InstructionValue) {
if (other is VariableValue) {
return info.newSubtractValue(this, other);
}
if (other is NegateValue) return this + other.value;
Expand Down
40 changes: 35 additions & 5 deletions pkg/dev_compiler/lib/src/kernel/compiler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3047,7 +3047,10 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
/// Arguments which are _directly_ wrapped at the site they are passed are
/// unmodified.
Expression _assertInterop(Expression f) {
var type = f.getStaticType(_staticTypeContext);
// Erasing any extension types here for legacy JS interop support but if
// using the new extension type interop the type system requires that
// `.toJS` was called.
var type = f.getStaticType(_staticTypeContext).extensionTypeErasure;
if (type is FunctionType ||
(type is InterfaceType && type.classNode == _coreTypes.functionClass)) {
if (!isAllowInterop(f)) {
Expand Down Expand Up @@ -5493,6 +5496,7 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
return false;
}

// TODO(54463): Refactor and specialize this code for each type of 'get'.
js_ast.Expression _emitPropertyGet(
Expression receiver, Member? member, String memberName) {
// TODO(jmesserly): should tearoff of `.call` on a function type be
Expand Down Expand Up @@ -5526,8 +5530,11 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
}
// Otherwise generate this as a normal typed property get.
} else if (member == null &&
// Records have no member node for the element getters so avoid emitting
// a dynamic get when the types are known statically.
// Null member usually means this is a dynamic get but Records also have
// no member node for the element getters so avoid emitting a dynamic
// get when the types are known statically.
// Accesses of extension type getters don't lead to this code path
// at all so only the test for RecordType is needed.
receiver.getStaticType(_staticTypeContext) is! RecordType) {
return runtimeCall('dload$_replSuffix(#, #)', [jsReceiver, jsName]);
}
Expand Down Expand Up @@ -5765,9 +5772,17 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>

var isCallingDynamicField = target is Member &&
target.hasGetter &&
// Erasing extension types here doesn't make sense. If there is an
// extension type on dynamic or Function it will only be callable if it
// defines a call method which would be invoked statically.
_isDynamicOrFunction(target.getterType);
if (name == 'call') {
var receiverType = receiver.getStaticType(_staticTypeContext);
// Erasing the extension types here to support existing callable behaivor
// on the old style JS interop types that are callable. This should be
// safe as it is a compile time error to try to dynamically invoke a call
// method that is inherited from an extension type.
var receiverType =
receiver.getStaticType(_staticTypeContext).extensionTypeErasure;
if (isCallingDynamicField || _isDynamicOrFunction(receiverType)) {
return _emitDynamicInvoke(jsReceiver, null, args, arguments);
} else if (_isDirectCallable(receiverType)) {
Expand All @@ -5793,7 +5808,22 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
// TODO(jmesserly): remove when Kernel desugars this for us.
// Handle `o.m(a)` where `o.m` is a getter returning a class with `call`.
if (target is Field || target is Procedure && target.isAccessor) {
var fromType = target!.getterType;
// We must erase the extension type to find the `call` method.
// If the extension type has a runtime representation with a `call`:
//
// ```
// extension type Ext(C c) implements C {...}
// class C {
// call() {...}
// }
// ```
//
// We can always erase eagerly becuase:
// - Extension types that do not implment an interface that exposes a
// `call` method will result in a static error at the call site.
// - Calls to extension types that implement their own call method are
// lowered by the CFE to top level static method calls.
var fromType = target!.getterType.extensionTypeErasure;
if (fromType is InterfaceType) {
var callName = _implicitCallTarget(fromType);
if (callName != null) {
Expand Down
13 changes: 13 additions & 0 deletions tests/web/regress/issue/54453_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// Make sure binary operations are correctly handled for range-like values in
// SSA's value range analyzer.

void main() {
int counter = 0;
for (int i = 0; i < 5; i++) {
counter += counter;
}
}
2 changes: 1 addition & 1 deletion tools/VERSION
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ CHANNEL dev
MAJOR 3
MINOR 3
PATCH 0
PRERELEASE 265
PRERELEASE 266
PRERELEASE_PATCH 0

0 comments on commit 93229b9

Please sign in to comment.