mirror of
https://github.com/dart-lang/sdk
synced 2024-10-04 18:36:29 +00:00
Simplify some CorrectionUtils code
The big one is `getIndent`, which I think can be simpler, and also used a handwritten implementation of `String.operator *`. It turns out: * > 90% of calls to `getIndent` were `getIndent(1)`, which can be replaced with a constant `' '`. * Then 4 calls to `getIndent` were `getIndent(2)`, which can be replaced with a constant `' ' + ' '`. * Then one last call, in CorrectionUtils itself, used a variable number of indents which can be replaced with `' ' * n`. This is in the `indentRight` function. Also: * Privatize `getInsertionLocationTop`, `isClassWithEmptyBody`, `isJustWhitespaceOrComment`, `skipEmptyLinesLeft` * Rewrite CorrectionUtils.findSimplePrintInvocation as an extension method on AstNode; does not need the `_buffer`. Change-Id: I15c19b8c0cc354adcd4ffea5803b3a182cf28336 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/358400 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Samuel Rawlins <srawlins@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
8f995c27f2
commit
a8a42cffd2
|
@ -309,7 +309,7 @@ class PostfixCompletionProcessor {
|
|||
builder.write(eol);
|
||||
var indent = utils.getNodePrefix(expr);
|
||||
builder.write(indent);
|
||||
builder.write(utils.getIndent(1));
|
||||
builder.write(utils.oneIndent);
|
||||
builder.selectHere();
|
||||
builder.write(eol);
|
||||
builder.write(indent);
|
||||
|
@ -351,7 +351,7 @@ class PostfixCompletionProcessor {
|
|||
builder.write('try {');
|
||||
builder.write(eol);
|
||||
builder.write(utils.replaceSourceIndent(
|
||||
src, indent, '$indent${utils.getIndent(1)}',
|
||||
src, indent, '$indent${utils.oneIndent}',
|
||||
includeLeading: true, ensureTrailingNewline: true));
|
||||
builder.selectHere();
|
||||
builder.write(indent);
|
||||
|
@ -363,7 +363,7 @@ class PostfixCompletionProcessor {
|
|||
builder.write(' catch (e, s) {');
|
||||
builder.write(eol);
|
||||
builder.write(indent);
|
||||
builder.write(utils.getIndent(1));
|
||||
builder.write(utils.oneIndent);
|
||||
builder.write('print(s);');
|
||||
builder.write(eol);
|
||||
builder.write(indent);
|
||||
|
|
|
@ -231,7 +231,7 @@ class StatementCompletionProcessor {
|
|||
sb.append(eol);
|
||||
var indent = utils.getLinePrefix(selectionOffset);
|
||||
sb.append(indent);
|
||||
sb.append(utils.getIndent(1));
|
||||
sb.append(utils.oneIndent);
|
||||
if (needsExitMark && sb.exitOffset == null) {
|
||||
sb.setExitOffset();
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ class AddCallSuper extends ResolvedCorrectionProducer {
|
|||
var expression = body.expression;
|
||||
var semicolon = body.semicolon;
|
||||
var prefix = utils.getLinePrefix(expression.offset);
|
||||
var prefixWithLine = eol + prefix + utils.getIndent(1);
|
||||
var prefixWithLine = eol + prefix + utils.oneIndent;
|
||||
|
||||
await builder.addDartFileEdit(file, (builder) {
|
||||
builder.addSimpleReplacement(
|
||||
|
|
|
@ -131,8 +131,8 @@ class AddDiagnosticPropertyReference extends ResolvedCorrectionProducer {
|
|||
await builder.addDartFileEdit(file, (builder) {
|
||||
builder.addInsertion(utils.getLineNext(insertOffset), (builder) {
|
||||
final declPrefix =
|
||||
utils.getLinePrefix(classDeclaration.offset) + utils.getIndent(1);
|
||||
final bodyPrefix = declPrefix + utils.getIndent(1);
|
||||
utils.getLinePrefix(classDeclaration.offset) + utils.oneIndent;
|
||||
final bodyPrefix = declPrefix + utils.oneIndent;
|
||||
|
||||
builder.writeln('$declPrefix@override');
|
||||
builder.writeln(
|
||||
|
@ -155,7 +155,7 @@ class AddDiagnosticPropertyReference extends ResolvedCorrectionProducer {
|
|||
String prefix;
|
||||
if (functionBody.block.statements.isEmpty) {
|
||||
offset = functionBody.block.leftBracket.offset;
|
||||
prefix = utils.getLinePrefix(offset) + utils.getIndent(1);
|
||||
prefix = utils.getLinePrefix(offset) + utils.oneIndent;
|
||||
} else {
|
||||
offset = functionBody.block.statements.last.endToken.offset;
|
||||
prefix = utils.getLinePrefix(offset);
|
||||
|
|
|
@ -81,7 +81,7 @@ class AddMissingEnumCaseClauses extends ResolvedCorrectionProducer {
|
|||
}
|
||||
|
||||
var statementIndent = utils.getLinePrefix(statement.offset);
|
||||
var singleIndent = utils.getIndent(1);
|
||||
var singleIndent = utils.oneIndent;
|
||||
var location = utils.newCaseClauseAtEndLocation(
|
||||
switchKeyword: statement.switchKeyword,
|
||||
leftBracket: statement.leftBracket,
|
||||
|
|
|
@ -34,7 +34,7 @@ class AddMissingEnumLikeCaseClauses extends ResolvedCorrectionProducer {
|
|||
missingNames.sort();
|
||||
|
||||
var statementIndent = utils.getLinePrefix(node.offset);
|
||||
var singleIndent = utils.getIndent(1);
|
||||
var singleIndent = utils.oneIndent;
|
||||
var location = utils.newCaseClauseAtEndLocation(
|
||||
switchKeyword: node.switchKeyword,
|
||||
leftBracket: node.leftBracket,
|
||||
|
|
|
@ -58,7 +58,7 @@ class AddMissingSwitchCases extends ResolvedCorrectionProducer {
|
|||
required List<MissingPatternPart> patternParts,
|
||||
}) async {
|
||||
final lineIndent = utils.getLinePrefix(node.offset);
|
||||
final singleIndent = utils.getIndent(1);
|
||||
final singleIndent = utils.oneIndent;
|
||||
final location = utils.newCaseClauseAtEndLocation(
|
||||
switchKeyword: node.switchKeyword,
|
||||
leftBracket: node.leftBracket,
|
||||
|
@ -86,7 +86,7 @@ class AddMissingSwitchCases extends ResolvedCorrectionProducer {
|
|||
required List<MissingPatternPart> patternParts,
|
||||
}) async {
|
||||
final lineIndent = utils.getLinePrefix(node.offset);
|
||||
final singleIndent = utils.getIndent(1);
|
||||
final singleIndent = utils.oneIndent;
|
||||
final location = utils.newCaseClauseAtEndLocation(
|
||||
switchKeyword: node.switchKeyword,
|
||||
leftBracket: node.leftBracket,
|
||||
|
|
|
@ -40,7 +40,7 @@ class AddOverride extends ResolvedCorrectionProducer {
|
|||
}
|
||||
|
||||
var exitPosition = Position(file, token.offset - 1);
|
||||
var indent = utils.getIndent(1);
|
||||
var indent = utils.oneIndent;
|
||||
await builder.addDartFileEdit(file, (builder) {
|
||||
builder.addSimpleReplacement(
|
||||
range.startLength(token, 0), '@override$eol$indent');
|
||||
|
|
|
@ -27,7 +27,7 @@ class AddRedeclare extends ResolvedCorrectionProducer {
|
|||
if (member == null) return;
|
||||
|
||||
var token = member.firstTokenAfterCommentAndMetadata;
|
||||
var indent = utils.getIndent(1);
|
||||
var indent = utils.oneIndent;
|
||||
await builder.addDartFileEdit(file, (builder) {
|
||||
builder.addInsertion(token.offset, (builder) {
|
||||
builder.write('@');
|
||||
|
|
|
@ -50,8 +50,7 @@ class AddReturnNull extends ResolvedCorrectionProducer {
|
|||
if (block.statements.isEmpty) {
|
||||
position = block.offset + 1;
|
||||
var prefix = utils.getLinePrefix(block.offset);
|
||||
returnStatement =
|
||||
'$eol$prefix${utils.getIndent(1)}return null;$eol$prefix';
|
||||
returnStatement = '$eol$prefix${utils.oneIndent}return null;$eol$prefix';
|
||||
} else {
|
||||
var lastStatement = block.statements.last;
|
||||
position = lastStatement.offset + lastStatement.length;
|
||||
|
|
|
@ -187,7 +187,7 @@ class _EnumDescription {
|
|||
// Compute the declarations of the enum constants and delete the fields
|
||||
// being converted.
|
||||
var members = classDeclaration.members;
|
||||
var indent = utils.getIndent(1);
|
||||
var indent = utils.oneIndent;
|
||||
var eol = utils.endOfLine;
|
||||
var constantsBuffer = StringBuffer();
|
||||
var fieldsToConvert = fields.fieldsToConvert;
|
||||
|
|
|
@ -32,7 +32,7 @@ class ConvertFlutterChild extends ResolvedCorrectionProducer {
|
|||
eol,
|
||||
utils.getNodeText,
|
||||
utils.getLinePrefix,
|
||||
utils.getIndent,
|
||||
utils.oneIndent,
|
||||
utils.getText,
|
||||
utils.replaceSourceIndent,
|
||||
range.node);
|
||||
|
|
|
@ -72,7 +72,7 @@ class ConvertIntoBlockBody extends ResolvedCorrectionProducer {
|
|||
|
||||
// prepare prefix
|
||||
var prefix = utils.getNodePrefix(body.parent!);
|
||||
var indent = utils.getIndent(1);
|
||||
var indent = utils.oneIndent;
|
||||
var sourceRange = range.endEnd(body.beginToken.previous!, body);
|
||||
|
||||
await builder.addDartFileEdit(file, (builder) {
|
||||
|
|
|
@ -78,7 +78,7 @@ class ConvertIntoForIndex extends ResolvedCorrectionProducer {
|
|||
}
|
||||
// prepare environment
|
||||
var prefix = utils.getNodePrefix(forStatement);
|
||||
var indent = utils.getIndent(1);
|
||||
var indent = utils.oneIndent;
|
||||
var firstBlockLine = utils.getLineContentEnd(body.leftBracket.end);
|
||||
// add change
|
||||
await builder.addDartFileEdit(file, (builder) {
|
||||
|
|
|
@ -132,7 +132,7 @@ class ConvertToIfCaseStatementChain extends ResolvedCorrectionProducer {
|
|||
|
||||
final range = utils.getLinesRangeStatements(statements);
|
||||
final firstIndent = utils.getLinePrefix(first.offset);
|
||||
final singleIndent = utils.getIndent(1);
|
||||
final singleIndent = utils.oneIndent;
|
||||
|
||||
final code = utils.replaceSourceRangeIndent(
|
||||
range,
|
||||
|
|
|
@ -41,7 +41,7 @@ class ConvertIfStatementToSwitchStatement extends ResolvedCorrectionProducer {
|
|||
}
|
||||
|
||||
final indent = utils.getLinePrefix(ifStatement.offset);
|
||||
final singleIndent = utils.getIndent(1);
|
||||
final singleIndent = utils.oneIndent;
|
||||
final caseIndent = '$indent$singleIndent';
|
||||
|
||||
await builder.addDartFileEdit(file, (builder) {
|
||||
|
@ -185,7 +185,7 @@ class ConvertIfStatementToSwitchStatement extends ResolvedCorrectionProducer {
|
|||
// switch
|
||||
// case
|
||||
// statement
|
||||
final singleIndent = utils.getIndent(1);
|
||||
final singleIndent = utils.oneIndent;
|
||||
final newIndent = '$ifStatementIndent$singleIndent';
|
||||
|
||||
final code = utils.replaceSourceRangeIndent(
|
||||
|
|
|
@ -52,7 +52,7 @@ class CreateMissingOverrides extends ResolvedCorrectionProducer {
|
|||
return;
|
||||
}
|
||||
|
||||
var prefix = utils.getIndent(1);
|
||||
var prefix = utils.oneIndent;
|
||||
await builder.addDartFileEdit(file, (builder) {
|
||||
final syntheticLeftBracket = targetClass.leftBracket.isSynthetic;
|
||||
if (syntheticLeftBracket) {
|
||||
|
|
|
@ -19,7 +19,7 @@ class CreateNoSuchMethod extends ResolvedCorrectionProducer {
|
|||
return;
|
||||
}
|
||||
// prepare environment
|
||||
var prefix = utils.getIndent(1);
|
||||
var prefix = utils.oneIndent;
|
||||
var insertOffset = targetClass.end - 1;
|
||||
await builder.addDartFileEdit(file, (builder) {
|
||||
builder.addInsertion(insertOffset, (builder) {
|
||||
|
|
|
@ -36,7 +36,7 @@ class FlutterConvertToChildren extends ResolvedCorrectionProducer {
|
|||
|
||||
await builder.addDartFileEdit(file, (builder) {
|
||||
_convertFlutterChildToChildren(namedExp, eol, utils.getNodeText,
|
||||
utils.getLinePrefix, utils.getIndent, utils.getText, builder);
|
||||
utils.getLinePrefix, utils.getText, builder);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,6 @@ class FlutterConvertToChildren extends ResolvedCorrectionProducer {
|
|||
String eol,
|
||||
String Function(Expression) getNodeText,
|
||||
String Function(int) getLinePrefix,
|
||||
String Function(int) getIndent,
|
||||
String Function(int, int) getText,
|
||||
FileEditBuilder builder) {
|
||||
var childArg = namedExp.expression;
|
||||
|
@ -62,7 +61,7 @@ class FlutterConvertToChildren extends ResolvedCorrectionProducer {
|
|||
newlineLoc -= 1;
|
||||
}
|
||||
var indentOld = getLinePrefix(childArg.offset + eol.length + newlineLoc);
|
||||
var indentNew = '$indentOld${getIndent(1)}';
|
||||
var indentNew = '$indentOld${utils.oneIndent}';
|
||||
// The separator includes 'child:' but that has no newlines.
|
||||
var separator =
|
||||
getText(namedExp.offset, childArg.offset - namedExp.offset);
|
||||
|
|
|
@ -223,8 +223,8 @@ abstract class _WrapMultipleWidgets extends ResolvedCorrectionProducer {
|
|||
builder.write('(');
|
||||
|
||||
var indentOld = utils.getLinePrefix(firstWidget.offset);
|
||||
var indentNew1 = indentOld + utils.getIndent(1);
|
||||
var indentNew2 = indentOld + utils.getIndent(2);
|
||||
var indentNew1 = indentOld + utils.oneIndent;
|
||||
var indentNew2 = indentOld + utils.twoIndents;
|
||||
|
||||
builder.write(eol);
|
||||
builder.write(indentNew1);
|
||||
|
@ -299,7 +299,7 @@ abstract class _WrapSingleWidget extends ResolvedCorrectionProducer {
|
|||
var leadingLines = _leadingLines;
|
||||
if (widgetSrc.contains(eol) || leadingLines.isNotEmpty) {
|
||||
var indentOld = utils.getLinePrefix(widgetExpr.offset);
|
||||
var indentNew = '$indentOld${utils.getIndent(1)}';
|
||||
var indentNew = '$indentOld${utils.oneIndent}';
|
||||
|
||||
for (var leadingLine in leadingLines) {
|
||||
builder.write(eol);
|
||||
|
|
|
@ -40,8 +40,8 @@ class FlutterWrapBuilder extends ResolvedCorrectionProducer {
|
|||
builder.writeln('(');
|
||||
|
||||
var indentOld = utils.getLinePrefix(widgetExpr.offset);
|
||||
var indentNew1 = indentOld + utils.getIndent(1);
|
||||
var indentNew2 = indentOld + utils.getIndent(2);
|
||||
var indentNew1 = indentOld + utils.oneIndent;
|
||||
var indentNew2 = indentOld + utils.twoIndents;
|
||||
|
||||
builder.write(indentNew1);
|
||||
builder.writeln('builder: (context) {');
|
||||
|
|
|
@ -30,8 +30,8 @@ class FlutterWrapGeneric extends ResolvedCorrectionProducer {
|
|||
return; // Lists need to be in multi-line format already.
|
||||
}
|
||||
var indentOld = utils.getLinePrefix(node.offset + eol.length + newlineIdx);
|
||||
var indentArg = '$indentOld${utils.getIndent(1)}';
|
||||
var indentList = '$indentOld${utils.getIndent(2)}';
|
||||
var indentArg = '$indentOld${utils.oneIndent}';
|
||||
var indentList = '$indentOld${utils.twoIndents}';
|
||||
|
||||
await builder.addDartFileEdit(file, (builder) {
|
||||
builder.addReplacement(range.node(node), (builder) {
|
||||
|
|
|
@ -42,8 +42,8 @@ class FlutterWrapStreamBuilder extends ResolvedCorrectionProducer {
|
|||
builder.writeln('>(');
|
||||
|
||||
var indentOld = utils.getLinePrefix(widgetExpr.offset);
|
||||
var indentNew1 = indentOld + utils.getIndent(1);
|
||||
var indentNew2 = indentOld + utils.getIndent(2);
|
||||
var indentNew1 = indentOld + utils.oneIndent;
|
||||
var indentNew2 = indentOld + utils.twoIndents;
|
||||
|
||||
builder.write(indentNew1);
|
||||
builder.writeln('stream: null,');
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
|
||||
import 'package:analysis_server/src/services/correction/fix.dart';
|
||||
import 'package:analysis_server/src/utilities/extensions/ast.dart';
|
||||
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
|
||||
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
|
||||
|
||||
|
@ -25,14 +26,14 @@ class MakeConditionalOnDebugMode extends ResolvedCorrectionProducer {
|
|||
if (unitResult.session.uriConverter.uriToPath(_foundationUri) == null) {
|
||||
return;
|
||||
}
|
||||
var printInvocation = utils.findSimplePrintInvocation(node);
|
||||
var printInvocation = node.findSimplePrintInvocation();
|
||||
if (printInvocation != null) {
|
||||
var indent = utils.getLinePrefix(printInvocation.offset);
|
||||
await builder.addDartFileEdit(file, (builder) {
|
||||
builder.addInsertion(printInvocation.offset, (builder) {
|
||||
builder.writeln('if (kDebugMode) {');
|
||||
builder.write(indent);
|
||||
builder.write(utils.getIndent(1));
|
||||
builder.write(utils.oneIndent);
|
||||
});
|
||||
builder.addInsertion(printInvocation.end, (builder) {
|
||||
builder.writeln();
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
|
||||
import 'package:analysis_server/src/services/correction/fix.dart';
|
||||
import 'package:analysis_server/src/utilities/extensions/ast.dart';
|
||||
import 'package:analyzer/source/source_range.dart';
|
||||
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
|
||||
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
|
||||
|
@ -25,7 +26,7 @@ class RemovePrint extends ResolvedCorrectionProducer {
|
|||
|
||||
@override
|
||||
Future<void> compute(ChangeBuilder builder) async {
|
||||
final printInvocation = utils.findSimplePrintInvocation(node);
|
||||
final printInvocation = node.findSimplePrintInvocation();
|
||||
if (printInvocation != null) {
|
||||
await builder.addDartFileEdit(file, (builder) {
|
||||
var start = utils.getLineContentStart(printInvocation.offset);
|
||||
|
|
|
@ -49,7 +49,7 @@ class ReplaceConditionalWithIfElse extends ResolvedCorrectionProducer {
|
|||
var conditional = assignment.rightHandSide;
|
||||
if (assignment.operator.type == TokenType.EQ &&
|
||||
conditional is ConditionalExpression) {
|
||||
var indent = utils.getIndent(1);
|
||||
var indent = utils.oneIndent;
|
||||
var prefix = utils.getNodePrefix(statement);
|
||||
|
||||
await builder.addDartFileEdit(file, (builder) {
|
||||
|
@ -75,7 +75,7 @@ class ReplaceConditionalWithIfElse extends ResolvedCorrectionProducer {
|
|||
) async {
|
||||
var conditional = statement.expression;
|
||||
if (conditional is ConditionalExpression) {
|
||||
var indent = utils.getIndent(1);
|
||||
var indent = utils.oneIndent;
|
||||
var prefix = utils.getNodePrefix(statement);
|
||||
|
||||
await builder.addDartFileEdit(file, (builder) {
|
||||
|
@ -100,7 +100,7 @@ class ReplaceConditionalWithIfElse extends ResolvedCorrectionProducer {
|
|||
for (var variable in statement.variables.variables) {
|
||||
var conditional = variable.initializer;
|
||||
if (conditional is ConditionalExpression) {
|
||||
var indent = utils.getIndent(1);
|
||||
var indent = utils.oneIndent;
|
||||
var prefix = utils.getNodePrefix(statement);
|
||||
|
||||
await builder.addDartFileEdit(file, (builder) {
|
||||
|
|
|
@ -51,7 +51,7 @@ class SplitAndCondition extends ResolvedCorrectionProducer {
|
|||
}
|
||||
// prepare environment
|
||||
var prefix = utils.getNodePrefix(ifStatement);
|
||||
var indent = utils.getIndent(1);
|
||||
var indent = utils.oneIndent;
|
||||
// prepare "rightCondition"
|
||||
String rightConditionSource;
|
||||
{
|
||||
|
|
|
@ -48,7 +48,7 @@ class SurroundWith extends MultiCorrectionProducer {
|
|||
var statementsRange = utils.getLinesRangeStatements(selectedStatements);
|
||||
// prepare environment
|
||||
var indentOld = utils.getNodePrefix(firstStatement);
|
||||
var indentNew = '$indentOld${utils.getIndent(1)}';
|
||||
var indentNew = '$indentOld${utils.oneIndent}';
|
||||
var indentedCode = utils.replaceSourceRangeIndent(
|
||||
statementsRange, indentOld, indentNew,
|
||||
includeLeading: true, ensureTrailingNewline: true);
|
||||
|
|
|
@ -77,7 +77,7 @@ class UseCurlyBraces extends ParsedCorrectionProducer {
|
|||
if (body is Block) return;
|
||||
|
||||
var prefix = utils.getLinePrefix(node.offset);
|
||||
var indent = prefix + utils.getIndent(1);
|
||||
var indent = prefix + utils.oneIndent;
|
||||
|
||||
await builder.addDartFileEdit(file, (builder) {
|
||||
_replaceRange(
|
||||
|
@ -100,7 +100,7 @@ class UseCurlyBraces extends ParsedCorrectionProducer {
|
|||
if (body is Block) return;
|
||||
|
||||
var prefix = utils.getLinePrefix(node.offset);
|
||||
var indent = prefix + utils.getIndent(1);
|
||||
var indent = prefix + utils.oneIndent;
|
||||
|
||||
await builder.addDartFileEdit(file, (builder) {
|
||||
_replace(builder, node.rightParenthesis, body, indent, prefix);
|
||||
|
@ -115,7 +115,7 @@ class UseCurlyBraces extends ParsedCorrectionProducer {
|
|||
}
|
||||
|
||||
var prefix = utils.getLinePrefix(node.offset);
|
||||
var indent = prefix + utils.getIndent(1);
|
||||
var indent = prefix + utils.oneIndent;
|
||||
|
||||
await builder.addDartFileEdit(file, (builder) {
|
||||
var thenStatement = node.thenStatement;
|
||||
|
@ -182,7 +182,7 @@ class UseCurlyBraces extends ParsedCorrectionProducer {
|
|||
if (body is Block) return;
|
||||
|
||||
var prefix = utils.getLinePrefix(node.offset);
|
||||
var indent = prefix + utils.getIndent(1);
|
||||
var indent = prefix + utils.oneIndent;
|
||||
|
||||
await builder.addDartFileEdit(file, (builder) {
|
||||
_replace(builder, node.rightParenthesis, body, indent, prefix);
|
||||
|
|
|
@ -128,7 +128,7 @@ Future<void> addLibraryImports(AnalysisSession session, SourceChange change,
|
|||
|
||||
// If still at the beginning of the file, skip shebang and line comments.
|
||||
{
|
||||
var desc = libUtils.getInsertionLocationTop();
|
||||
var desc = libUtils._getInsertionLocationTop();
|
||||
var offset = desc.offset;
|
||||
for (var i = 0; i < uriList.length; i++) {
|
||||
var importUri = uriList[i];
|
||||
|
@ -539,9 +539,15 @@ bool _allListsIdentical(List<List<Object>> lists, int position) {
|
|||
return true;
|
||||
}
|
||||
|
||||
class CorrectionUtils {
|
||||
final class CorrectionUtils {
|
||||
static const String _oneIndent = ' ';
|
||||
|
||||
static const String _twoIndents = _oneIndent + _oneIndent;
|
||||
|
||||
final CompilationUnit unit;
|
||||
|
||||
final LibraryElement? _library;
|
||||
|
||||
final String _buffer;
|
||||
|
||||
/// The [ClassElement] the generated code is inserted to, so we can decide if
|
||||
|
@ -571,6 +577,10 @@ class CorrectionUtils {
|
|||
}
|
||||
}
|
||||
|
||||
String get oneIndent => _oneIndent;
|
||||
|
||||
String get twoIndents => _twoIndents;
|
||||
|
||||
/// Returns the [AstNode] that encloses the given offset.
|
||||
AstNode? findNode(int offset) => NodeLocator(offset).searchWithin(unit);
|
||||
|
||||
|
@ -588,28 +598,6 @@ class CorrectionUtils {
|
|||
return conflicts;
|
||||
}
|
||||
|
||||
/// Returns the [ExpressionStatement] associated with [node] if [node] points
|
||||
/// to the identifier for a simple `print`. Returns `null`,
|
||||
/// otherwise.
|
||||
ExpressionStatement? findSimplePrintInvocation(AstNode node) {
|
||||
var parent = node.parent;
|
||||
var grandparent = parent?.parent;
|
||||
if (node is SimpleIdentifier) {
|
||||
var element = node.staticElement;
|
||||
if (element is FunctionElement &&
|
||||
element.name == 'print' &&
|
||||
element.library.isDartCore &&
|
||||
parent is MethodInvocation &&
|
||||
grandparent is ExpressionStatement) {
|
||||
return grandparent;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Returns the indentation with the given level.
|
||||
String getIndent(int level) => repeat(' ', level);
|
||||
|
||||
/// Returns a description of the place in which to insert an `ignore_for_file`
|
||||
/// comment.
|
||||
///
|
||||
|
@ -666,60 +654,6 @@ class CorrectionUtils {
|
|||
);
|
||||
}
|
||||
|
||||
/// Returns a description of the place in which to insert a new directive or a
|
||||
/// top-level declaration at the top of the file.
|
||||
InsertionLocation getInsertionLocationTop() {
|
||||
// skip leading line comments
|
||||
var offset = 0;
|
||||
var insertEmptyLineBefore = false;
|
||||
var insertEmptyLineAfter = false;
|
||||
var source = _buffer;
|
||||
// skip hash-bang
|
||||
if (offset < source.length - 2) {
|
||||
var linePrefix = getText(offset, 2);
|
||||
if (linePrefix == '#!') {
|
||||
insertEmptyLineBefore = true;
|
||||
offset = getLineNext(offset);
|
||||
// skip empty lines to first line comment
|
||||
var emptyOffset = offset;
|
||||
while (emptyOffset < source.length - 2) {
|
||||
var nextLineOffset = getLineNext(emptyOffset);
|
||||
var line = source.substring(emptyOffset, nextLineOffset);
|
||||
if (line.trim().isEmpty) {
|
||||
emptyOffset = nextLineOffset;
|
||||
continue;
|
||||
} else if (line.startsWith('//')) {
|
||||
offset = emptyOffset;
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// skip line comments
|
||||
while (offset < source.length - 2) {
|
||||
var linePrefix = getText(offset, 2);
|
||||
if (linePrefix == '//') {
|
||||
insertEmptyLineBefore = true;
|
||||
offset = getLineNext(offset);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// determine if empty line is required after
|
||||
var nextLineOffset = getLineNext(offset);
|
||||
var insertLine = source.substring(offset, nextLineOffset);
|
||||
if (insertLine.trim().isNotEmpty) {
|
||||
insertEmptyLineAfter = true;
|
||||
}
|
||||
return InsertionLocation(
|
||||
prefix: insertEmptyLineBefore ? endOfLine : '',
|
||||
offset: offset,
|
||||
suffix: insertEmptyLineAfter ? endOfLine : '',
|
||||
);
|
||||
}
|
||||
|
||||
/// Skips whitespace characters and single EOL on the right from [index].
|
||||
///
|
||||
/// If [index] the end of a statement or method, then in the most cases it is
|
||||
|
@ -811,7 +745,7 @@ class CorrectionUtils {
|
|||
var startOffset = sourceRange.offset;
|
||||
var startLineOffset = getLineContentStart(startOffset);
|
||||
if (skipLeadingEmptyLines) {
|
||||
startLineOffset = skipEmptyLinesLeft(startLineOffset);
|
||||
startLineOffset = _skipEmptyLinesLeft(startLineOffset);
|
||||
}
|
||||
// end
|
||||
var endOffset = sourceRange.end;
|
||||
|
@ -971,7 +905,7 @@ class CorrectionUtils {
|
|||
/// Lines that don't start with indentation are left as is.
|
||||
String indentLeft(String text) {
|
||||
final buffer = StringBuffer();
|
||||
final indent = getIndent(1);
|
||||
final indent = oneIndent;
|
||||
final eol = endOfLine;
|
||||
final lines = text.split(eol);
|
||||
for (final line in lines) {
|
||||
|
@ -989,10 +923,10 @@ class CorrectionUtils {
|
|||
return buffer.toString();
|
||||
}
|
||||
|
||||
/// Splits [text] into lines, and adds [level] indents to each line.
|
||||
/// Adds [level] indents to each line.
|
||||
String indentRight(String text, {int level = 1}) {
|
||||
final buffer = StringBuffer();
|
||||
final indent = getIndent(level);
|
||||
final indent = _oneIndent * level;
|
||||
final eol = endOfLine;
|
||||
final lines = text.split(eol);
|
||||
for (final line in lines) {
|
||||
|
@ -1007,7 +941,7 @@ class CorrectionUtils {
|
|||
/// Indents given source left or right.
|
||||
String indentSourceLeftRight(String source, {bool indentLeft = true}) {
|
||||
var sb = StringBuffer();
|
||||
var indent = getIndent(1);
|
||||
var indent = oneIndent;
|
||||
var eol = endOfLine;
|
||||
var lines = source.split(eol);
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
|
@ -1034,24 +968,6 @@ class CorrectionUtils {
|
|||
String invertCondition(Expression expression) =>
|
||||
_invertCondition0(expression)._source;
|
||||
|
||||
/// Return `true` if the given class, mixin, enum or extension [declaration]
|
||||
/// has open '{' and close '}' on the same line, e.g. `class X {}`.
|
||||
bool isClassWithEmptyBody(CompilationUnitMember declaration) {
|
||||
return getLineThis(_getLeftBracket(declaration)!.offset) ==
|
||||
getLineThis(_getRightBracket(declaration)!.offset);
|
||||
}
|
||||
|
||||
/// Return <code>true</code> if [range] contains only whitespace or comments.
|
||||
bool isJustWhitespaceOrComment(SourceRange range) {
|
||||
var trimmedText = getRangeText(range).trim();
|
||||
// may be whitespace
|
||||
if (trimmedText.isEmpty) {
|
||||
return true;
|
||||
}
|
||||
// may be comment
|
||||
return TokenUtils.getTokens(trimmedText, unit.featureSet).isEmpty;
|
||||
}
|
||||
|
||||
InsertionLocation newCaseClauseAtEndLocation({
|
||||
required Token switchKeyword,
|
||||
required Token leftBracket,
|
||||
|
@ -1074,14 +990,12 @@ class CorrectionUtils {
|
|||
InsertionLocation prepareEnumNewConstructorLocation(
|
||||
EnumDeclaration enumDeclaration,
|
||||
) {
|
||||
var indent = getIndent(1);
|
||||
|
||||
var targetMember = enumDeclaration.members
|
||||
.where((e) => e is FieldDeclaration || e is ConstructorDeclaration)
|
||||
.lastOrNull;
|
||||
if (targetMember != null) {
|
||||
return InsertionLocation(
|
||||
prefix: endOfLine + endOfLine + indent,
|
||||
prefix: endOfLine + endOfLine + oneIndent,
|
||||
offset: targetMember.end,
|
||||
suffix: '',
|
||||
);
|
||||
|
@ -1090,7 +1004,7 @@ class CorrectionUtils {
|
|||
var semicolon = enumDeclaration.semicolon;
|
||||
if (semicolon != null) {
|
||||
return InsertionLocation(
|
||||
prefix: endOfLine + endOfLine + indent,
|
||||
prefix: endOfLine + endOfLine + oneIndent,
|
||||
offset: semicolon.end,
|
||||
suffix: '',
|
||||
);
|
||||
|
@ -1098,7 +1012,7 @@ class CorrectionUtils {
|
|||
|
||||
var lastConstant = enumDeclaration.constants.last;
|
||||
return InsertionLocation(
|
||||
prefix: ';$endOfLine$endOfLine$indent',
|
||||
prefix: ';$endOfLine$endOfLine$oneIndent',
|
||||
offset: lastConstant.end,
|
||||
suffix: '',
|
||||
);
|
||||
|
@ -1107,7 +1021,6 @@ class CorrectionUtils {
|
|||
InsertionLocation? prepareNewClassMemberLocation(
|
||||
CompilationUnitMember declaration,
|
||||
bool Function(ClassMember existingMember) shouldSkip) {
|
||||
var indent = getIndent(1);
|
||||
// Find the last target member.
|
||||
ClassMember? targetMember;
|
||||
var members = _getMembers(declaration);
|
||||
|
@ -1124,17 +1037,17 @@ class CorrectionUtils {
|
|||
// After the last target member.
|
||||
if (targetMember != null) {
|
||||
return InsertionLocation(
|
||||
prefix: endOfLine + endOfLine + indent,
|
||||
prefix: endOfLine + endOfLine + oneIndent,
|
||||
offset: targetMember.end,
|
||||
suffix: '',
|
||||
);
|
||||
}
|
||||
// At the beginning of the class.
|
||||
var suffix = members.isNotEmpty || isClassWithEmptyBody(declaration)
|
||||
var suffix = members.isNotEmpty || _isClassWithEmptyBody(declaration)
|
||||
? endOfLine
|
||||
: '';
|
||||
return InsertionLocation(
|
||||
prefix: endOfLine + indent,
|
||||
prefix: endOfLine + oneIndent,
|
||||
offset: _getLeftBracket(declaration)!.end,
|
||||
suffix: suffix,
|
||||
);
|
||||
|
@ -1189,14 +1102,13 @@ class CorrectionUtils {
|
|||
var last = empty || first ? block.leftBracket : statements.last;
|
||||
|
||||
var linePrefix = getLinePrefix(last.offset);
|
||||
var indent = getIndent(1);
|
||||
String prefix;
|
||||
String suffix;
|
||||
if (empty) {
|
||||
prefix = endOfLine + linePrefix + indent;
|
||||
prefix = endOfLine + linePrefix + oneIndent;
|
||||
suffix = endOfLine + linePrefix;
|
||||
} else if (first) {
|
||||
prefix = endOfLine + linePrefix + indent;
|
||||
prefix = endOfLine + linePrefix + oneIndent;
|
||||
suffix = '';
|
||||
} else {
|
||||
prefix = endOfLine + linePrefix;
|
||||
|
@ -1303,25 +1215,6 @@ class CorrectionUtils {
|
|||
selection, range.node(node));
|
||||
}
|
||||
|
||||
/// Skip spaces, tabs and EOLs on the left from [index].
|
||||
///
|
||||
/// If [index] is the start of a method, then in the most cases return the end
|
||||
/// of the previous not-whitespace line.
|
||||
int skipEmptyLinesLeft(int index) {
|
||||
var lastLine = index;
|
||||
while (index > 0) {
|
||||
var c = _buffer.codeUnitAt(index - 1);
|
||||
if (!isWhitespace(c)) {
|
||||
return lastLine;
|
||||
}
|
||||
if (isEOL(c)) {
|
||||
lastLine = index;
|
||||
}
|
||||
index--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Return the import element used to import given [element] into the library.
|
||||
/// May be `null` if was not imported, i.e. declared in the same library.
|
||||
LibraryImportElement? _getImportElement(Element element) {
|
||||
|
@ -1338,6 +1231,60 @@ class CorrectionUtils {
|
|||
return null;
|
||||
}
|
||||
|
||||
/// Returns a description of the place in which to insert a new directive or a
|
||||
/// top-level declaration at the top of the file.
|
||||
InsertionLocation _getInsertionLocationTop() {
|
||||
// skip leading line comments
|
||||
var offset = 0;
|
||||
var insertEmptyLineBefore = false;
|
||||
var insertEmptyLineAfter = false;
|
||||
var source = _buffer;
|
||||
// skip hash-bang
|
||||
if (offset < source.length - 2) {
|
||||
var linePrefix = getText(offset, 2);
|
||||
if (linePrefix == '#!') {
|
||||
insertEmptyLineBefore = true;
|
||||
offset = getLineNext(offset);
|
||||
// skip empty lines to first line comment
|
||||
var emptyOffset = offset;
|
||||
while (emptyOffset < source.length - 2) {
|
||||
var nextLineOffset = getLineNext(emptyOffset);
|
||||
var line = source.substring(emptyOffset, nextLineOffset);
|
||||
if (line.trim().isEmpty) {
|
||||
emptyOffset = nextLineOffset;
|
||||
continue;
|
||||
} else if (line.startsWith('//')) {
|
||||
offset = emptyOffset;
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// skip line comments
|
||||
while (offset < source.length - 2) {
|
||||
var linePrefix = getText(offset, 2);
|
||||
if (linePrefix == '//') {
|
||||
insertEmptyLineBefore = true;
|
||||
offset = getLineNext(offset);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// determine if empty line is required after
|
||||
var nextLineOffset = getLineNext(offset);
|
||||
var insertLine = source.substring(offset, nextLineOffset);
|
||||
if (insertLine.trim().isNotEmpty) {
|
||||
insertEmptyLineAfter = true;
|
||||
}
|
||||
return InsertionLocation(
|
||||
prefix: insertEmptyLineBefore ? endOfLine : '',
|
||||
offset: offset,
|
||||
suffix: insertEmptyLineAfter ? endOfLine : '',
|
||||
);
|
||||
}
|
||||
|
||||
Token? _getLeftBracket(CompilationUnitMember declaration) {
|
||||
if (declaration is ClassDeclaration) {
|
||||
return declaration.leftBracket;
|
||||
|
@ -1549,6 +1496,24 @@ class CorrectionUtils {
|
|||
return _InvertedCondition._simple(getNodeText(expression));
|
||||
}
|
||||
|
||||
/// Return `true` if the given class, mixin, enum or extension [declaration]
|
||||
/// has open '{' and close '}' on the same line, e.g. `class X {}`.
|
||||
bool _isClassWithEmptyBody(CompilationUnitMember declaration) {
|
||||
return getLineThis(_getLeftBracket(declaration)!.offset) ==
|
||||
getLineThis(_getRightBracket(declaration)!.offset);
|
||||
}
|
||||
|
||||
/// Returns whether [range] contains only whitespace or comments.
|
||||
bool _isJustWhitespaceOrComment(SourceRange range) {
|
||||
var trimmedText = getRangeText(range).trim();
|
||||
// may be whitespace
|
||||
if (trimmedText.isEmpty) {
|
||||
return true;
|
||||
}
|
||||
// may be comment
|
||||
return TokenUtils.getTokens(trimmedText, unit.featureSet).isEmpty;
|
||||
}
|
||||
|
||||
/// Checks if [element] is visible in [targetExecutableElement] or
|
||||
/// [targetClassElement].
|
||||
bool _isTypeParameterVisible(TypeParameterElement element) {
|
||||
|
@ -1566,18 +1531,37 @@ class CorrectionUtils {
|
|||
return false;
|
||||
}
|
||||
// non-whitespace between selection start and range start
|
||||
if (!isJustWhitespaceOrComment(
|
||||
if (!_isJustWhitespaceOrComment(
|
||||
range.startOffsetEndOffset(selection.offset, sourceRange.offset))) {
|
||||
return true;
|
||||
}
|
||||
// non-whitespace after range
|
||||
if (!isJustWhitespaceOrComment(
|
||||
if (!_isJustWhitespaceOrComment(
|
||||
range.startOffsetEndOffset(sourceRange.end, selection.end))) {
|
||||
return true;
|
||||
}
|
||||
// only whitespace in selection around range
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Skip spaces, tabs and EOLs on the left from [index].
|
||||
///
|
||||
/// If [index] is the start of a method, then in the most cases return the end
|
||||
/// of the previous not-whitespace line.
|
||||
int _skipEmptyLinesLeft(int index) {
|
||||
var lastLine = index;
|
||||
while (index > 0) {
|
||||
var c = _buffer.codeUnitAt(index - 1);
|
||||
if (!isWhitespace(c)) {
|
||||
return lastLine;
|
||||
}
|
||||
if (isEOL(c)) {
|
||||
lastLine = index;
|
||||
}
|
||||
index--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes where to insert new text.
|
||||
|
|
|
@ -191,7 +191,7 @@ class ExtractLocalRefactoringImpl extends RefactoringImpl
|
|||
occurrencesShift = edit.replacement.length;
|
||||
} else if (target is ExpressionFunctionBody) {
|
||||
var prefix = utils.getNodePrefix(target.parent!);
|
||||
var indent = utils.getIndent(1);
|
||||
var indent = utils.oneIndent;
|
||||
var expr = target.expression;
|
||||
{
|
||||
var code = '{$eol$prefix$indent';
|
||||
|
|
|
@ -132,6 +132,23 @@ extension AstNodeExtension on AstNode {
|
|||
current = parent;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the [ExpressionStatement] associated with `this` if `this` points
|
||||
/// to the identifier for a simple `print`, and `null` otherwise.
|
||||
ExpressionStatement? findSimplePrintInvocation() {
|
||||
var parent = this.parent;
|
||||
var grandparent = parent?.parent;
|
||||
if (this case SimpleIdentifier(:var staticElement)) {
|
||||
if (staticElement is FunctionElement &&
|
||||
staticElement.name == 'print' &&
|
||||
staticElement.library.isDartCore &&
|
||||
parent is MethodInvocation &&
|
||||
grandparent is ExpressionStatement) {
|
||||
return grandparent;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
extension BinaryExpressionExtension on BinaryExpression {
|
||||
|
|
|
@ -61,7 +61,7 @@ abstract final class Flutter {
|
|||
String eol,
|
||||
String Function(Expression) getNodeText,
|
||||
String Function(int) getLinePrefix,
|
||||
String Function(int) getIndent,
|
||||
String oneIndent,
|
||||
String Function(int, int) getText,
|
||||
String Function(String, String, String,
|
||||
{bool includeLeading, bool ensureTrailingNewline})
|
||||
|
@ -80,7 +80,7 @@ abstract final class Flutter {
|
|||
newlineLoc -= 1;
|
||||
}
|
||||
var indentOld = getLinePrefix(childArg.offset + eol.length + newlineLoc);
|
||||
var indentNew = '$indentOld${getIndent(1)}';
|
||||
var indentNew = '$indentOld$oneIndent';
|
||||
// The separator includes 'child:' but that has no newlines.
|
||||
var separator =
|
||||
getText(namedExp.offset, childArg.offset - namedExp.offset);
|
||||
|
|
|
@ -146,14 +146,6 @@ String? removeEnd(String? str, String? remove) {
|
|||
return str;
|
||||
}
|
||||
|
||||
String repeat(String s, int n) {
|
||||
var sb = StringBuffer();
|
||||
for (var i = 0; i < n; i++) {
|
||||
sb.write(s);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/// If the [text] length is above the [limit], replace the middle with `...`.
|
||||
String shorten(String text, int limit) {
|
||||
if (text.length > limit) {
|
||||
|
|
|
@ -441,46 +441,6 @@ import 'package:ddd/ddd.dart';
|
|||
''');
|
||||
}
|
||||
|
||||
Future<void> test_findSimplePrintInvocation() async {
|
||||
await resolveTestCode('''
|
||||
void f() {
|
||||
print('hi');
|
||||
}
|
||||
''');
|
||||
var printIdentifier = findNode.simple('print');
|
||||
var expected = findNode.expressionStatement('print');
|
||||
var result = CorrectionUtils(testAnalysisResult)
|
||||
.findSimplePrintInvocation(printIdentifier);
|
||||
expect(result, expected);
|
||||
}
|
||||
|
||||
Future<void> test_findSimplePrintInvocation_custom_print() async {
|
||||
await resolveTestCode('''
|
||||
void print(String toPrint) {
|
||||
}
|
||||
|
||||
void f() {
|
||||
print('hi');
|
||||
}
|
||||
''');
|
||||
var printIdentifier = findNode.simple('print(\'hi\'');
|
||||
var result = CorrectionUtils(testAnalysisResult)
|
||||
.findSimplePrintInvocation(printIdentifier);
|
||||
expect(result, null);
|
||||
}
|
||||
|
||||
Future<void> test_findSimplePrintInvocation_negative() async {
|
||||
await resolveTestCode('''
|
||||
void f() {
|
||||
true ? print('hi') : print('false');
|
||||
}
|
||||
''');
|
||||
var printIdentifier = findNode.simple('print(\'false');
|
||||
var result = CorrectionUtils(testAnalysisResult)
|
||||
.findSimplePrintInvocation(printIdentifier);
|
||||
expect(result, null);
|
||||
}
|
||||
|
||||
Future<void> test_invertCondition_binary_compare() async {
|
||||
await assert_invertCondition('0 < 1', '0 >= 1');
|
||||
await assert_invertCondition('0 > 1', '0 <= 1');
|
||||
|
|
|
@ -11,6 +11,7 @@ import '../../../services/search/search_engine_test.dart';
|
|||
void main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(CompilationUnitFileHeaderTest);
|
||||
defineReflectiveTests(FindSimplePrintInvocationTest);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -179,3 +180,43 @@ class C {}
|
|||
orderedEquals(expected));
|
||||
}
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class FindSimplePrintInvocationTest extends PubPackageResolutionTest {
|
||||
Future<void> test_customPrint() async {
|
||||
await resolveTestCode('''
|
||||
void print(String toPrint) {
|
||||
}
|
||||
|
||||
void f() {
|
||||
print('hi');
|
||||
}
|
||||
''');
|
||||
var printIdentifier = findNode.simple('print(\'hi\'');
|
||||
var result = printIdentifier.findSimplePrintInvocation();
|
||||
expect(result, null);
|
||||
}
|
||||
|
||||
Future<void> test_negative() async {
|
||||
await resolveTestCode('''
|
||||
void f() {
|
||||
true ? print('hi') : print('false');
|
||||
}
|
||||
''');
|
||||
var printIdentifier = findNode.simple('print(\'false');
|
||||
var result = printIdentifier.findSimplePrintInvocation();
|
||||
expect(result, null);
|
||||
}
|
||||
|
||||
Future<void> test_simplePrintInvocation() async {
|
||||
await resolveTestCode('''
|
||||
void f() {
|
||||
print('hi');
|
||||
}
|
||||
''');
|
||||
var printIdentifier = findNode.simple('print');
|
||||
var expected = findNode.expressionStatement('print');
|
||||
var result = printIdentifier.findSimplePrintInvocation();
|
||||
expect(result, expected);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -141,12 +141,6 @@ class StringsTest {
|
|||
expect(removeEnd('www.domain.com', '.com'), 'www.domain');
|
||||
}
|
||||
|
||||
void test_repeat() {
|
||||
expect(repeat('x', 0), '');
|
||||
expect(repeat('x', 5), 'xxxxx');
|
||||
expect(repeat('abc', 3), 'abcabcabc');
|
||||
}
|
||||
|
||||
void test_shorten() {
|
||||
expect(shorten('', 10), '');
|
||||
expect(shorten('0', 10), '0');
|
||||
|
|
Loading…
Reference in a new issue