Version 2.15.0-41.0.dev
Merge commit '86898c2ee6ad46758a43a197bcdc374591f2c5a5' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_type_annotation.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_type_annotation.dart
index 95ddbc7..d5b7137 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/add_type_annotation.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_type_annotation.dart
@@ -12,7 +12,6 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_system.dart';
-import 'package:analyzer_plugin/src/utilities/change_builder/change_builder_core.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/fixes/fixes.dart';
@@ -63,27 +62,23 @@
Future<void> _applyChange(
ChangeBuilder builder, Token? keyword, int offset, DartType type) async {
- Future<bool> tryToApplyChange(ChangeBuilder builder) async {
- var validChange = true;
- await builder.addDartFileEdit(file, (builder) {
+
+ _configureTargetLocation(node);
+
+ await builder.addDartFileEdit(file, (builder) {
+ if (builder.canWriteType(type)) {
if (keyword != null && keyword.keyword == Keyword.VAR) {
builder.addReplacement(range.token(keyword), (builder) {
- validChange = builder.writeType(type);
+ builder.writeType(type);
});
} else {
builder.addInsertion(offset, (builder) {
- validChange = builder.writeType(type);
+ builder.writeType(type);
builder.write(' ');
});
}
- });
- return validChange;
- }
-
- _configureTargetLocation(node);
- if (await tryToApplyChange(_temporaryBuilder(builder))) {
- await tryToApplyChange(builder);
- }
+ }
+ });
}
/// Configure the [utils] using the given [target].
@@ -158,9 +153,6 @@
await _applyChange(builder, declarationList.keyword, variable.offset, type);
}
- ChangeBuilder _temporaryBuilder(ChangeBuilder builder) =>
- ChangeBuilder(workspace: (builder as ChangeBuilderImpl).workspace);
-
DartType? _typeForVariable(VariableDeclaration variable) {
var initializer = variable.initializer;
if (initializer != null) {
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/split_variable_declaration.dart b/pkg/analysis_server/lib/src/services/correction/dart/split_variable_declaration.dart
index b6b3910..abe052d 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/split_variable_declaration.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/split_variable_declaration.dart
@@ -6,7 +6,6 @@
import 'package:analysis_server/src/services/correction/assist.dart';
import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer_plugin/src/utilities/change_builder/change_builder_core.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';
@@ -51,34 +50,26 @@
return;
}
- Future<bool> tryToApplyChange(ChangeBuilder builder) async {
- var validChange = true;
- await builder.addDartFileEdit(file, (builder) {
- if (variableList.type == null) {
- final type = variable.declaredElement!.type;
- if (!type.isDynamic && keyword != null) {
- builder.addReplacement(range.token(keyword), (builder) {
- validChange = builder.writeType(type);
- });
+ await builder.addDartFileEdit(file, (builder) {
+ if (variableList.type == null) {
+ final type = variable.declaredElement!.type;
+ if (!type.isDynamic && keyword != null) {
+ if (!builder.canWriteType(type)) {
+ return;
}
+ builder.addReplacement(range.token(keyword), (builder) {
+ builder.writeType(type);
+ });
}
+ }
- var indent = utils.getNodePrefix(statement);
- var name = variable.name.name;
- builder.addSimpleInsertion(
- variable.name.end, ';' + eol + indent + name);
- });
- return validChange;
- }
-
- if (await tryToApplyChange(_temporaryBuilder(builder))) {
- await tryToApplyChange(builder);
- }
+ var indent = utils.getNodePrefix(statement);
+ var name = variable.name.name;
+ builder.addSimpleInsertion(
+ variable.name.end, ';' + eol + indent + name);
+ });
}
- ChangeBuilder _temporaryBuilder(ChangeBuilder builder) =>
- ChangeBuilder(workspace: (builder as ChangeBuilderImpl).workspace);
-
/// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
static SplitVariableDeclaration newInstance() => SplitVariableDeclaration();
}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/split_variable_declaration_test.dart b/pkg/analysis_server/test/src/services/correction/assist/split_variable_declaration_test.dart
index cca64e3..4fb3e72 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/split_variable_declaration_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/split_variable_declaration_test.dart
@@ -119,7 +119,7 @@
''');
}
- Future<void> test_unknownType() async {
+ Future<void> test_privateType() async {
addSource('/home/test/lib/a.dart', '''
class A {
_B b => _B();
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
index 7d86a7f..0738926 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
@@ -57,6 +57,12 @@
(builder) => buildLinkedEdit(builder as DartLinkedEditBuilder));
@override
+ bool canWriteType(DartType? type, {ExecutableElement? methodBeingCopied}) =>
+ type != null && !type.isDynamic
+ ? _canWriteType(type, methodBeingCopied: methodBeingCopied)
+ : false;
+
+ @override
LinkedEditBuilderImpl createLinkedEditBuilder() {
return DartLinkedEditBuilderImpl(this);
}
@@ -838,6 +844,60 @@
}
}
+ /// Check if the code to reference [type] in this compilation unit can be
+ /// written.
+ ///
+ /// See also [_writeType]
+ bool _canWriteType(DartType? type,
+ {ExecutableElement? methodBeingCopied, bool required = false}) {
+ type = _getVisibleType(type, methodBeingCopied: methodBeingCopied);
+
+ // If not a useful type, don't write it.
+ if (type == null) {
+ return false;
+ }
+ if (type.isDynamic) {
+ if (required) {
+ return true;
+ }
+ return false;
+ }
+ if (type.isBottom) {
+ var library = dartFileEditBuilder.resolvedUnit.libraryElement;
+ if (library.isNonNullableByDefault) {
+ return true;
+ }
+ return false;
+ }
+
+ var alias = type.alias;
+ if (alias != null) {
+ return true;
+ }
+
+ if (type is FunctionType) {
+ return true;
+ }
+
+ if (type is InterfaceType) {
+ return true;
+ }
+
+ if (type is NeverType) {
+ return true;
+ }
+
+ if (type is TypeParameterType) {
+ return true;
+ }
+
+ if (type is VoidType) {
+ return true;
+ }
+
+ throw UnimplementedError('(${type.runtimeType}) $type');
+ }
+
/// Generate a name that does not occur in [existingNames] that begins with
/// the given [prefix].
String _generateUniqueName(Set<String> existingNames, String prefix) {
@@ -1301,6 +1361,12 @@
range, (builder) => buildEdit(builder as DartEditBuilder));
@override
+ bool canWriteType(DartType? type, {ExecutableElement? methodBeingCopied}) {
+ var builder = createEditBuilder(0, 0);
+ return builder.canWriteType(type, methodBeingCopied: methodBeingCopied);
+ }
+
+ @override
void convertFunctionFromSyncToAsync(
FunctionBody? body, TypeProvider typeProvider) {
if (body == null || body.keyword != null) {
diff --git a/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart
index af9b40a..946343c 100644
--- a/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart
@@ -20,6 +20,17 @@
void addLinkedEdit(String groupName,
void Function(DartLinkedEditBuilder builder) buildLinkedEdit);
+ /// Check if the code for a type annotation for the given [type] can be
+ /// written.
+ ///
+ /// If a [methodBeingCopied] is provided, then type parameters defined by that
+ /// method are assumed to be part of what is being written and hence valid
+ /// types.
+ ///
+ /// The logic is the same as the one used in [writeType]
+ bool canWriteType(DartType? type,
+ {ExecutableElement? methodBeingCopied});
+
/// Write the code for a declaration of a class with the given [name]. If a
/// list of [interfaces] is provided, then the class will implement those
/// interfaces. If [isAbstract] is `true`, then the class will be abstract. If
@@ -299,6 +310,15 @@
void addReplacement(
SourceRange range, void Function(DartEditBuilder builder) buildEdit);
+ /// Check if the code for a type annotation for the given [type] can be
+ /// written.
+ ///
+ /// If a [methodBeingCopied] is provided, then type parameters defined by that
+ /// method are assumed to be part of what is being written and hence valid
+ /// types.
+ bool canWriteType(DartType? type,
+ {ExecutableElement? methodBeingCopied});
+
/// Create one or more edits that will convert the given function [body] from
/// being synchronous to be asynchronous. This includes adding the `async`
/// modifier to the body as well as potentially replacing the return type of
diff --git a/tools/VERSION b/tools/VERSION
index b004d65..8a31d56 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 15
PATCH 0
-PRERELEASE 40
+PRERELEASE 41
PRERELEASE_PATCH 0
\ No newline at end of file