Skip to content

Commit

Permalink
Version 3.8.0-77.0.dev
Browse files Browse the repository at this point in the history
Merge e3d809f into dev
  • Loading branch information
Dart CI committed Feb 8, 2025
2 parents 9978982 + e3d809f commit 2c2680b
Show file tree
Hide file tree
Showing 31 changed files with 560 additions and 141 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

[`unnecessary_ignore`]: http://dart.dev/lints/unnecessary_ignore

- Added a quick assist for Wrap with ValueListenableBuilder.

#### Dart Development Compiler (dartdevc)

In order to align with dart2js semantics, DDC will now throw a runtime error
Expand Down
4 changes: 2 additions & 2 deletions DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ vars = {
"download_reclient": True,

# Update from https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core
"fuchsia_sdk_version": "version:27.20250203.4.1",
"fuchsia_sdk_version": "version:27.20250204.4.1",
"download_fuchsia_deps": False,

# Ninja, runs the build based on files generated by GN.
Expand All @@ -98,7 +98,7 @@ vars = {

# Prefer to use hashes of binaryen that have been reviewed & rolled into g3.
"binaryen_rev" : "3f6831c0bd147ae1ae0ab1d9187d37bce7cca38b",
"boringssl_rev": "ea42fe28775844ec8fe0444fc421398be42d51fe",
"boringssl_rev": "8ec37a156c8a9f11740ea3930628fedf9fc5e07b",
"browser-compat-data_tag": "ac8cae697014da1ff7124fba33b0b4245cc6cd1b", # v1.0.22
"cpu_features_rev": "936b9ab5515dead115606559502e3864958f7f6e",
"devtools_rev": "b38abb81337b10c4b675d418e50f82a5fe6a894d",
Expand Down
18 changes: 11 additions & 7 deletions pkg/analysis_server/lib/src/computer/computer_highlights.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1497,15 +1497,19 @@ class _DartUnitHighlightsComputerVisitor extends RecursiveAstVisitor<void> {
}

@override
void visitPatternFieldName(PatternFieldName node) {
var name = node.name;
void visitPatternField(PatternField node) {
var name = node.name?.name;
if (name != null) {
computer._addRegion_token(
node.name,
HighlightRegionType.INSTANCE_GETTER_REFERENCE,
);
// Patterns can be method tear-offs as well as getters:
// https://github.com/dart-lang/sdk/issues/59976#issuecomment-2613558317
var type = switch (node.element2) {
MethodElement2() => HighlightRegionType.INSTANCE_METHOD_TEAR_OFF,
_ => HighlightRegionType.INSTANCE_GETTER_REFERENCE,
};

computer._addRegion_token(name, type);
}
super.visitPatternFieldName(node);
super.visitPatternField(node);
}

@override
Expand Down
5 changes: 5 additions & 0 deletions pkg/analysis_server/lib/src/services/correction/assist.dart
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,11 @@ abstract final class DartAssistKind {
DartAssistKindPriority.FLUTTER_WRAP_SPECIFIC,
'Wrap with StreamBuilder',
);
static const FLUTTER_WRAP_VALUE_LISTENABLE_BUILDER = AssistKind(
'dart.assist.flutter.wrap.valueListenableBuilder',
DartAssistKindPriority.FLUTTER_WRAP_SPECIFIC,
'Wrap with ValueListenableBuilder',
);
static const FLUTTER_SWAP_WITH_CHILD = AssistKind(
'dart.assist.flutter.swap.withChild',
DartAssistKindPriority.FLUTTER_SWAP,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import 'package:analysis_server/src/services/correction/dart/flutter_wrap.dart';
import 'package:analysis_server/src/services/correction/dart/flutter_wrap_builder.dart';
import 'package:analysis_server/src/services/correction/dart/flutter_wrap_generic.dart';
import 'package:analysis_server/src/services/correction/dart/flutter_wrap_stream_builder.dart';
import 'package:analysis_server/src/services/correction/dart/flutter_wrap_value_listenable_builder.dart';
import 'package:analysis_server/src/services/correction/dart/import_add_show.dart';
import 'package:analysis_server/src/services/correction/dart/inline_invocation.dart';
import 'package:analysis_server/src/services/correction/dart/invert_conditional_expression.dart';
Expand Down Expand Up @@ -143,6 +144,7 @@ class AssistProcessor {
FlutterWrapBuilder.new,
FlutterWrapGeneric.new,
FlutterWrapStreamBuilder.new,
FlutterWrapValueListenableBuilder.new,
ImportAddShow.new,
InlineInvocation.new,
InvertConditionalExpression.new,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright (c) 2025, 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.

import 'package:analysis_server/src/services/correction/assist.dart';
import 'package:analysis_server_plugin/edit/dart/correction_producer.dart';
import 'package:analyzer/src/utilities/extensions/flutter.dart';
import 'package:analyzer_plugin/utilities/assist/assist.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';

// TODO(kenz): share common implementation between the various builder wrappers.
// See https://github.com/dart-lang/sdk/issues/60075.
class FlutterWrapValueListenableBuilder extends ResolvedCorrectionProducer {
FlutterWrapValueListenableBuilder({required super.context});

@override
CorrectionApplicability get applicability =>
// TODO(applicability): comment on why.
CorrectionApplicability
.singleLocation;

@override
AssistKind get assistKind =>
DartAssistKind.FLUTTER_WRAP_VALUE_LISTENABLE_BUILDER;

@override
Future<void> compute(ChangeBuilder builder) async {
var widgetExpr = node.findWidgetExpression;
if (widgetExpr == null) {
return;
}

var widgetSrc = utils.getNodeText(widgetExpr);

var valueListenableBuilderElement = await sessionHelper.getFlutterClass(
'ValueListenableBuilder',
);
if (valueListenableBuilderElement == null) {
return;
}

await builder.addDartFileEdit(file, (builder) {
builder.addReplacement(range.node(widgetExpr), (builder) {
builder.writeReference(valueListenableBuilderElement);

builder.write('<');
builder.addSimpleLinkedEdit('type', 'Object');
builder.writeln('>(');

var indentOld = utils.getLinePrefix(widgetExpr.offset);
var indentNew1 = indentOld + utils.oneIndent;
var indentNew2 = indentOld + utils.twoIndents;

builder.write(indentNew1);
builder.writeln('valueListenable: valueListenable,');

builder.write(indentNew1);
// If there is a ValueListenableBuilder above or below the Widget being
// added that has a parameter named 'value', then this parameter named
// 'value' will take precedence in the scope of this builder. This is a
// known risk and is acceptable at this time. It is possible to improve
// this logic in the future by looking for naming collisisons above and
// below this Widget and giving the parameter a unique name.
builder.writeln('builder: (context, value, child) {');

widgetSrc = utils.replaceSourceIndent(widgetSrc, indentOld, indentNew2);
builder.write(indentNew2);
builder.write('return $widgetSrc');
builder.writeln(';');

builder.write(indentNew1);
var addTrailingCommas =
getCodeStyleOptions(unitResult.file).addTrailingCommas;
builder.writeln('}${addTrailingCommas ? "," : ""}');

builder.write(indentOld);
builder.write(')');
});
});
}
}
13 changes: 12 additions & 1 deletion pkg/analysis_server/test/lsp/semantic_tokens_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1726,7 +1726,9 @@ void f() {
var content = r'''
void f() {
switch (1) {
case int(isEven: var isEven) when isEven:
case int(isEven: var isEven, toString: var toString) when isEven:
isEven;
toString;
}
}
''';
Expand Down Expand Up @@ -1754,10 +1756,19 @@ void f() {
_Token('isEven', SemanticTokenTypes.variable, [
SemanticTokenModifiers.declaration,
]),
_Token('toString', SemanticTokenTypes.method, [
CustomSemanticTokenModifiers.instance,
]),
_Token('var', SemanticTokenTypes.keyword),
_Token('toString', SemanticTokenTypes.variable, [
SemanticTokenModifiers.declaration,
]),
_Token('when', SemanticTokenTypes.keyword, [
CustomSemanticTokenModifiers.control,
]),
_Token('isEven', SemanticTokenTypes.variable),
_Token('isEven', SemanticTokenTypes.variable),
_Token('toString', SemanticTokenTypes.variable),
];

await _initializeAndVerifyTokens(content, expected);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import 'package:analysis_server/src/services/completion/yaml/analysis_options_generator.dart';
import 'package:analyzer/src/dart/error/lint_codes.dart';
import 'package:analyzer/src/lint/linter.dart';
import 'package:analyzer/src/lint/registry.dart';
import 'package:analyzer/src/task/options.dart';
import 'package:analyzer/src/test_utilities/lint_registration_mixin.dart';
import 'package:linter/src/rules.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
Expand All @@ -20,30 +20,21 @@ void main() {
}

@reflectiveTest
class AnalysisOptionsGeneratorTest extends YamlGeneratorTest {
// Keep track of any added rules so they can be unregistered in `tearDown`.
var addedRules = <LintRule>[];

class AnalysisOptionsGeneratorTest extends YamlGeneratorTest
with LintRegistrationMixin {
@override
String get fileName => 'analysis_options.yaml';

@override
AnalysisOptionsGenerator get generator =>
AnalysisOptionsGenerator(resourceProvider);

void registerRule(LintRule rule) {
addedRules.add(rule);
Registry.ruleRegistry.registerLintRule(rule);
}

void setUp() {
registerLintRules();
}

void tearDown() {
for (var rule in addedRules) {
Registry.ruleRegistry.unregisterLintRule(rule);
}
unregisterLintRules();
}

void test_analyzer() {
Expand Down Expand Up @@ -161,7 +152,7 @@ linter:
}

void test_linter_rules_internal() {
registerRule(InternalRule());
registerLintRule(InternalRule());

getCompletions('''
linter:
Expand Down Expand Up @@ -236,7 +227,7 @@ linter:
}

void test_linter_rules_removed() {
registerRule(_RemovedLint());
registerLintRule(_RemovedLint());

getCompletions('''
linter:
Expand Down
Loading

0 comments on commit 2c2680b

Please sign in to comment.