blob: af8eb02d9d01dcfdd41d49dba83f74f3cadb7160 [file] [log] [blame]
// Copyright (c) 2020, 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/src/services/correction/dart/abstract_producer.dart';
import 'package:analysis_server/src/services/correction/name_suggestion.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/utilities/assist/assist.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
class IntroduceLocalCastType extends CorrectionProducer {
@override
AssistKind get assistKind => DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE;
@override
Future<void> compute(ChangeBuilder builder) async {
var node = this.node;
if (node is IfStatement) {
node = (node as IfStatement).condition;
} else if (node is WhileStatement) {
node = (node as WhileStatement).condition;
}
// prepare IsExpression
if (node is! IsExpression) {
return;
}
IsExpression isExpression = node;
var castType = isExpression.type.type;
var castTypeCode = utils.getNodeText(isExpression.type);
// prepare environment
var indent = utils.getIndent(1);
String prefix;
Block targetBlock;
{
var statement = node.thisOrAncestorOfType<Statement>();
if (statement is IfStatement && statement.thenStatement is Block) {
targetBlock = statement.thenStatement;
} else if (statement is WhileStatement && statement.body is Block) {
targetBlock = statement.body;
} else {
return;
}
prefix = utils.getNodePrefix(statement);
}
// prepare location
int offset;
String statementPrefix;
if (isExpression.notOperator == null) {
offset = targetBlock.leftBracket.end;
statementPrefix = indent;
} else {
offset = targetBlock.rightBracket.end;
statementPrefix = '';
}
// prepare excluded names
var excluded = <String>{};
var scopedNameFinder = ScopedNameFinder(offset);
isExpression.accept(scopedNameFinder);
excluded.addAll(scopedNameFinder.locals.keys.toSet());
// name(s)
var suggestions =
getVariableNameSuggestionsForExpression(castType, null, excluded);
if (suggestions.isNotEmpty) {
await builder.addDartFileEdit(file, (builder) {
builder.addInsertion(offset, (builder) {
builder.write(eol + prefix + statementPrefix);
builder.write(castTypeCode);
builder.write(' ');
builder.addSimpleLinkedEdit('NAME', suggestions[0],
kind: LinkedEditSuggestionKind.VARIABLE,
suggestions: suggestions);
builder.write(' = ');
builder.write(utils.getNodeText(isExpression.expression));
builder.write(';');
builder.selectHere();
});
});
}
}
/// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
static IntroduceLocalCastType newInstance() => IntroduceLocalCastType();
}