| // 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(); |
| } |