blob: ecabe3cbca92f59034033c671af2bebe2479097f [file] [log] [blame]
// Copyright (c) 2019, 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/util.dart';
import 'package:analysis_server/src/utilities/flutter.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:analyzer/src/dart/analysis/session_helper.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_workspace.dart';
import 'package:meta/meta.dart';
abstract class CorrectionProducer {
CorrectionProducerContext _context;
/// Returns the EOL to use for this [CompilationUnit].
String get eol => utils.endOfLine;
String get file => _context.file;
AstNode get node => _context.node;
int get selectionLength => _context.selectionLength;
int get selectionOffset => _context.selectionOffset;
TypeProvider get typeProvider => _context.typeProvider;
CorrectionUtils get utils => _context.utils;
Future<void> compute(DartChangeBuilder builder);
void configure(CorrectionProducerContext context) {
_context = context;
}
/// Return the text of the given [range] in the unit.
String getRangeText(SourceRange range) {
return utils.getRangeText(range);
}
/// Return `true` if the selection covers an operator of the given
/// [binaryExpression].
bool isOperatorSelected(BinaryExpression binaryExpression) {
AstNode left = binaryExpression.leftOperand;
AstNode right = binaryExpression.rightOperand;
// between the nodes
if (selectionOffset >= left.end &&
selectionOffset + selectionLength <= right.offset) {
return true;
}
// or exactly select the node (but not with infix expressions)
if (selectionOffset == left.offset &&
selectionOffset + selectionLength == right.end) {
if (left is BinaryExpression || right is BinaryExpression) {
return false;
}
return true;
}
// invalid selection (part of node, etc)
return false;
}
}
class CorrectionProducerContext {
final int selectionOffset;
final int selectionLength;
final int selectionEnd;
final CorrectionUtils utils;
final String file;
final TypeProvider typeProvider;
final Flutter flutter;
final AnalysisSession session;
final AnalysisSessionHelper sessionHelper;
final ResolvedUnitResult resolvedResult;
final ChangeWorkspace workspace;
AstNode _node;
CorrectionProducerContext({
this.selectionOffset = -1,
this.selectionLength = 0,
@required this.resolvedResult,
@required this.workspace,
}) : file = resolvedResult.path,
flutter = Flutter.of(resolvedResult),
session = resolvedResult.session,
sessionHelper = AnalysisSessionHelper(resolvedResult.session),
typeProvider = resolvedResult.typeProvider,
selectionEnd = (selectionOffset ?? 0) + (selectionLength ?? 0),
utils = CorrectionUtils(resolvedResult);
AstNode get node => _node;
bool setupCompute() {
final locator = NodeLocator(selectionOffset, selectionEnd);
_node = locator.searchWithin(resolvedResult.unit);
return _node != null;
}
}