Skip to content

Commit

Permalink
Version 2.18.0-179.0.dev
Browse files Browse the repository at this point in the history
Merge commit '57b192f3a63ac109cd7550071c52cec69e637aeb' into 'dev'
  • Loading branch information
Dart CI committed Jun 12, 2022
2 parents e7281c5 + 57b192f commit 41e17af
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,31 @@

import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:collection/collection.dart';

class AddAwait extends CorrectionProducer {
/// The kind of correction to be made.
final _CorrectionKind _correctionKind;

@override
bool get canBeAppliedInBulk => true;
bool canBeAppliedInBulk;

@override
bool get canBeAppliedToFile => true;
bool canBeAppliedToFile;

AddAwait.nonBool()
: _correctionKind = _CorrectionKind.nonBool,
canBeAppliedInBulk = false,
canBeAppliedToFile = false;

AddAwait.unawaited()
: _correctionKind = _CorrectionKind.unawaited,
canBeAppliedInBulk = true,
canBeAppliedToFile = true;

@override
FixKind get fixKind => DartFixKind.ADD_AWAIT;
Expand All @@ -22,8 +38,34 @@ class AddAwait extends CorrectionProducer {

@override
Future<void> compute(ChangeBuilder builder) async {
if (_correctionKind == _CorrectionKind.unawaited) {
await _addAwait(builder);
} else if (_correctionKind == _CorrectionKind.nonBool) {
await _computeNonBool(builder);
}
}

Future<void> _addAwait(ChangeBuilder builder) async {
await builder.addDartFileEdit(file, (builder) {
builder.addSimpleInsertion(node.offset, 'await ');
});
}

Future<void> _computeNonBool(ChangeBuilder builder) async {
var expr = node;
if (expr is! Expression) return;
var staticType = expr.staticType;
if (staticType is! ParameterizedType) return;

if (staticType.isDartAsyncFuture &&
staticType.typeArguments.firstOrNull?.isDartCoreBool == true) {
await _addAwait(builder);
}
}
}

/// The kinds of corrections supported by [AddAwait].
enum _CorrectionKind {
unawaited,
nonBool,
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ class RemoveTypeAnnotation extends CorrectionProducer {
Future<void> _removeFromDeclarationList(
ChangeBuilder builder, VariableDeclarationList declarationList) async {
// we need a type
var typeNode = declarationList.type;
if (typeNode == null) {
var type = declarationList.type;
if (type == null) {
return;
}
// ignore if an incomplete variable declaration
Expand All @@ -63,19 +63,60 @@ class RemoveTypeAnnotation extends CorrectionProducer {
if (selectionOffset > firstVariable.name.end) {
return;
}

var initializer = firstVariable.initializer;
// The variable must have an initializer, otherwise there is no other
// source for its type.
if (firstVariable.initializer == null) {
if (initializer == null) {
return;
}

String? typeArgumentsText;
int? typeArgumentsOffset;
if (type is NamedType) {
var typeArguments = type.typeArguments;
if (typeArguments != null) {
if (initializer is CascadeExpression) {
initializer = initializer.target;
}
if (initializer is TypedLiteral) {
if (initializer.typeArguments == null) {
typeArgumentsText = utils.getNodeText(typeArguments);
if (initializer is ListLiteral) {
typeArgumentsOffset = initializer.leftBracket.offset;
} else if (initializer is SetOrMapLiteral) {
typeArgumentsOffset = initializer.leftBracket.offset;
} else {
throw StateError('Unhandled subclass of TypedLiteral');
}
}
} else if (initializer is InstanceCreationExpression) {
if (initializer.constructorName.type.typeArguments == null) {
typeArgumentsText = utils.getNodeText(typeArguments);
typeArgumentsOffset = initializer.constructorName.type.end;
}
}
}
}
if (initializer is SetOrMapLiteral &&
initializer.typeArguments == null &&
typeArgumentsText == null) {
// This is to prevent the fix from converting a valid map or set literal
// into an ambiguous literal. We could apply this in more places
// by examining the elements of the collection.
return;
}
var keyword = declarationList.keyword;
await builder.addDartFileEdit(file, (builder) {
var typeRange = range.startStart(typeNode, firstVariable);
var typeRange = range.startStart(type, firstVariable);
if (keyword != null && keyword.lexeme != 'var') {
builder.addSimpleReplacement(typeRange, '');
} else {
builder.addSimpleReplacement(typeRange, 'var ');
}
if (typeArgumentsText != null && typeArgumentsOffset != null) {
builder.addSimpleInsertion(typeArgumentsOffset, typeArgumentsText);
}
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ class ReplaceWithVar extends CorrectionProducer {
typeArgumentsOffset = initializer.leftBracket.offset;
} else if (initializer is SetOrMapLiteral) {
typeArgumentsOffset = initializer.leftBracket.offset;
} else {
throw StateError('Unhandled subclass of TypedLiteral');
}
}
} else if (initializer is InstanceCreationExpression) {
Expand All @@ -77,9 +79,9 @@ class ReplaceWithVar extends CorrectionProducer {
if (initializer is SetOrMapLiteral &&
initializer.typeArguments == null &&
typeArgumentsText == null) {
// TODO(brianwilkerson) This is to prevent the fix from converting a
// valid map or set literal into an ambiguous literal. We could apply
// this in more places by examining the elements of the collection.
// This is to prevent the fix from converting a valid map or set literal
// into an ambiguous literal. We could apply this in more places
// by examining the elements of the collection.
return;
}
await builder.addDartFileEdit(file, (builder) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ class FixProcessor extends BaseProcessor {
RemoveTypeAnnotation.new,
],
LintNames.unawaited_futures: [
AddAwait.new,
AddAwait.unawaited,
],
LintNames.unnecessary_brace_in_string_interps: [
RemoveInterpolationBraces.new,
Expand Down Expand Up @@ -1010,6 +1010,7 @@ class FixProcessor extends BaseProcessor {
],
CompileTimeErrorCode.NON_BOOL_CONDITION: [
AddNeNull.new,
AddAwait.nonBool,
],
CompileTimeErrorCode.NON_CONST_GENERATIVE_ENUM_CONSTRUCTOR: [
AddConst.new,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,45 @@ class A {
await assertNoAssistAt('v');
}

Future<void> test_generic_instanceCreation_withoutArguments() async {
await resolveTestCode('''
C<int> c = C();
class C<T> {}
''');
await assertHasAssistAt('c = ', '''
var c = C<int>();
class C<T> {}
''');
}

Future<void> test_generic_listLiteral() async {
await resolveTestCode('''
List<int> l = [];
''');
await assertHasAssistAt('l = ', '''
var l = <int>[];
''');
}

Future<void> test_generic_setLiteral_ambiguous() async {
await resolveTestCode('''
Set f() {
/*caret*/Set s = {};
return s;
}
''');
await assertNoAssist();
}

Future<void> test_generic_setLiteral_cascade() async {
await resolveTestCode('''
Set<String> s = {}..addAll([]);
''');
await assertHasAssistAt('s = ', '''
var s = <String>{}..addAll([]);
''');
}

Future<void> test_instanceCreation_freeStanding() async {
await resolveTestCode('''
class A {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,35 @@ void f() async {
}
''');
}

Future<void> test_nonBoolCondition_futureBool() async {
await resolveTestCode('''
Future<bool> doSomething() async => true;
Future<void> f() async {
if (doSomething()) {
}
}
''');
await assertHasFix('''
Future<bool> doSomething() async => true;
Future<void> f() async {
if (await doSomething()) {
}
}
''');
}

Future<void> test_nonBoolCondition_futureInt() async {
await resolveTestCode('''
Future<int> doSomething() async => 0;
Future<void> f() async {
if (doSomething()) {
}
}
''');
await assertNoFix();
}
}
15 changes: 11 additions & 4 deletions pkg/analyzer/lib/src/lint/linter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/scope.dart';
import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/file_system/file_system.dart' as file_system;
Expand Down Expand Up @@ -636,25 +637,31 @@ abstract class LintRule extends Linter implements Comparable<LintRule> {

void reportLint(AstNode? node,
{List<Object> arguments = const [],
List<DiagnosticMessage>? contextMessages,
ErrorCode? errorCode,
bool ignoreSyntheticNodes = true}) {
if (node != null && (!node.isSynthetic || !ignoreSyntheticNodes)) {
reporter.reportErrorForNode(errorCode ?? lintCode, node, arguments);
reporter.reportErrorForNode(
errorCode ?? lintCode, node, arguments, contextMessages);
}
}

void reportLintForOffset(int offset, int length,
{List<Object> arguments = const [], ErrorCode? errorCode}) {
{List<Object> arguments = const [],
List<DiagnosticMessage>? contextMessages,
ErrorCode? errorCode}) {
reporter.reportErrorForOffset(
errorCode ?? lintCode, offset, length, arguments);
errorCode ?? lintCode, offset, length, arguments, contextMessages);
}

void reportLintForToken(Token? token,
{List<Object> arguments = const [],
List<DiagnosticMessage>? contextMessages,
ErrorCode? errorCode,
bool ignoreSyntheticTokens = true}) {
if (token != null && (!token.isSynthetic || !ignoreSyntheticTokens)) {
reporter.reportErrorForToken(errorCode ?? lintCode, token, arguments);
reporter.reportErrorForToken(
errorCode ?? lintCode, token, arguments, contextMessages);
}
}

Expand Down
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 2
MINOR 18
PATCH 0
PRERELEASE 178
PRERELEASE 179
PRERELEASE_PATCH 0

0 comments on commit 41e17af

Please sign in to comment.