| Index: pkg/analysis_services/lib/src/correction/util.dart
|
| diff --git a/pkg/analysis_services/lib/src/correction/util.dart b/pkg/analysis_services/lib/src/correction/util.dart
|
| deleted file mode 100644
|
| index bc16dc01858da4afea4344a0e8ea0c4aa2ad3330..0000000000000000000000000000000000000000
|
| --- a/pkg/analysis_services/lib/src/correction/util.dart
|
| +++ /dev/null
|
| @@ -1,923 +0,0 @@
|
| -// Copyright (c) 2014, 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.
|
| -
|
| -library services.src.correction.util;
|
| -
|
| -import 'package:analysis_services/correction/change.dart';
|
| -import 'package:analysis_services/src/correction/source_range.dart';
|
| -import 'package:analysis_services/src/correction/strings.dart';
|
| -import 'package:analyzer/src/generated/ast.dart';
|
| -import 'package:analyzer/src/generated/element.dart';
|
| -import 'package:analyzer/src/generated/engine.dart';
|
| -import 'package:analyzer/src/generated/resolver.dart';
|
| -import 'package:analyzer/src/generated/scanner.dart';
|
| -import 'package:analyzer/src/generated/source.dart';
|
| -
|
| -
|
| -/**
|
| - * TODO(scheglov) replace with nodes once there will be [CompilationUnit#getComments].
|
| - *
|
| - * Returns [SourceRange]s of all comments in [unit].
|
| - */
|
| -List<SourceRange> getCommentRanges(CompilationUnit unit) {
|
| - List<SourceRange> ranges = <SourceRange>[];
|
| - Token token = unit.beginToken;
|
| - while (token != null && token.type != TokenType.EOF) {
|
| - Token commentToken = token.precedingComments;
|
| - while (commentToken != null) {
|
| - ranges.add(rangeToken(commentToken));
|
| - commentToken = commentToken.next;
|
| - }
|
| - token = token.next;
|
| - }
|
| - return ranges;
|
| -}
|
| -
|
| -
|
| -String getDefaultValueCode(DartType type) {
|
| - if (type != null) {
|
| - String typeName = type.displayName;
|
| - if (typeName == "bool") {
|
| - return "false";
|
| - }
|
| - if (typeName == "int") {
|
| - return "0";
|
| - }
|
| - if (typeName == "double") {
|
| - return "0.0";
|
| - }
|
| - if (typeName == "String") {
|
| - return "''";
|
| - }
|
| - }
|
| - // no better guess
|
| - return "null";
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Return the name of the [Element] kind.
|
| - */
|
| -String getElementKindName(Element element) {
|
| - return element.kind.displayName;
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Returns the name to display in the UI for the given [Element].
|
| - */
|
| -String getElementQualifiedName(Element element) {
|
| - ElementKind kind = element.kind;
|
| - if (kind == ElementKind.FIELD || kind == ElementKind.METHOD) {
|
| - return '${element.enclosingElement.displayName}.${element.displayName}';
|
| - } else {
|
| - return element.displayName;
|
| - }
|
| -}
|
| -
|
| -
|
| -/**
|
| - * @return the [ExecutableElement] of the enclosing executable [AstNode].
|
| - */
|
| -ExecutableElement getEnclosingExecutableElement(AstNode node) {
|
| - while (node != null) {
|
| - if (node is FunctionDeclaration) {
|
| - return node.element;
|
| - }
|
| - if (node is ConstructorDeclaration) {
|
| - return node.element;
|
| - }
|
| - if (node is MethodDeclaration) {
|
| - return node.element;
|
| - }
|
| - node = node.parent;
|
| - }
|
| - return null;
|
| -}
|
| -
|
| -/**
|
| - * Returns a namespace of the given [ExportElement].
|
| - */
|
| -Map<String, Element> getExportNamespaceForDirective(ExportElement exp) {
|
| - Namespace namespace =
|
| - new NamespaceBuilder().createExportNamespaceForDirective(exp);
|
| - return namespace.definedNames;
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Returns a export namespace of the given [LibraryElement].
|
| - */
|
| -Map<String, Element> getExportNamespaceForLibrary(LibraryElement library) {
|
| - Namespace namespace =
|
| - new NamespaceBuilder().createExportNamespaceForLibrary(library);
|
| - return namespace.definedNames;
|
| -}
|
| -
|
| -/**
|
| - * Returns an [Element] exported from the given [LibraryElement].
|
| - */
|
| -Element getExportedElement(LibraryElement library, String name) {
|
| - if (library == null) {
|
| - return null;
|
| - }
|
| - return getExportNamespaceForLibrary(library)[name];
|
| -}
|
| -
|
| -/**
|
| - * Returns [getExpressionPrecedence] for the parent of [node],
|
| - * or `0` if the parent node is [ParenthesizedExpression].
|
| - *
|
| - * The reason is that `(expr)` is always executed after `expr`.
|
| - */
|
| -int getExpressionParentPrecedence(AstNode node) {
|
| - AstNode parent = node.parent;
|
| - if (parent is ParenthesizedExpression) {
|
| - return 0;
|
| - }
|
| - return getExpressionPrecedence(parent);
|
| -}
|
| -
|
| -/**
|
| - * Returns the precedence of [node] it is an [Expression], negative otherwise.
|
| - */
|
| -int getExpressionPrecedence(AstNode node) {
|
| - if (node is Expression) {
|
| - return node.precedence;
|
| - }
|
| - return -1000;
|
| -}
|
| -
|
| -/**
|
| - * Returns the namespace of the given [ImportElement].
|
| - */
|
| -Map<String, Element> getImportNamespace(ImportElement imp) {
|
| - NamespaceBuilder builder = new NamespaceBuilder();
|
| - Namespace namespace = builder.createImportNamespaceForDirective(imp);
|
| - return namespace.definedNames;
|
| -}
|
| -
|
| -
|
| -/**
|
| - * If given [AstNode] is name of qualified property extraction, returns target from which
|
| - * this property is extracted. Otherwise `null`.
|
| - */
|
| -Expression getQualifiedPropertyTarget(AstNode node) {
|
| - AstNode parent = node.parent;
|
| - if (parent is PrefixedIdentifier) {
|
| - PrefixedIdentifier prefixed = parent;
|
| - if (prefixed.identifier == node) {
|
| - return parent.prefix;
|
| - }
|
| - }
|
| - if (parent is PropertyAccess) {
|
| - PropertyAccess access = parent;
|
| - if (access.propertyName == node) {
|
| - return access.realTarget;
|
| - }
|
| - }
|
| - return null;
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Returns the given [Statement] if not a [Block], or the first child
|
| - * [Statement] if a [Block], or `null` if more than one child.
|
| - */
|
| -Statement getSingleStatement(Statement statement) {
|
| - if (statement is Block) {
|
| - List<Statement> blockStatements = statement.statements;
|
| - if (blockStatements.length != 1) {
|
| - return null;
|
| - }
|
| - return blockStatements[0];
|
| - }
|
| - return statement;
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Returns the [String] content of the given [Source].
|
| - */
|
| -String getSourceContent(AnalysisContext context, Source source) {
|
| - return context.getContents(source).data;
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Returns the given [Statement] if not a [Block], or all the children
|
| - * [Statement]s if a [Block].
|
| - */
|
| -List<Statement> getStatements(Statement statement) {
|
| - if (statement is Block) {
|
| - return statement.statements;
|
| - }
|
| - return [statement];
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Checks if the given [Element]'s display name equals to the given name.
|
| - */
|
| -bool hasDisplayName(Element element, String name) {
|
| - if (element == null) {
|
| - return false;
|
| - }
|
| - return element.displayName == name;
|
| -}
|
| -
|
| -
|
| -class CorrectionUtils {
|
| - final CompilationUnit unit;
|
| -
|
| - LibraryElement _library;
|
| - String _buffer;
|
| - String _endOfLine;
|
| -
|
| - CorrectionUtils(this.unit) {
|
| - CompilationUnitElement unitElement = unit.element;
|
| - this._library = unitElement.library;
|
| - this._buffer = unitElement.context.getContents(unitElement.source).data;
|
| - }
|
| -
|
| - /**
|
| - * Returns the EOL to use for this [CompilationUnit].
|
| - */
|
| - String get endOfLine {
|
| - if (_endOfLine == null) {
|
| - if (_buffer.contains("\r\n")) {
|
| - _endOfLine = "\r\n";
|
| - } else {
|
| - _endOfLine = "\n";
|
| - }
|
| - }
|
| - return _endOfLine;
|
| - }
|
| -
|
| - /**
|
| - * Returns an [Edit] that changes indentation of the source of the given
|
| - * [SourceRange] from [oldIndent] to [newIndent], keeping indentation of lines
|
| - * relative to each other.
|
| - */
|
| - Edit createIndentEdit(SourceRange range, String oldIndent, String newIndent) {
|
| - String newSource = replaceSourceRangeIndent(range, oldIndent, newIndent);
|
| - return new Edit(range.offset, range.length, newSource);
|
| - }
|
| -
|
| - /**
|
| - * Returns the actual type source of the given [Expression], may be `null`
|
| - * if can not be resolved, should be treated as the `dynamic` type.
|
| - */
|
| - String getExpressionTypeSource(Expression expression) {
|
| - if (expression == null) {
|
| - return null;
|
| - }
|
| - DartType type = expression.bestType;
|
| - if (type.isDynamic) {
|
| - return null;
|
| - }
|
| - return getTypeSource(type);
|
| - }
|
| -
|
| - /**
|
| - * Returns the indentation with the given level.
|
| - */
|
| - String getIndent(int level) => repeat(' ', level);
|
| -
|
| - /**
|
| - * Returns a [InsertDesc] describing where to insert a new library-related
|
| - * directive.
|
| - */
|
| - CorrectionUtils_InsertDesc getInsertDescImport() {
|
| - // analyze directives
|
| - Directive prevDirective = null;
|
| - for (Directive directive in unit.directives) {
|
| - if (directive is LibraryDirective ||
|
| - directive is ImportDirective ||
|
| - directive is ExportDirective) {
|
| - prevDirective = directive;
|
| - }
|
| - }
|
| - // insert after last library-related directive
|
| - if (prevDirective != null) {
|
| - CorrectionUtils_InsertDesc result = new CorrectionUtils_InsertDesc();
|
| - result.offset = prevDirective.end;
|
| - String eol = endOfLine;
|
| - if (prevDirective is LibraryDirective) {
|
| - result.prefix = "${eol}${eol}";
|
| - } else {
|
| - result.prefix = eol;
|
| - }
|
| - return result;
|
| - }
|
| - // no directives, use "top" location
|
| - return getInsertDescTop();
|
| - }
|
| -
|
| - /**
|
| - * Returns a [InsertDesc] describing where to insert a new 'part' directive.
|
| - */
|
| - CorrectionUtils_InsertDesc getInsertDescPart() {
|
| - // analyze directives
|
| - Directive prevDirective = null;
|
| - for (Directive directive in unit.directives) {
|
| - prevDirective = directive;
|
| - }
|
| - // insert after last directive
|
| - if (prevDirective != null) {
|
| - CorrectionUtils_InsertDesc result = new CorrectionUtils_InsertDesc();
|
| - result.offset = prevDirective.end;
|
| - String eol = endOfLine;
|
| - if (prevDirective is PartDirective) {
|
| - result.prefix = eol;
|
| - } else {
|
| - result.prefix = "${eol}${eol}";
|
| - }
|
| - return result;
|
| - }
|
| - // no directives, use "top" location
|
| - return getInsertDescTop();
|
| - }
|
| -
|
| - /**
|
| - * Returns a [InsertDesc] describing where to insert a new directive or a
|
| - * top-level declaration at the top of the file.
|
| - */
|
| - CorrectionUtils_InsertDesc getInsertDescTop() {
|
| - // skip leading line comments
|
| - int offset = 0;
|
| - bool insertEmptyLineBefore = false;
|
| - bool insertEmptyLineAfter = false;
|
| - String source = _buffer;
|
| - // skip hash-bang
|
| - if (offset < source.length - 2) {
|
| - String linePrefix = getText(offset, 2);
|
| - if (linePrefix == "#!") {
|
| - insertEmptyLineBefore = true;
|
| - offset = getLineNext(offset);
|
| - // skip empty lines to first line comment
|
| - int emptyOffset = offset;
|
| - while (emptyOffset < source.length - 2) {
|
| - int nextLineOffset = getLineNext(emptyOffset);
|
| - String 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) {
|
| - String linePrefix = getText(offset, 2);
|
| - if (linePrefix == "//") {
|
| - insertEmptyLineBefore = true;
|
| - offset = getLineNext(offset);
|
| - } else {
|
| - break;
|
| - }
|
| - }
|
| - // determine if empty line is required after
|
| - int nextLineOffset = getLineNext(offset);
|
| - String insertLine = source.substring(offset, nextLineOffset);
|
| - if (!insertLine.trim().isEmpty) {
|
| - insertEmptyLineAfter = true;
|
| - }
|
| - // fill InsertDesc
|
| - CorrectionUtils_InsertDesc desc = new CorrectionUtils_InsertDesc();
|
| - desc.offset = offset;
|
| - if (insertEmptyLineBefore) {
|
| - desc.prefix = endOfLine;
|
| - }
|
| - if (insertEmptyLineAfter) {
|
| - desc.suffix = endOfLine;
|
| - }
|
| - return desc;
|
| - }
|
| -
|
| - /**
|
| - * 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
|
| - * a start of the next line.
|
| - */
|
| - int getLineContentEnd(int index) {
|
| - int length = _buffer.length;
|
| - // skip whitespace characters
|
| - while (index < length) {
|
| - int c = _buffer.codeUnitAt(index);
|
| - if (!isWhitespace(c) || c == 0x0D || c == 0x0A) {
|
| - break;
|
| - }
|
| - index++;
|
| - }
|
| - // skip single \r
|
| - if (index < length && _buffer.codeUnitAt(index) == 0x0D) {
|
| - index++;
|
| - }
|
| - // skip single \n
|
| - if (index < length && _buffer.codeUnitAt(index) == 0x0A) {
|
| - index++;
|
| - }
|
| - // done
|
| - return index;
|
| - }
|
| -
|
| - /**
|
| - * Skips spaces and tabs on the left from [index].
|
| - *
|
| - * If [index] is the start or a statement, then in the most cases it is a
|
| - * start on its line.
|
| - */
|
| - int getLineContentStart(int index) {
|
| - while (index > 0) {
|
| - int c = _buffer.codeUnitAt(index - 1);
|
| - if (!isSpace(c)) {
|
| - break;
|
| - }
|
| - index--;
|
| - }
|
| - return index;
|
| - }
|
| -
|
| - /**
|
| - * Returns a start index of the next line after the line which contains the
|
| - * given index.
|
| - */
|
| - int getLineNext(int index) {
|
| - int length = _buffer.length;
|
| - // skip to the end of the line
|
| - while (index < length) {
|
| - int c = _buffer.codeUnitAt(index);
|
| - if (c == 0xD || c == 0xA) {
|
| - break;
|
| - }
|
| - index++;
|
| - }
|
| - // skip single \r
|
| - if (index < length && _buffer.codeUnitAt(index) == 0xD) {
|
| - index++;
|
| - }
|
| - // skip single \n
|
| - if (index < length && _buffer.codeUnitAt(index) == 0xA) {
|
| - index++;
|
| - }
|
| - // done
|
| - return index;
|
| - }
|
| -
|
| - /**
|
| - * Returns the whitespace prefix of the line which contains given offset.
|
| - */
|
| - String getLinePrefix(int index) {
|
| - int lineStart = getLineThis(index);
|
| - int length = _buffer.length;
|
| - int lineNonWhitespace = lineStart;
|
| - while (lineNonWhitespace < length) {
|
| - int c = _buffer.codeUnitAt(lineNonWhitespace);
|
| - if (c == 0xD || c == 0xA) {
|
| - break;
|
| - }
|
| - if (!isWhitespace(c)) {
|
| - break;
|
| - }
|
| - lineNonWhitespace++;
|
| - }
|
| - return getText(lineStart, lineNonWhitespace - lineStart);
|
| - }
|
| -
|
| - /**
|
| - * Returns the start index of the line which contains given index.
|
| - */
|
| - int getLineThis(int index) {
|
| - while (index > 0) {
|
| - int c = _buffer.codeUnitAt(index - 1);
|
| - if (c == 0xD || c == 0xA) {
|
| - break;
|
| - }
|
| - index--;
|
| - }
|
| - return index;
|
| - }
|
| -
|
| - /**
|
| - * Returns a [SourceRange] that covers [range] and extends (if possible) to
|
| - * cover whole lines.
|
| - */
|
| - SourceRange getLinesRange(SourceRange range) {
|
| - // start
|
| - int startOffset = range.offset;
|
| - int startLineOffset = getLineContentStart(startOffset);
|
| - // end
|
| - int endOffset = range.end;
|
| - int afterEndLineOffset = getLineContentEnd(endOffset);
|
| - // range
|
| - return rangeStartEnd(startLineOffset, afterEndLineOffset);
|
| - }
|
| -
|
| - /**
|
| - * Returns a [SourceRange] that covers all the given [Statement]s.
|
| - */
|
| - SourceRange getLinesRangeStatements(List<Statement> statements) {
|
| - SourceRange range = rangeNodes(statements);
|
| - return getLinesRange(range);
|
| - }
|
| -
|
| - /**
|
| - * Returns the line prefix consisting of spaces and tabs on the left from the given
|
| - * [AstNode].
|
| - */
|
| - String getNodePrefix(AstNode node) {
|
| - int offset = node.offset;
|
| - // function literal is special, it uses offset of enclosing line
|
| - if (node is FunctionExpression) {
|
| - return getLinePrefix(offset);
|
| - }
|
| - // use just prefix directly before node
|
| - return getPrefix(offset);
|
| - }
|
| -
|
| - /**
|
| - * Returns the text of the given [AstNode] in the unit.
|
| - */
|
| - String getNodeText(AstNode node) {
|
| - return getText(node.offset, node.length);
|
| - }
|
| -
|
| - /**
|
| - * @return the source for the parameter with the given type and name.
|
| - */
|
| - String getParameterSource(DartType type, String name) {
|
| - // no type
|
| - if (type == null || type.isDynamic) {
|
| - return name;
|
| - }
|
| - // function type
|
| - if (type is FunctionType) {
|
| - FunctionType functionType = type;
|
| - StringBuffer sb = new StringBuffer();
|
| - // return type
|
| - DartType returnType = functionType.returnType;
|
| - if (returnType != null && !returnType.isDynamic) {
|
| - sb.write(getTypeSource(returnType));
|
| - sb.write(' ');
|
| - }
|
| - // parameter name
|
| - sb.write(name);
|
| - // parameters
|
| - sb.write('(');
|
| - List<ParameterElement> fParameters = functionType.parameters;
|
| - for (int i = 0; i < fParameters.length; i++) {
|
| - ParameterElement fParameter = fParameters[i];
|
| - if (i != 0) {
|
| - sb.write(", ");
|
| - }
|
| - sb.write(getParameterSource(fParameter.type, fParameter.name));
|
| - }
|
| - sb.write(')');
|
| - // done
|
| - return sb.toString();
|
| - }
|
| - // simple type
|
| - return "${getTypeSource(type)} ${name}";
|
| - }
|
| -
|
| - /**
|
| - * Returns the line prefix consisting of spaces and tabs on the left from the
|
| - * given offset.
|
| - */
|
| - String getPrefix(int endIndex) {
|
| - int startIndex = getLineContentStart(endIndex);
|
| - return _buffer.substring(startIndex, endIndex);
|
| - }
|
| -
|
| - /**
|
| - * Returns the text of the given range in the unit.
|
| - */
|
| - String getRangeText(SourceRange range) {
|
| - return getText(range.offset, range.length);
|
| - }
|
| -
|
| - /**
|
| - * Returns the text of the given range in the unit.
|
| - */
|
| - String getText(int offset, int length) {
|
| - return _buffer.substring(offset, offset + length);
|
| - }
|
| -
|
| - /**
|
| - * Returns the source to reference [type] in this [CompilationUnit].
|
| - */
|
| - String getTypeSource(DartType type) {
|
| - StringBuffer sb = new StringBuffer();
|
| - // just some Function, maybe find Function Type Alias later
|
| - if (type is FunctionType) {
|
| - return "Function";
|
| - }
|
| - // prepare element
|
| - Element element = type.element;
|
| - if (element == null) {
|
| - String source = type.toString();
|
| - source = source.replaceAll('<dynamic>', '');
|
| - source = source.replaceAll('<dynamic, dynamic>', '');
|
| - return source;
|
| - }
|
| - // append prefix
|
| - {
|
| - ImportElement imp = _getImportElement(element);
|
| - if (imp != null && imp.prefix != null) {
|
| - sb.write(imp.prefix.displayName);
|
| - sb.write(".");
|
| - }
|
| - }
|
| - // append simple name
|
| - String name = element.displayName;
|
| - sb.write(name);
|
| - // may be type arguments
|
| - if (type is InterfaceType) {
|
| - InterfaceType interfaceType = type;
|
| - List<DartType> arguments = interfaceType.typeArguments;
|
| - // check if has arguments
|
| - bool hasArguments = false;
|
| - for (DartType argument in arguments) {
|
| - if (!argument.isDynamic) {
|
| - hasArguments = true;
|
| - break;
|
| - }
|
| - }
|
| - // append type arguments
|
| - if (hasArguments) {
|
| - sb.write("<");
|
| - for (int i = 0; i < arguments.length; i++) {
|
| - DartType argument = arguments[i];
|
| - if (i != 0) {
|
| - sb.write(", ");
|
| - }
|
| - sb.write(getTypeSource(argument));
|
| - }
|
| - sb.write(">");
|
| - }
|
| - }
|
| - // done
|
| - return sb.toString();
|
| - }
|
| -
|
| - /**
|
| - * Indents given source left or right.
|
| - */
|
| - String indentSourceLeftRight(String source, bool right) {
|
| - StringBuffer sb = new StringBuffer();
|
| - String indent = getIndent(1);
|
| - String eol = endOfLine;
|
| - List<String> lines = source.split(eol);
|
| - for (int i = 0; i < lines.length; i++) {
|
| - String line = lines[i];
|
| - // last line, stop if empty
|
| - if (i == lines.length - 1 && isEmpty(line)) {
|
| - break;
|
| - }
|
| - // update line
|
| - if (right) {
|
| - line = "${indent}${line}";
|
| - } else {
|
| - line = removeStart(line, indent);
|
| - }
|
| - // append line
|
| - sb.write(line);
|
| - sb.write(eol);
|
| - }
|
| - return sb.toString();
|
| - }
|
| -
|
| - /**
|
| - * @return the source of the inverted condition for the given logical expression.
|
| - */
|
| - String invertCondition(Expression expression) =>
|
| - _invertCondition0(expression)._source;
|
| -
|
| - /**
|
| - * Returns the source with indentation changed from [oldIndent] to
|
| - * [newIndent], keeping indentation of lines relative to each other.
|
| - */
|
| - String replaceSourceIndent(String source, String oldIndent,
|
| - String newIndent) {
|
| - // prepare STRING token ranges
|
| - List<SourceRange> lineRanges = [];
|
| - {
|
| - var token = unit.beginToken;
|
| - while (token != null && token.type != TokenType.EOF) {
|
| - if (token.type == TokenType.STRING) {
|
| - lineRanges.add(rangeToken(token));
|
| - }
|
| - token = token.next;
|
| - }
|
| - }
|
| - // re-indent lines
|
| - StringBuffer sb = new StringBuffer();
|
| - String eol = endOfLine;
|
| - List<String> lines = source.split(eol);
|
| - int lineOffset = 0;
|
| - for (int i = 0; i < lines.length; i++) {
|
| - String line = lines[i];
|
| - // last line, stop if empty
|
| - if (i == lines.length - 1 && isEmpty(line)) {
|
| - break;
|
| - }
|
| - // check if "offset" is in one of the String ranges
|
| - bool inString = false;
|
| - for (SourceRange lineRange in lineRanges) {
|
| - if (lineOffset > lineRange.offset && lineOffset < lineRange.end) {
|
| - inString = true;
|
| - }
|
| - if (lineOffset > lineRange.end) {
|
| - break;
|
| - }
|
| - }
|
| - lineOffset += line.length + eol.length;
|
| - // update line indent
|
| - if (!inString) {
|
| - line = "${newIndent}${removeStart(line, oldIndent)}";
|
| - }
|
| - // append line
|
| - sb.write(line);
|
| - sb.write(eol);
|
| - }
|
| - return sb.toString();
|
| - }
|
| -
|
| - /**
|
| - * Returns the source of the given [SourceRange] with indentation changed
|
| - * from [oldIndent] to [newIndent], keeping indentation of lines relative
|
| - * to each other.
|
| - */
|
| - String replaceSourceRangeIndent(SourceRange range, String oldIndent,
|
| - String newIndent) {
|
| - String oldSource = getRangeText(range);
|
| - return replaceSourceIndent(oldSource, oldIndent, newIndent);
|
| - }
|
| -
|
| - /**
|
| - * @return the [ImportElement] used to import given [Element] into [library].
|
| - * May be `null` if was not imported, i.e. declared in the same library.
|
| - */
|
| - ImportElement _getImportElement(Element element) {
|
| - for (ImportElement imp in _library.imports) {
|
| - Map<String, Element> definedNames = getImportNamespace(imp);
|
| - if (definedNames.containsValue(element)) {
|
| - return imp;
|
| - }
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - /**
|
| - * @return the [InvertedCondition] for the given logical expression.
|
| - */
|
| - _InvertedCondition _invertCondition0(Expression expression) {
|
| - if (expression is BooleanLiteral) {
|
| - BooleanLiteral literal = expression;
|
| - if (literal.value) {
|
| - return _InvertedCondition._simple("false");
|
| - } else {
|
| - return _InvertedCondition._simple("true");
|
| - }
|
| - }
|
| - if (expression is BinaryExpression) {
|
| - BinaryExpression binary = expression;
|
| - TokenType operator = binary.operator.type;
|
| - Expression le = binary.leftOperand;
|
| - Expression re = binary.rightOperand;
|
| - _InvertedCondition ls = _invertCondition0(le);
|
| - _InvertedCondition rs = _invertCondition0(re);
|
| - if (operator == TokenType.LT) {
|
| - return _InvertedCondition._binary2(ls, " >= ", rs);
|
| - }
|
| - if (operator == TokenType.GT) {
|
| - return _InvertedCondition._binary2(ls, " <= ", rs);
|
| - }
|
| - if (operator == TokenType.LT_EQ) {
|
| - return _InvertedCondition._binary2(ls, " > ", rs);
|
| - }
|
| - if (operator == TokenType.GT_EQ) {
|
| - return _InvertedCondition._binary2(ls, " < ", rs);
|
| - }
|
| - if (operator == TokenType.EQ_EQ) {
|
| - return _InvertedCondition._binary2(ls, " != ", rs);
|
| - }
|
| - if (operator == TokenType.BANG_EQ) {
|
| - return _InvertedCondition._binary2(ls, " == ", rs);
|
| - }
|
| - if (operator == TokenType.AMPERSAND_AMPERSAND) {
|
| - return _InvertedCondition._binary(
|
| - TokenType.BAR_BAR.precedence,
|
| - ls,
|
| - " || ",
|
| - rs);
|
| - }
|
| - if (operator == TokenType.BAR_BAR) {
|
| - return _InvertedCondition._binary(
|
| - TokenType.AMPERSAND_AMPERSAND.precedence,
|
| - ls,
|
| - " && ",
|
| - rs);
|
| - }
|
| - }
|
| - if (expression is IsExpression) {
|
| - IsExpression isExpression = expression;
|
| - String expressionSource = getNodeText(isExpression.expression);
|
| - String typeSource = getNodeText(isExpression.type);
|
| - if (isExpression.notOperator == null) {
|
| - return _InvertedCondition._simple(
|
| - "${expressionSource} is! ${typeSource}");
|
| - } else {
|
| - return _InvertedCondition._simple(
|
| - "${expressionSource} is ${typeSource}");
|
| - }
|
| - }
|
| - if (expression is PrefixExpression) {
|
| - PrefixExpression prefixExpression = expression;
|
| - TokenType operator = prefixExpression.operator.type;
|
| - if (operator == TokenType.BANG) {
|
| - Expression operand = prefixExpression.operand;
|
| - while (operand is ParenthesizedExpression) {
|
| - ParenthesizedExpression pe = operand as ParenthesizedExpression;
|
| - operand = pe.expression;
|
| - }
|
| - return _InvertedCondition._simple(getNodeText(operand));
|
| - }
|
| - }
|
| - if (expression is ParenthesizedExpression) {
|
| - ParenthesizedExpression pe = expression;
|
| - Expression innerExpresion = pe.expression;
|
| - while (innerExpresion is ParenthesizedExpression) {
|
| - innerExpresion = (innerExpresion as ParenthesizedExpression).expression;
|
| - }
|
| - return _invertCondition0(innerExpresion);
|
| - }
|
| - DartType type = expression.bestType;
|
| - if (type.displayName == "bool") {
|
| - return _InvertedCondition._simple("!${getNodeText(expression)}");
|
| - }
|
| - return _InvertedCondition._simple(getNodeText(expression));
|
| - }
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Describes where to insert new directive or top-level declaration.
|
| - */
|
| -class CorrectionUtils_InsertDesc {
|
| - int offset = 0;
|
| - String prefix = "";
|
| - String suffix = "";
|
| -}
|
| -
|
| -
|
| -/**
|
| - * A container with a source and its precedence.
|
| - */
|
| -class _InvertedCondition {
|
| - final int _precedence;
|
| -
|
| - final String _source;
|
| -
|
| - _InvertedCondition(this._precedence, this._source);
|
| -
|
| - static _InvertedCondition _binary(int precedence, _InvertedCondition left,
|
| - String operation, _InvertedCondition right) {
|
| - String src =
|
| - _parenthesizeIfRequired(left, precedence) +
|
| - operation +
|
| - _parenthesizeIfRequired(right, precedence);
|
| - return new _InvertedCondition(precedence, src);
|
| - }
|
| -
|
| - static _InvertedCondition _binary2(_InvertedCondition left, String operation,
|
| - _InvertedCondition right) {
|
| - // TODO(scheglov) conside merging with "_binary()" after testing
|
| - return new _InvertedCondition(
|
| - 1 << 20,
|
| - "${left._source}${operation}${right._source}");
|
| - }
|
| -
|
| - /**
|
| - * Adds enclosing parenthesis if the precedence of the [_InvertedCondition] if less than the
|
| - * precedence of the expression we are going it to use in.
|
| - */
|
| - static String _parenthesizeIfRequired(_InvertedCondition expr,
|
| - int newOperatorPrecedence) {
|
| - if (expr._precedence < newOperatorPrecedence) {
|
| - return "(${expr._source})";
|
| - }
|
| - return expr._source;
|
| - }
|
| -
|
| - static _InvertedCondition _simple(String source) =>
|
| - new _InvertedCondition(2147483647, source);
|
| -}
|
|
|