| Index: pkg/analysis_services/lib/src/correction/fix.dart
|
| diff --git a/pkg/analysis_services/lib/src/correction/fix.dart b/pkg/analysis_services/lib/src/correction/fix.dart
|
| deleted file mode 100644
|
| index dfaac9c7436e93129fe5227b905c5b63c92c3cf8..0000000000000000000000000000000000000000
|
| --- a/pkg/analysis_services/lib/src/correction/fix.dart
|
| +++ /dev/null
|
| @@ -1,1912 +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.fix;
|
| -
|
| -import 'dart:collection';
|
| -
|
| -import 'package:analysis_services/correction/change.dart';
|
| -import 'package:analysis_services/correction/fix.dart';
|
| -import 'package:analysis_services/search/hierarchy.dart';
|
| -import 'package:analysis_services/search/search_engine.dart';
|
| -import 'package:analysis_services/src/correction/levenshtein.dart';
|
| -import 'package:analysis_services/src/correction/name_suggestion.dart';
|
| -import 'package:analysis_services/src/correction/source_buffer.dart';
|
| -import 'package:analysis_services/src/correction/source_range.dart' as rf;
|
| -import 'package:analysis_services/src/correction/strings.dart';
|
| -import 'package:analysis_services/src/correction/util.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/error.dart';
|
| -import 'package:analyzer/src/generated/java_core.dart';
|
| -import 'package:analyzer/src/generated/parser.dart';
|
| -import 'package:analyzer/src/generated/scanner.dart';
|
| -import 'package:analyzer/src/generated/sdk.dart';
|
| -import 'package:analyzer/src/generated/source.dart';
|
| -import 'package:analyzer/src/generated/utilities_dart.dart';
|
| -import 'package:path/path.dart';
|
| -
|
| -
|
| -/**
|
| - * A predicate is a one-argument function that returns a boolean value.
|
| - */
|
| -typedef bool Predicate<E>(E argument);
|
| -
|
| -
|
| -/**
|
| - * The computer for Dart fixes.
|
| - */
|
| -class FixProcessor {
|
| - static const int MAX_LEVENSHTEIN_DISTANCE = 3;
|
| -
|
| - final SearchEngine searchEngine;
|
| - final Source source;
|
| - final String file;
|
| - final CompilationUnit unit;
|
| - final AnalysisError error;
|
| - CompilationUnitElement unitElement;
|
| - Source unitSource;
|
| - LibraryElement unitLibraryElement;
|
| - String unitLibraryFile;
|
| - String unitLibraryFolder;
|
| -
|
| - final List<Edit> edits = <Edit>[];
|
| - final Map<String, LinkedEditGroup> linkedPositionGroups = <String,
|
| - LinkedEditGroup>{};
|
| - Position exitPosition = null;
|
| - final List<Fix> fixes = <Fix>[];
|
| -
|
| - CorrectionUtils utils;
|
| - int errorOffset;
|
| - int errorLength;
|
| - int errorEnd;
|
| - AstNode node;
|
| - AstNode coveredNode;
|
| -
|
| - FixProcessor(this.searchEngine, this.source, this.file, this.unit, this.error)
|
| - {
|
| - unitElement = unit.element;
|
| - unitSource = unitElement.source;
|
| - unitLibraryElement = unitElement.library;
|
| - unitLibraryFile = unitLibraryElement.source.fullName;
|
| - unitLibraryFolder = dirname(unitLibraryFile);
|
| - }
|
| -
|
| - DartType get coreTypeBool => _getCoreType("bool");
|
| -
|
| - /**
|
| - * Returns the EOL to use for this [CompilationUnit].
|
| - */
|
| - String get eol => utils.endOfLine;
|
| -
|
| - List<Fix> compute() {
|
| - utils = new CorrectionUtils(unit);
|
| - errorOffset = error.offset;
|
| - errorLength = error.length;
|
| - errorEnd = errorOffset + errorLength;
|
| - node = new NodeLocator.con1(errorOffset).searchWithin(unit);
|
| - coveredNode = new NodeLocator.con2(
|
| - errorOffset,
|
| - errorOffset + errorLength).searchWithin(unit);
|
| - // analyze ErrorCode
|
| - ErrorCode errorCode = error.errorCode;
|
| - if (errorCode == StaticWarningCode.UNDEFINED_CLASS_BOOLEAN) {
|
| - _addFix_boolInsteadOfBoolean();
|
| - }
|
| - if (errorCode ==
|
| - CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE) {
|
| - _addFix_replaceWithConstInstanceCreation();
|
| - }
|
| - if (errorCode ==
|
| - CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT) {
|
| - _addFix_createConstructorSuperExplicit();
|
| - }
|
| - if (errorCode ==
|
| - CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT) {
|
| - _addFix_createConstructorSuperImplicit();
|
| - }
|
| - if (errorCode ==
|
| - CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT) {
|
| - _addFix_createConstructorSuperExplicit();
|
| - }
|
| - if (errorCode == HintCode.DIVISION_OPTIMIZATION) {
|
| - _addFix_useEffectiveIntegerDivision();
|
| - }
|
| - if (errorCode == HintCode.TYPE_CHECK_IS_NOT_NULL) {
|
| - _addFix_isNotNull();
|
| - }
|
| - if (errorCode == HintCode.TYPE_CHECK_IS_NULL) {
|
| - _addFix_isNull();
|
| - }
|
| - if (errorCode == HintCode.UNNECESSARY_CAST) {
|
| - _addFix_removeUnnecessaryCast();
|
| - }
|
| - if (errorCode == HintCode.UNUSED_IMPORT) {
|
| - _addFix_removeUnusedImport();
|
| - }
|
| - if (errorCode == ParserErrorCode.EXPECTED_TOKEN) {
|
| - _addFix_insertSemicolon();
|
| - }
|
| - if (errorCode == ParserErrorCode.GETTER_WITH_PARAMETERS) {
|
| - _addFix_removeParameters_inGetterDeclaration();
|
| - }
|
| - if (errorCode == StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER) {
|
| - _addFix_makeEnclosingClassAbstract();
|
| - }
|
| - if (errorCode == StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS) {
|
| - _addFix_createConstructor_insteadOfSyntheticDefault();
|
| - }
|
| - if (errorCode == StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCTOR) {
|
| - _addFix_createConstructor_named();
|
| - }
|
| - if (errorCode ==
|
| - StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE ||
|
| - errorCode ==
|
| - StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO ||
|
| - errorCode ==
|
| - StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE ||
|
| - errorCode ==
|
| - StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR ||
|
| - errorCode ==
|
| - StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS) {
|
| - // make class abstract
|
| - _addFix_makeEnclosingClassAbstract();
|
| - // implement methods
|
| - AnalysisErrorWithProperties errorWithProperties =
|
| - error as AnalysisErrorWithProperties;
|
| - Object property =
|
| - errorWithProperties.getProperty(ErrorProperty.UNIMPLEMENTED_METHODS);
|
| - List<ExecutableElement> missingOverrides =
|
| - property as List<ExecutableElement>;
|
| - _addFix_createMissingOverrides(missingOverrides);
|
| - _addFix_createNoSuchMethod();
|
| - }
|
| - if (errorCode == StaticWarningCode.UNDEFINED_CLASS) {
|
| - _addFix_importLibrary_withType();
|
| - _addFix_createClass();
|
| - _addFix_undefinedClass_useSimilar();
|
| - }
|
| - if (errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER) {
|
| - _addFix_createFunction_forFunctionType();
|
| - _addFix_importLibrary_withType();
|
| - _addFix_importLibrary_withTopLevelVariable();
|
| - }
|
| - if (errorCode == StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER) {
|
| - _addFix_useStaticAccess_method();
|
| - _addFix_useStaticAccess_property();
|
| - }
|
| - if (errorCode == StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION) {
|
| - _addFix_removeParentheses_inGetterInvocation();
|
| - }
|
| - if (errorCode == StaticTypeWarningCode.UNDEFINED_FUNCTION) {
|
| - _addFix_importLibrary_withFunction();
|
| - _addFix_undefinedFunction_useSimilar();
|
| - _addFix_undefinedFunction_create();
|
| - }
|
| - if (errorCode == StaticTypeWarningCode.UNDEFINED_GETTER) {
|
| - _addFix_createFunction_forFunctionType();
|
| - }
|
| - if (errorCode == HintCode.UNDEFINED_METHOD ||
|
| - errorCode == StaticTypeWarningCode.UNDEFINED_METHOD) {
|
| - _addFix_undefinedMethod_useSimilar();
|
| - _addFix_undefinedMethod_create();
|
| - _addFix_undefinedFunction_create();
|
| - }
|
| - // done
|
| - return fixes;
|
| - }
|
| -
|
| - void _addFix(FixKind kind, List args, {String fixFile}) {
|
| - if (fixFile == null) {
|
| - fixFile = file;
|
| - }
|
| - FileEdit fileEdit = new FileEdit(file);
|
| - fileEdit.addAll(edits);
|
| - // prepare Change
|
| - String message = formatList(kind.message, args);
|
| - Change change = new Change(message);
|
| - change.addFileEdit(fileEdit);
|
| - linkedPositionGroups.values.forEach(
|
| - (group) => change.addLinkedEditGroup(group));
|
| - change.selection = exitPosition;
|
| - // add Fix
|
| - Fix fix = new Fix(kind, change);
|
| - fixes.add(fix);
|
| - // clear
|
| - edits.clear();
|
| - linkedPositionGroups.clear();
|
| - exitPosition = null;
|
| - }
|
| -
|
| - void _addFix_boolInsteadOfBoolean() {
|
| - SourceRange range = rf.rangeError(error);
|
| - _addReplaceEdit(range, "bool");
|
| - _addFix(FixKind.REPLACE_BOOLEAN_WITH_BOOL, []);
|
| - }
|
| -
|
| - void _addFix_createClass() {
|
| - if (_mayBeTypeIdentifier(node)) {
|
| - String name = (node as SimpleIdentifier).name;
|
| - // prepare environment
|
| - CompilationUnitMember enclosingMember =
|
| - node.getAncestor((node) => node is CompilationUnitMember);
|
| - int offset = enclosingMember.end;
|
| - String prefix = "";
|
| - // prepare source
|
| - SourceBuilder sb = new SourceBuilder(file, offset);
|
| - {
|
| - sb.append("${eol}${eol}");
|
| - sb.append(prefix);
|
| - // "class"
|
| - sb.append("class ");
|
| - // append name
|
| - {
|
| - sb.startPosition("NAME");
|
| - sb.append(name);
|
| - sb.endPosition();
|
| - }
|
| - // no members
|
| - sb.append(" {");
|
| - sb.append(eol);
|
| - sb.append("}");
|
| - }
|
| - // insert source
|
| - _insertBuilder(sb);
|
| - _addLinkedPosition("NAME", rf.rangeNode(node));
|
| - // add proposal
|
| - _addFix(FixKind.CREATE_CLASS, [name]);
|
| - }
|
| - }
|
| -
|
| - void _addFix_createConstructorSuperExplicit() {
|
| - ConstructorDeclaration targetConstructor =
|
| - node.parent as ConstructorDeclaration;
|
| - ClassDeclaration targetClassNode =
|
| - targetConstructor.parent as ClassDeclaration;
|
| - ClassElement targetClassElement = targetClassNode.element;
|
| - ClassElement superClassElement = targetClassElement.supertype.element;
|
| - // add proposals for all super constructors
|
| - List<ConstructorElement> superConstructors = superClassElement.constructors;
|
| - for (ConstructorElement superConstructor in superConstructors) {
|
| - String constructorName = superConstructor.name;
|
| - // skip private
|
| - if (Identifier.isPrivateName(constructorName)) {
|
| - continue;
|
| - }
|
| - // prepare SourceBuilder
|
| - SourceBuilder sb;
|
| - {
|
| - List<ConstructorInitializer> initializers =
|
| - targetConstructor.initializers;
|
| - if (initializers.isEmpty) {
|
| - int insertOffset = targetConstructor.parameters.end;
|
| - sb = new SourceBuilder(file, insertOffset);
|
| - sb.append(" : ");
|
| - } else {
|
| - ConstructorInitializer lastInitializer =
|
| - initializers[initializers.length - 1];
|
| - int insertOffset = lastInitializer.end;
|
| - sb = new SourceBuilder(file, insertOffset);
|
| - sb.append(", ");
|
| - }
|
| - }
|
| - // add super constructor name
|
| - sb.append("super");
|
| - if (!StringUtils.isEmpty(constructorName)) {
|
| - sb.append(".");
|
| - sb.append(constructorName);
|
| - }
|
| - // add arguments
|
| - sb.append("(");
|
| - bool firstParameter = true;
|
| - for (ParameterElement parameter in superConstructor.parameters) {
|
| - // skip non-required parameters
|
| - if (parameter.parameterKind != ParameterKind.REQUIRED) {
|
| - break;
|
| - }
|
| - // comma
|
| - if (firstParameter) {
|
| - firstParameter = false;
|
| - } else {
|
| - sb.append(", ");
|
| - }
|
| - // default value
|
| - DartType parameterType = parameter.type;
|
| - sb.startPosition(parameter.name);
|
| - sb.append(getDefaultValueCode(parameterType));
|
| - sb.endPosition();
|
| - }
|
| - sb.append(")");
|
| - // insert proposal
|
| - _insertBuilder(sb);
|
| - // add proposal
|
| - String proposalName = _getConstructorProposalName(superConstructor);
|
| - _addFix(FixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, [proposalName]);
|
| - }
|
| - }
|
| -
|
| - void _addFix_createConstructorSuperImplicit() {
|
| - ClassDeclaration targetClassNode = node.parent as ClassDeclaration;
|
| - ClassElement targetClassElement = targetClassNode.element;
|
| - ClassElement superClassElement = targetClassElement.supertype.element;
|
| - String targetClassName = targetClassElement.name;
|
| - // add proposals for all super constructors
|
| - List<ConstructorElement> superConstructors = superClassElement.constructors;
|
| - for (ConstructorElement superConstructor in superConstructors) {
|
| - String constructorName = superConstructor.name;
|
| - // skip private
|
| - if (Identifier.isPrivateName(constructorName)) {
|
| - continue;
|
| - }
|
| - // prepare parameters and arguments
|
| - SourceBuilder parametersBuffer = new SourceBuilder.buffer();
|
| - SourceBuilder argumentsBuffer = new SourceBuilder.buffer();
|
| - bool firstParameter = true;
|
| - for (ParameterElement parameter in superConstructor.parameters) {
|
| - // skip non-required parameters
|
| - if (parameter.parameterKind != ParameterKind.REQUIRED) {
|
| - break;
|
| - }
|
| - // comma
|
| - if (firstParameter) {
|
| - firstParameter = false;
|
| - } else {
|
| - parametersBuffer.append(', ');
|
| - argumentsBuffer.append(', ');
|
| - }
|
| - // name
|
| - String parameterName = parameter.displayName;
|
| - if (parameterName.length > 1 && parameterName.startsWith('_')) {
|
| - parameterName = parameterName.substring(1);
|
| - }
|
| - // parameter & argument
|
| - _appendParameterSource(parametersBuffer, parameter.type, parameterName);
|
| - argumentsBuffer.append(parameterName);
|
| - }
|
| - // add proposal
|
| - _ConstructorLocation targetLocation =
|
| - _prepareNewConstructorLocation(targetClassNode);
|
| - SourceBuilder sb = new SourceBuilder(file, targetLocation._offset);
|
| - {
|
| - String indent = utils.getIndent(1);
|
| - sb.append(targetLocation._prefix);
|
| - sb.append(indent);
|
| - sb.append(targetClassName);
|
| - if (!constructorName.isEmpty) {
|
| - sb.startPosition('NAME');
|
| - sb.append('.');
|
| - sb.append(constructorName);
|
| - sb.endPosition();
|
| - }
|
| - sb.append("(");
|
| - sb.append(parametersBuffer.toString());
|
| - sb.append(') : super');
|
| - if (!constructorName.isEmpty) {
|
| - sb.append('.');
|
| - sb.append(constructorName);
|
| - }
|
| - sb.append('(');
|
| - sb.append(argumentsBuffer.toString());
|
| - sb.append(');');
|
| - sb.append(targetLocation._suffix);
|
| - }
|
| - _insertBuilder(sb);
|
| - // add proposal
|
| - String proposalName = _getConstructorProposalName(superConstructor);
|
| - _addFix(FixKind.CREATE_CONSTRUCTOR_SUPER, [proposalName]);
|
| - }
|
| - }
|
| -
|
| - void _addFix_createConstructor_insteadOfSyntheticDefault() {
|
| - TypeName typeName = null;
|
| - ConstructorName constructorName = null;
|
| - InstanceCreationExpression instanceCreation = null;
|
| - if (node is SimpleIdentifier) {
|
| - if (node.parent is TypeName) {
|
| - typeName = node.parent as TypeName;
|
| - if (typeName.name == node && typeName.parent is ConstructorName) {
|
| - constructorName = typeName.parent as ConstructorName;
|
| - // should be synthetic default constructor
|
| - {
|
| - ConstructorElement constructorElement =
|
| - constructorName.staticElement;
|
| - if (constructorElement == null ||
|
| - !constructorElement.isDefaultConstructor ||
|
| - !constructorElement.isSynthetic) {
|
| - return;
|
| - }
|
| - }
|
| - // prepare InstanceCreationExpression
|
| - if (constructorName.parent is InstanceCreationExpression) {
|
| - instanceCreation = constructorName.parent as
|
| - InstanceCreationExpression;
|
| - if (instanceCreation.constructorName != constructorName) {
|
| - return;
|
| - }
|
| - }
|
| - }
|
| - }
|
| - }
|
| - // do we have enough information?
|
| - if (instanceCreation == null) {
|
| - return;
|
| - }
|
| - // prepare target
|
| - DartType targetType = typeName.type;
|
| - if (targetType is! InterfaceType) {
|
| - return;
|
| - }
|
| - ClassElement targetElement = targetType.element as ClassElement;
|
| - String targetFile = targetElement.source.fullName;
|
| - ClassDeclaration targetClass = targetElement.node;
|
| - _ConstructorLocation targetLocation =
|
| - _prepareNewConstructorLocation(targetClass);
|
| - // build method source
|
| - SourceBuilder sb = new SourceBuilder(targetFile, targetLocation._offset);
|
| - {
|
| - String indent = " ";
|
| - sb.append(targetLocation._prefix);
|
| - sb.append(indent);
|
| - sb.append(targetElement.name);
|
| - _addFix_undefinedMethod_create_parameters(
|
| - sb,
|
| - instanceCreation.argumentList);
|
| - sb.append(") {${eol}${indent}}");
|
| - sb.append(targetLocation._suffix);
|
| - }
|
| - // insert source
|
| - _insertBuilder(sb);
|
| - // add proposal
|
| - _addFix(FixKind.CREATE_CONSTRUCTOR, [constructorName], fixFile: targetFile);
|
| - }
|
| -
|
| - void _addFix_createConstructor_named() {
|
| - SimpleIdentifier name = null;
|
| - ConstructorName constructorName = null;
|
| - InstanceCreationExpression instanceCreation = null;
|
| - if (node is SimpleIdentifier) {
|
| - // name
|
| - name = node as SimpleIdentifier;
|
| - if (name.parent is ConstructorName) {
|
| - constructorName = name.parent as ConstructorName;
|
| - if (constructorName.name == name) {
|
| - // Type.name
|
| - if (constructorName.parent is InstanceCreationExpression) {
|
| - instanceCreation = constructorName.parent as
|
| - InstanceCreationExpression;
|
| - // new Type.name()
|
| - if (instanceCreation.constructorName != constructorName) {
|
| - return;
|
| - }
|
| - }
|
| - }
|
| - }
|
| - }
|
| - // do we have enough information?
|
| - if (instanceCreation == null) {
|
| - return;
|
| - }
|
| - // prepare target interface type
|
| - DartType targetType = constructorName.type.type;
|
| - if (targetType is! InterfaceType) {
|
| - return;
|
| - }
|
| - ClassElement targetElement = targetType.element as ClassElement;
|
| - String targetFile = targetElement.source.fullName;
|
| - ClassDeclaration targetClass = targetElement.node;
|
| - _ConstructorLocation targetLocation =
|
| - _prepareNewConstructorLocation(targetClass);
|
| - // build method source
|
| - SourceBuilder sb = new SourceBuilder(targetFile, targetLocation._offset);
|
| - {
|
| - String indent = " ";
|
| - sb.append(targetLocation._prefix);
|
| - sb.append(indent);
|
| - sb.append(targetElement.name);
|
| - sb.append(".");
|
| - // append name
|
| - {
|
| - sb.startPosition("NAME");
|
| - sb.append(name.name);
|
| - sb.endPosition();
|
| - }
|
| - _addFix_undefinedMethod_create_parameters(
|
| - sb,
|
| - instanceCreation.argumentList);
|
| - sb.append(") {${eol}${indent}}");
|
| - sb.append(targetLocation._suffix);
|
| - }
|
| - // insert source
|
| - _insertBuilder(sb);
|
| - if (targetFile == file) {
|
| - _addLinkedPosition("NAME", rf.rangeNode(name));
|
| - }
|
| - // add proposal
|
| - _addFix(FixKind.CREATE_CONSTRUCTOR, [constructorName], fixFile: targetFile);
|
| - }
|
| -
|
| - void _addFix_createFunction_forFunctionType() {
|
| - if (node is SimpleIdentifier) {
|
| - SimpleIdentifier nameNode = node as SimpleIdentifier;
|
| - // prepare argument expression (to get parameter)
|
| - ClassElement targetElement;
|
| - Expression argument;
|
| - {
|
| - Expression target = getQualifiedPropertyTarget(node);
|
| - if (target != null) {
|
| - DartType targetType = target.bestType;
|
| - if (targetType != null && targetType.element is ClassElement) {
|
| - targetElement = targetType.element as ClassElement;
|
| - argument = target.parent as Expression;
|
| - } else {
|
| - return;
|
| - }
|
| - } else {
|
| - ClassDeclaration enclosingClass =
|
| - node.getAncestor((node) => node is ClassDeclaration);
|
| - targetElement = enclosingClass != null ?
|
| - enclosingClass.element :
|
| - null;
|
| - argument = nameNode;
|
| - }
|
| - }
|
| - // should be argument of some invocation
|
| - ParameterElement parameterElement = argument.bestParameterElement;
|
| - if (parameterElement == null) {
|
| - return;
|
| - }
|
| - // should be parameter of function type
|
| - DartType parameterType = parameterElement.type;
|
| - if (parameterType is! FunctionType) {
|
| - return;
|
| - }
|
| - FunctionType functionType = parameterType as FunctionType;
|
| - // add proposal
|
| - if (targetElement != null) {
|
| - _addProposal_createFunction_method(targetElement, functionType);
|
| - } else {
|
| - _addProposal_createFunction_function(functionType);
|
| - }
|
| - }
|
| - }
|
| -
|
| - void
|
| - _addFix_createMissingOverrides(List<ExecutableElement> missingOverrides) {
|
| - // sort by name
|
| - missingOverrides.sort((Element firstElement, Element secondElement) {
|
| - return compareStrings(
|
| - firstElement.displayName,
|
| - secondElement.displayName);
|
| - });
|
| - ClassDeclaration targetClass = node.parent as ClassDeclaration;
|
| - int insertOffset = targetClass.end - 1;
|
| - SourceBuilder sb = new SourceBuilder(file, insertOffset);
|
| - // add elements
|
| - bool isFirst = true;
|
| - for (ExecutableElement missingOverride in missingOverrides) {
|
| - if (!isFirst || !targetClass.members.isEmpty) {
|
| - sb.append(eol);
|
| - }
|
| - _addFix_createMissingOverrides_single(sb, targetClass, missingOverride);
|
| - isFirst = false;
|
| - }
|
| - // add proposal
|
| - exitPosition = new Position(file, insertOffset);
|
| - _insertBuilder(sb);
|
| - _addFix(FixKind.CREATE_MISSING_OVERRIDES, [missingOverrides.length]);
|
| - }
|
| -
|
| - void _addFix_createMissingOverrides_single(SourceBuilder sb,
|
| - ClassDeclaration targetClass, ExecutableElement missingOverride) {
|
| - // prepare environment
|
| - String prefix = utils.getIndent(1);
|
| - String prefix2 = utils.getIndent(2);
|
| - // may be property
|
| - ElementKind elementKind = missingOverride.kind;
|
| - bool isGetter = elementKind == ElementKind.GETTER;
|
| - bool isSetter = elementKind == ElementKind.SETTER;
|
| - bool isMethod = elementKind == ElementKind.METHOD;
|
| - bool isOperator = isMethod && (missingOverride as MethodElement).isOperator;
|
| - sb.append(prefix);
|
| - if (isGetter) {
|
| - sb.append('// TODO: implement ${missingOverride.displayName}');
|
| - sb.append(eol);
|
| - sb.append(prefix);
|
| - }
|
| - // @override
|
| - {
|
| - sb.append('@override');
|
| - sb.append(eol);
|
| - sb.append(prefix);
|
| - }
|
| - // return type
|
| - _appendType(sb, missingOverride.type.returnType);
|
| - if (isGetter) {
|
| - sb.append('get ');
|
| - } else if (isSetter) {
|
| - sb.append('set ');
|
| - } else if (isOperator) {
|
| - sb.append('operator ');
|
| - }
|
| - // name
|
| - sb.append(missingOverride.displayName);
|
| - // parameters + body
|
| - if (isGetter) {
|
| - sb.append(' => null;');
|
| - } else {
|
| - List<ParameterElement> parameters = missingOverride.parameters;
|
| - _appendParameters(sb, parameters, _getDefaultValueMap(parameters));
|
| - sb.append(' {');
|
| - // TO-DO
|
| - sb.append(eol);
|
| - sb.append(prefix2);
|
| - sb.append('// TODO: implement ${missingOverride.displayName}');
|
| - sb.append(eol);
|
| - // close method
|
| - sb.append(prefix);
|
| - sb.append('}');
|
| - }
|
| - sb.append(eol);
|
| - }
|
| -
|
| - void _addFix_createNoSuchMethod() {
|
| - ClassDeclaration targetClass = node.parent as ClassDeclaration;
|
| - // prepare environment
|
| - String prefix = utils.getIndent(1);
|
| - int insertOffset = targetClass.end - 1;
|
| - // prepare source
|
| - SourceBuilder sb = new SourceBuilder(file, insertOffset);
|
| - {
|
| - // insert empty line before existing member
|
| - if (!targetClass.members.isEmpty) {
|
| - sb.append(eol);
|
| - }
|
| - // append method
|
| - sb.append(prefix);
|
| - sb.append(
|
| - "noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);");
|
| - sb.append(eol);
|
| - }
|
| - // done
|
| - _insertBuilder(sb);
|
| - exitPosition = new Position(file, insertOffset);
|
| - // add proposal
|
| - _addFix(FixKind.CREATE_NO_SUCH_METHOD, []);
|
| - }
|
| -
|
| - void _addFix_importLibrary(FixKind kind, String importPath) {
|
| - CompilationUnitElement libraryUnitElement =
|
| - unitLibraryElement.definingCompilationUnit;
|
| - CompilationUnit libraryUnit = libraryUnitElement.node;
|
| - // prepare new import location
|
| - int offset = 0;
|
| - String prefix;
|
| - String suffix;
|
| - {
|
| - // if no directives
|
| - prefix = "";
|
| - suffix = eol;
|
| - CorrectionUtils libraryUtils = new CorrectionUtils(libraryUnit);
|
| - // after last directive in library
|
| - for (Directive directive in libraryUnit.directives) {
|
| - if (directive is LibraryDirective || directive is ImportDirective) {
|
| - offset = directive.end;
|
| - prefix = eol;
|
| - suffix = "";
|
| - }
|
| - }
|
| - // if still beginning of file, skip shebang and line comments
|
| - if (offset == 0) {
|
| - CorrectionUtils_InsertDesc desc = libraryUtils.getInsertDescTop();
|
| - offset = desc.offset;
|
| - prefix = desc.prefix;
|
| - suffix = "${desc.suffix}${eol}";
|
| - }
|
| - }
|
| - // insert new import
|
| - String importSource = "${prefix}import '${importPath}';${suffix}";
|
| - _addInsertEdit(offset, importSource);
|
| - // add proposal
|
| - _addFix(kind, [importPath], fixFile: libraryUnitElement.source.fullName);
|
| - }
|
| -
|
| - void _addFix_importLibrary_withElement(String name, ElementKind kind) {
|
| - // ignore if private
|
| - if (name.startsWith("_")) {
|
| - return;
|
| - }
|
| -
|
| - // may be there is an existing import,
|
| - // but it is with prefix and we don't use this prefix
|
| - for (ImportElement imp in unitLibraryElement.imports) {
|
| - // prepare element
|
| - LibraryElement libraryElement = imp.importedLibrary;
|
| - Element element = getExportedElement(libraryElement, name);
|
| - if (element == null) {
|
| - continue;
|
| - }
|
| - if (element is PropertyAccessorElement) {
|
| - element = (element as PropertyAccessorElement).variable;
|
| - }
|
| - if (element.kind != kind) {
|
| - continue;
|
| - }
|
| - // may be apply prefix
|
| - PrefixElement prefix = imp.prefix;
|
| - if (prefix != null) {
|
| - SourceRange range = rf.rangeStartLength(node, 0);
|
| - _addReplaceEdit(range, "${prefix.displayName}.");
|
| - _addFix(
|
| - FixKind.IMPORT_LIBRARY_PREFIX,
|
| - [libraryElement.displayName, prefix.displayName]);
|
| - continue;
|
| - }
|
| - // may be update "show" directive
|
| - List<NamespaceCombinator> combinators = imp.combinators;
|
| - if (combinators.length == 1 && combinators[0] is ShowElementCombinator) {
|
| - ShowElementCombinator showCombinator =
|
| - combinators[0] as ShowElementCombinator;
|
| - // prepare new set of names to show
|
| - Set<String> showNames = new SplayTreeSet<String>();
|
| - showNames.addAll(showCombinator.shownNames);
|
| - showNames.add(name);
|
| - // prepare library name - unit name or 'dart:name' for SDK library
|
| - String libraryName = libraryElement.definingCompilationUnit.displayName;
|
| - if (libraryElement.isInSdk) {
|
| - libraryName = imp.uri;
|
| - }
|
| - // update library
|
| - String newShowCode = "show ${StringUtils.join(showNames, ", ")}";
|
| - _addReplaceEdit(rf.rangeOffsetEnd(showCombinator), newShowCode);
|
| - _addFix(
|
| - FixKind.IMPORT_LIBRARY_SHOW,
|
| - [libraryName],
|
| - fixFile: unitLibraryFile);
|
| - // we support only one import without prefix
|
| - return;
|
| - }
|
| - }
|
| - // check SDK libraries
|
| - AnalysisContext context = unitLibraryElement.context;
|
| - {
|
| - DartSdk sdk = context.sourceFactory.dartSdk;
|
| - List<SdkLibrary> sdkLibraries = sdk.sdkLibraries;
|
| - for (SdkLibrary sdkLibrary in sdkLibraries) {
|
| - SourceFactory sdkSourceFactory = context.sourceFactory;
|
| - String libraryUri = 'dart:' + sdkLibrary.shortName;
|
| - Source librarySource =
|
| - sdkSourceFactory.resolveUri(unitSource, libraryUri);
|
| - // prepare LibraryElement
|
| - LibraryElement libraryElement =
|
| - context.getLibraryElement(librarySource);
|
| - if (libraryElement == null) {
|
| - continue;
|
| - }
|
| - // prepare exported Element
|
| - Element element = getExportedElement(libraryElement, name);
|
| - if (element == null) {
|
| - continue;
|
| - }
|
| - if (element is PropertyAccessorElement) {
|
| - element = (element as PropertyAccessorElement).variable;
|
| - }
|
| - if (element.kind != kind) {
|
| - continue;
|
| - }
|
| - // add import
|
| - _addFix_importLibrary(FixKind.IMPORT_LIBRARY_SDK, libraryUri);
|
| - }
|
| - }
|
| - // check project libraries
|
| - {
|
| - List<Source> librarySources = context.librarySources;
|
| - for (Source librarySource in librarySources) {
|
| - // we don't need SDK libraries here
|
| - if (librarySource.isInSystemLibrary) {
|
| - continue;
|
| - }
|
| - // prepare LibraryElement
|
| - LibraryElement libraryElement =
|
| - context.getLibraryElement(librarySource);
|
| - if (libraryElement == null) {
|
| - continue;
|
| - }
|
| - // prepare exported Element
|
| - Element element = getExportedElement(libraryElement, name);
|
| - if (element == null) {
|
| - continue;
|
| - }
|
| - if (element is PropertyAccessorElement) {
|
| - element = (element as PropertyAccessorElement).variable;
|
| - }
|
| - if (element.kind != kind) {
|
| - continue;
|
| - }
|
| - // prepare "library" file
|
| - String libraryFile = librarySource.fullName;
|
| - // may be "package:" URI
|
| - {
|
| - String libraryPackageUri = _findPackageUri(context, libraryFile);
|
| - if (libraryPackageUri != null) {
|
| - _addFix_importLibrary(
|
| - FixKind.IMPORT_LIBRARY_PROJECT,
|
| - libraryPackageUri);
|
| - continue;
|
| - }
|
| - }
|
| - // relative URI
|
| - String relativeFile = relative(libraryFile, from: unitLibraryFolder);
|
| - relativeFile = split(relativeFile).join('/');
|
| - _addFix_importLibrary(FixKind.IMPORT_LIBRARY_PROJECT, relativeFile);
|
| - }
|
| - }
|
| - }
|
| -
|
| - void _addFix_importLibrary_withFunction() {
|
| - if (node is SimpleIdentifier && node.parent is MethodInvocation) {
|
| - MethodInvocation invocation = node.parent as MethodInvocation;
|
| - if (invocation.realTarget == null && invocation.methodName == node) {
|
| - String name = (node as SimpleIdentifier).name;
|
| - _addFix_importLibrary_withElement(name, ElementKind.FUNCTION);
|
| - }
|
| - }
|
| - }
|
| -
|
| - void _addFix_importLibrary_withTopLevelVariable() {
|
| - if (node is SimpleIdentifier) {
|
| - String name = (node as SimpleIdentifier).name;
|
| - _addFix_importLibrary_withElement(name, ElementKind.TOP_LEVEL_VARIABLE);
|
| - }
|
| - }
|
| -
|
| - void _addFix_importLibrary_withType() {
|
| - if (_mayBeTypeIdentifier(node)) {
|
| - String typeName = (node as SimpleIdentifier).name;
|
| - _addFix_importLibrary_withElement(typeName, ElementKind.CLASS);
|
| - }
|
| - }
|
| -
|
| - void _addFix_insertSemicolon() {
|
| - if (error.message.contains("';'")) {
|
| - int insertOffset = error.offset + error.length;
|
| - _addInsertEdit(insertOffset, ";");
|
| - _addFix(FixKind.INSERT_SEMICOLON, []);
|
| - }
|
| - }
|
| -
|
| - void _addFix_isNotNull() {
|
| - if (coveredNode is IsExpression) {
|
| - IsExpression isExpression = coveredNode as IsExpression;
|
| - _addReplaceEdit(
|
| - rf.rangeEndEnd(isExpression.expression, isExpression),
|
| - " != null");
|
| - _addFix(FixKind.USE_NOT_EQ_NULL, []);
|
| - }
|
| - }
|
| -
|
| - void _addFix_isNull() {
|
| - if (coveredNode is IsExpression) {
|
| - IsExpression isExpression = coveredNode as IsExpression;
|
| - _addReplaceEdit(
|
| - rf.rangeEndEnd(isExpression.expression, isExpression),
|
| - " == null");
|
| - _addFix(FixKind.USE_EQ_EQ_NULL, []);
|
| - }
|
| - }
|
| -
|
| - void _addFix_makeEnclosingClassAbstract() {
|
| - ClassDeclaration enclosingClass =
|
| - node.getAncestor((node) => node is ClassDeclaration);
|
| - String className = enclosingClass.name.name;
|
| - _addInsertEdit(enclosingClass.classKeyword.offset, "abstract ");
|
| - _addFix(FixKind.MAKE_CLASS_ABSTRACT, [className]);
|
| - }
|
| -
|
| - void _addFix_removeParameters_inGetterDeclaration() {
|
| - if (node is SimpleIdentifier && node.parent is MethodDeclaration) {
|
| - MethodDeclaration method = node.parent as MethodDeclaration;
|
| - FunctionBody body = method.body;
|
| - if (method.name == node && body != null) {
|
| - _addReplaceEdit(rf.rangeEndStart(node, body), " ");
|
| - _addFix(FixKind.REMOVE_PARAMETERS_IN_GETTER_DECLARATION, []);
|
| - }
|
| - }
|
| - }
|
| -
|
| - void _addFix_removeParentheses_inGetterInvocation() {
|
| - if (node is SimpleIdentifier && node.parent is MethodInvocation) {
|
| - MethodInvocation invocation = node.parent as MethodInvocation;
|
| - if (invocation.methodName == node && invocation.target != null) {
|
| - _addRemoveEdit(rf.rangeEndEnd(node, invocation));
|
| - _addFix(FixKind.REMOVE_PARENTHESIS_IN_GETTER_INVOCATION, []);
|
| - }
|
| - }
|
| - }
|
| -
|
| - void _addFix_removeUnnecessaryCast() {
|
| - if (coveredNode is! AsExpression) {
|
| - return;
|
| - }
|
| - AsExpression asExpression = coveredNode as AsExpression;
|
| - Expression expression = asExpression.expression;
|
| - int expressionPrecedence = getExpressionPrecedence(expression);
|
| - // remove 'as T' from 'e as T'
|
| - _addRemoveEdit(rf.rangeEndEnd(expression, asExpression));
|
| - _removeEnclosingParentheses(asExpression, expressionPrecedence);
|
| - // done
|
| - _addFix(FixKind.REMOVE_UNNECASSARY_CAST, []);
|
| - }
|
| -
|
| - void _addFix_removeUnusedImport() {
|
| - // prepare ImportDirective
|
| - ImportDirective importDirective =
|
| - node.getAncestor((node) => node is ImportDirective);
|
| - if (importDirective == null) {
|
| - return;
|
| - }
|
| - // remove the whole line with import
|
| - _addRemoveEdit(utils.getLinesRange(rf.rangeNode(importDirective)));
|
| - // done
|
| - _addFix(FixKind.REMOVE_UNUSED_IMPORT, []);
|
| - }
|
| -
|
| - void _addFix_replaceWithConstInstanceCreation() {
|
| - if (coveredNode is InstanceCreationExpression) {
|
| - var instanceCreation = coveredNode as InstanceCreationExpression;
|
| - _addReplaceEdit(rf.rangeToken(instanceCreation.keyword), "const");
|
| - _addFix(FixKind.USE_CONST, []);
|
| - }
|
| - }
|
| -
|
| - void _addFix_undefinedClass_useSimilar() {
|
| - if (_mayBeTypeIdentifier(node)) {
|
| - String name = (node as SimpleIdentifier).name;
|
| - _ClosestElementFinder finder =
|
| - new _ClosestElementFinder(
|
| - name,
|
| - (Element element) => element is ClassElement,
|
| - MAX_LEVENSHTEIN_DISTANCE);
|
| - // find closest element
|
| - {
|
| - // elements of this library
|
| - for (CompilationUnitElement unit in unitLibraryElement.units) {
|
| - finder._updateList(unit.types);
|
| - }
|
| - // elements from imports
|
| - for (ImportElement importElement in unitLibraryElement.imports) {
|
| - if (importElement.prefix == null) {
|
| - Map<String, Element> namespace = getImportNamespace(importElement);
|
| - finder._updateList(namespace.values);
|
| - }
|
| - }
|
| - }
|
| - // if we have close enough element, suggest to use it
|
| - if (finder._element != null) {
|
| - String closestName = finder._element.name;
|
| - _addReplaceEdit(rf.rangeNode(node), closestName);
|
| - // add proposal
|
| - if (closestName != null) {
|
| - _addFix(FixKind.CHANGE_TO, [closestName]);
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - void _addFix_undefinedFunction_create() {
|
| - // should be the name of the invocation
|
| - if (node is SimpleIdentifier && node.parent is MethodInvocation) {
|
| - } else {
|
| - return;
|
| - }
|
| - String name = (node as SimpleIdentifier).name;
|
| - MethodInvocation invocation = node.parent as MethodInvocation;
|
| - // function invocation has no target
|
| - Expression target = invocation.realTarget;
|
| - if (target != null) {
|
| - return;
|
| - }
|
| - // prepare environment
|
| - int insertOffset;
|
| - String sourcePrefix;
|
| - AstNode enclosingMember =
|
| - node.getAncestor((node) => node is CompilationUnitMember);
|
| - insertOffset = enclosingMember.end;
|
| - sourcePrefix = "${eol}${eol}";
|
| - // build method source
|
| - SourceBuilder sb = new SourceBuilder(file, insertOffset);
|
| - {
|
| - sb.append(sourcePrefix);
|
| - // append return type
|
| - {
|
| - DartType type = _inferReturnType(invocation);
|
| - _appendType(sb, type, 'RETURN_TYPE');
|
| - }
|
| - // append name
|
| - {
|
| - sb.startPosition("NAME");
|
| - sb.append(name);
|
| - sb.endPosition();
|
| - }
|
| - _addFix_undefinedMethod_create_parameters(sb, invocation.argumentList);
|
| - sb.append(") {${eol}}");
|
| - }
|
| - // insert source
|
| - _insertBuilder(sb);
|
| - _addLinkedPosition3('NAME', sb, rf.rangeNode(node));
|
| - // add proposal
|
| - _addFix(FixKind.CREATE_FUNCTION, [name]);
|
| - }
|
| -
|
| - void _addFix_undefinedFunction_useSimilar() {
|
| - if (node is SimpleIdentifier) {
|
| - String name = (node as SimpleIdentifier).name;
|
| - _ClosestElementFinder finder =
|
| - new _ClosestElementFinder(
|
| - name,
|
| - (Element element) => element is FunctionElement,
|
| - MAX_LEVENSHTEIN_DISTANCE);
|
| - // this library
|
| - for (CompilationUnitElement unit in unitLibraryElement.units) {
|
| - finder._updateList(unit.functions);
|
| - }
|
| - // imports
|
| - for (ImportElement importElement in unitLibraryElement.imports) {
|
| - if (importElement.prefix == null) {
|
| - Map<String, Element> namespace = getImportNamespace(importElement);
|
| - finder._updateList(namespace.values);
|
| - }
|
| - }
|
| - // if we have close enough element, suggest to use it
|
| - if (finder._element != null) {
|
| - String closestName = finder._element.name;
|
| - _addReplaceEdit(rf.rangeNode(node), closestName);
|
| - _addFix(FixKind.CHANGE_TO, [closestName]);
|
| - }
|
| - }
|
| - }
|
| -
|
| - void _addFix_undefinedMethod_create() {
|
| - if (node is SimpleIdentifier && node.parent is MethodInvocation) {
|
| - String name = (node as SimpleIdentifier).name;
|
| - MethodInvocation invocation = node.parent as MethodInvocation;
|
| - // prepare environment
|
| - Source targetSource;
|
| - String prefix;
|
| - int insertOffset;
|
| - String sourcePrefix;
|
| - String sourceSuffix;
|
| - bool staticModifier = false;
|
| - Expression target = invocation.realTarget;
|
| - if (target == null) {
|
| - targetSource = source;
|
| - ClassMember enclosingMember =
|
| - node.getAncestor((node) => node is ClassMember);
|
| - staticModifier = _inStaticContext();
|
| - prefix = utils.getNodePrefix(enclosingMember);
|
| - insertOffset = enclosingMember.end;
|
| - sourcePrefix = "${eol}${eol}";
|
| - sourceSuffix = "";
|
| - } else {
|
| - // prepare target interface type
|
| - DartType targetType = target.bestType;
|
| - if (targetType is! InterfaceType) {
|
| - return;
|
| - }
|
| - ClassElement targetElement = targetType.element as ClassElement;
|
| - targetSource = targetElement.source;
|
| - // may be static
|
| - if (target is Identifier) {
|
| - staticModifier = target.bestElement.kind == ElementKind.CLASS;
|
| - }
|
| - // prepare insert offset
|
| - ClassDeclaration targetClass = targetElement.node;
|
| - prefix = " ";
|
| - insertOffset = targetClass.end - 1;
|
| - if (targetClass.members.isEmpty) {
|
| - sourcePrefix = "";
|
| - } else {
|
| - sourcePrefix = eol;
|
| - }
|
| - sourceSuffix = eol;
|
| - }
|
| - String targetFile = targetSource.fullName;
|
| - // build method source
|
| - SourceBuilder sb = new SourceBuilder(targetFile, insertOffset);
|
| - {
|
| - sb.append(sourcePrefix);
|
| - sb.append(prefix);
|
| - // maybe "static"
|
| - if (staticModifier) {
|
| - sb.append("static ");
|
| - }
|
| - // append return type
|
| - _appendType(sb, _inferReturnType(invocation), 'RETURN_TYPE');
|
| - // append name
|
| - {
|
| - sb.startPosition("NAME");
|
| - sb.append(name);
|
| - sb.endPosition();
|
| - }
|
| - _addFix_undefinedMethod_create_parameters(sb, invocation.argumentList);
|
| - sb.append(") {${eol}${prefix}}");
|
| - sb.append(sourceSuffix);
|
| - }
|
| - // insert source
|
| - _insertBuilder(sb);
|
| - // add linked positions
|
| - if (targetSource == source) {
|
| - _addLinkedPosition3('NAME', sb, rf.rangeNode(node));
|
| - }
|
| - // add proposal
|
| - _addFix(FixKind.CREATE_METHOD, [name], fixFile: targetFile);
|
| - }
|
| - }
|
| -
|
| - void _addFix_undefinedMethod_create_parameters(SourceBuilder sb,
|
| - ArgumentList argumentList) {
|
| - // append parameters
|
| - sb.append("(");
|
| - Set<String> excluded = new Set();
|
| - List<Expression> arguments = argumentList.arguments;
|
| - for (int i = 0; i < arguments.length; i++) {
|
| - Expression argument = arguments[i];
|
| - // append separator
|
| - if (i != 0) {
|
| - sb.append(", ");
|
| - }
|
| - // append type name
|
| - DartType type = argument.bestType;
|
| - String typeSource = utils.getTypeSource(type);
|
| - {
|
| - sb.startPosition("TYPE${i}");
|
| - sb.append(typeSource);
|
| - _addSuperTypeProposals(sb, new Set(), type);
|
| - sb.endPosition();
|
| - }
|
| - sb.append(" ");
|
| - // append parameter name
|
| - {
|
| - List<String> suggestions =
|
| - _getArgumentNameSuggestions(excluded, type, argument, i);
|
| - String favorite = suggestions[0];
|
| - excluded.add(favorite);
|
| - sb.startPosition("ARG${i}");
|
| - sb.append(favorite);
|
| - sb.addSuggestions(LinkedEditSuggestionKind.PARAMETER, suggestions);
|
| - sb.endPosition();
|
| - }
|
| - }
|
| - }
|
| -
|
| - void _addFix_undefinedMethod_useSimilar() {
|
| - if (node is SimpleIdentifier && node.parent is MethodInvocation) {
|
| - MethodInvocation invocation = node.parent as MethodInvocation;
|
| - String name = (node as SimpleIdentifier).name;
|
| - _ClosestElementFinder finder =
|
| - new _ClosestElementFinder(
|
| - name,
|
| - (Element element) => element is MethodElement && !element.isOperator,
|
| - MAX_LEVENSHTEIN_DISTANCE);
|
| - // unqualified invocation
|
| - Expression target = invocation.realTarget;
|
| - if (target == null) {
|
| - ClassDeclaration clazz =
|
| - invocation.getAncestor((node) => node is ClassDeclaration);
|
| - if (clazz != null) {
|
| - ClassElement classElement = clazz.element;
|
| - _updateFinderWithClassMembers(finder, classElement);
|
| - }
|
| - } else {
|
| - DartType type = target.bestType;
|
| - if (type is InterfaceType) {
|
| - ClassElement classElement = type.element;
|
| - _updateFinderWithClassMembers(finder, classElement);
|
| - }
|
| - }
|
| - // if we have close enough element, suggest to use it
|
| - if (finder._element != null) {
|
| - String closestName = finder._element.name;
|
| - _addReplaceEdit(rf.rangeNode(node), closestName);
|
| - _addFix(FixKind.CHANGE_TO, [closestName]);
|
| - }
|
| - }
|
| - }
|
| -
|
| - void _addFix_useEffectiveIntegerDivision() {
|
| - for (AstNode n = node; n != null; n = n.parent) {
|
| - if (n is MethodInvocation &&
|
| - n.offset == errorOffset &&
|
| - n.length == errorLength) {
|
| - MethodInvocation invocation = n as MethodInvocation;
|
| - Expression target = invocation.target;
|
| - while (target is ParenthesizedExpression) {
|
| - target = (target as ParenthesizedExpression).expression;
|
| - }
|
| - // replace "/" with "~/"
|
| - BinaryExpression binary = target as BinaryExpression;
|
| - _addReplaceEdit(rf.rangeToken(binary.operator), "~/");
|
| - // remove everything before and after
|
| - _addRemoveEdit(rf.rangeStartStart(invocation, binary.leftOperand));
|
| - _addRemoveEdit(rf.rangeEndEnd(binary.rightOperand, invocation));
|
| - // add proposal
|
| - _addFix(FixKind.USE_EFFECTIVE_INTEGER_DIVISION, []);
|
| - // done
|
| - break;
|
| - }
|
| - }
|
| - }
|
| -
|
| - void _addFix_useStaticAccess_method() {
|
| - if (node is SimpleIdentifier && node.parent is MethodInvocation) {
|
| - MethodInvocation invocation = node.parent as MethodInvocation;
|
| - if (invocation.methodName == node) {
|
| - Expression target = invocation.target;
|
| - String targetType = utils.getExpressionTypeSource(target);
|
| - // replace "target" with class name
|
| - SourceRange range = rf.rangeNode(target);
|
| - _addReplaceEdit(range, targetType);
|
| - // add proposal
|
| - _addFix(FixKind.CHANGE_TO_STATIC_ACCESS, [targetType]);
|
| - }
|
| - }
|
| - }
|
| -
|
| - void _addFix_useStaticAccess_property() {
|
| - if (node is SimpleIdentifier) {
|
| - if (node.parent is PrefixedIdentifier) {
|
| - PrefixedIdentifier prefixed = node.parent as PrefixedIdentifier;
|
| - if (prefixed.identifier == node) {
|
| - Expression target = prefixed.prefix;
|
| - String targetType = utils.getExpressionTypeSource(target);
|
| - // replace "target" with class name
|
| - SourceRange range = rf.rangeNode(target);
|
| - _addReplaceEdit(range, targetType);
|
| - // add proposal
|
| - _addFix(FixKind.CHANGE_TO_STATIC_ACCESS, [targetType]);
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Adds a new [Edit] to [edits].
|
| - */
|
| - void _addInsertEdit(int offset, String text) {
|
| - Edit edit = new Edit(offset, 0, text);
|
| - edits.add(edit);
|
| - }
|
| -
|
| - /**
|
| - * Adds a single linked position to [groupId].
|
| - */
|
| - void _addLinkedPosition(String groupId, SourceRange range) {
|
| - Position position = new Position(file, range.offset);
|
| - LinkedEditGroup group = _getLinkedPosition(groupId);
|
| - group.addPosition(position, range.length);
|
| - }
|
| -
|
| - /**
|
| - * Adds a single linked position to [groupId].
|
| - */
|
| - void _addLinkedPosition3(String groupId, SourceBuilder sb,
|
| - SourceRange range) {
|
| - if (sb.offset < range.offset) {
|
| - int delta = sb.length;
|
| - range = range.getTranslated(delta);
|
| - }
|
| - _addLinkedPosition(groupId, range);
|
| - }
|
| -
|
| - /**
|
| - * Prepares proposal for creating function corresponding to the given [FunctionType].
|
| - */
|
| - void _addProposal_createFunction(FunctionType functionType, String name,
|
| - Source targetSource, int insertOffset, bool isStatic, String prefix,
|
| - String sourcePrefix, String sourceSuffix) {
|
| - // build method source
|
| - String targetFile = targetSource.fullName;
|
| - SourceBuilder sb = new SourceBuilder(targetFile, insertOffset);
|
| - {
|
| - sb.append(sourcePrefix);
|
| - sb.append(prefix);
|
| - // may be static
|
| - if (isStatic) {
|
| - sb.append("static ");
|
| - }
|
| - // append return type
|
| - _appendType(sb, functionType.returnType, 'RETURN_TYPE');
|
| - // append name
|
| - {
|
| - sb.startPosition("NAME");
|
| - sb.append(name);
|
| - sb.endPosition();
|
| - }
|
| - // append parameters
|
| - sb.append("(");
|
| - List<ParameterElement> parameters = functionType.parameters;
|
| - for (int i = 0; i < parameters.length; i++) {
|
| - ParameterElement parameter = parameters[i];
|
| - // append separator
|
| - if (i != 0) {
|
| - sb.append(", ");
|
| - }
|
| - // append type name
|
| - DartType type = parameter.type;
|
| - if (!type.isDynamic) {
|
| - String typeSource = utils.getTypeSource(type);
|
| - {
|
| - sb.startPosition("TYPE${i}");
|
| - sb.append(typeSource);
|
| - _addSuperTypeProposals(sb, new Set(), type);
|
| - sb.endPosition();
|
| - }
|
| - sb.append(" ");
|
| - }
|
| - // append parameter name
|
| - {
|
| - sb.startPosition("ARG${i}");
|
| - sb.append(parameter.displayName);
|
| - sb.endPosition();
|
| - }
|
| - }
|
| - sb.append(")");
|
| - // close method
|
| - sb.append(" {${eol}${prefix}}");
|
| - sb.append(sourceSuffix);
|
| - }
|
| - // insert source
|
| - _insertBuilder(sb);
|
| - // add linked positions
|
| - if (targetSource == source) {
|
| - _addLinkedPosition3("NAME", sb, rf.rangeNode(node));
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Adds proposal for creating method corresponding to the given [FunctionType] in the given
|
| - * [ClassElement].
|
| - */
|
| - void _addProposal_createFunction_function(FunctionType functionType) {
|
| - String name = (node as SimpleIdentifier).name;
|
| - // prepare environment
|
| - int insertOffset = unit.end;
|
| - // prepare prefix
|
| - String prefix = "";
|
| - String sourcePrefix = "${eol}";
|
| - String sourceSuffix = eol;
|
| - _addProposal_createFunction(
|
| - functionType,
|
| - name,
|
| - source,
|
| - insertOffset,
|
| - false,
|
| - prefix,
|
| - sourcePrefix,
|
| - sourceSuffix);
|
| - // add proposal
|
| - _addFix(FixKind.CREATE_FUNCTION, [name], fixFile: file);
|
| - }
|
| -
|
| - /**
|
| - * Adds proposal for creating method corresponding to the given [FunctionType] in the given
|
| - * [ClassElement].
|
| - */
|
| - void _addProposal_createFunction_method(ClassElement targetClassElement,
|
| - FunctionType functionType) {
|
| - String name = (node as SimpleIdentifier).name;
|
| - // prepare environment
|
| - Source targetSource = targetClassElement.source;
|
| - String targetFile = targetSource.fullName;
|
| - // prepare insert offset
|
| - ClassDeclaration targetClassNode = targetClassElement.node;
|
| - int insertOffset = targetClassNode.end - 1;
|
| - // prepare prefix
|
| - String prefix = " ";
|
| - String sourcePrefix;
|
| - if (targetClassNode.members.isEmpty) {
|
| - sourcePrefix = "";
|
| - } else {
|
| - sourcePrefix = eol;
|
| - }
|
| - String sourceSuffix = eol;
|
| - _addProposal_createFunction(
|
| - functionType,
|
| - name,
|
| - targetSource,
|
| - insertOffset,
|
| - _inStaticContext(),
|
| - prefix,
|
| - sourcePrefix,
|
| - sourceSuffix);
|
| - // add proposal
|
| - _addFix(FixKind.CREATE_METHOD, [name], fixFile: targetFile);
|
| - }
|
| -
|
| - /**
|
| - * Adds a new [Edit] to [edits].
|
| - */
|
| - void _addRemoveEdit(SourceRange range) {
|
| - _addReplaceEdit(range, '');
|
| - }
|
| -
|
| - /**
|
| - * Adds a new [Edit] to [edits].
|
| - */
|
| - void _addReplaceEdit(SourceRange range, String text) {
|
| - Edit edit = new Edit(range.offset, range.length, text);
|
| - edits.add(edit);
|
| - }
|
| -
|
| - void _appendParameterSource(SourceBuilder sb, DartType type, String name) {
|
| - String parameterSource = utils.getParameterSource(type, name);
|
| - sb.append(parameterSource);
|
| - }
|
| -
|
| - void _appendParameters(SourceBuilder sb, List<ParameterElement> parameters,
|
| - Map<ParameterElement, String> defaultValueMap) {
|
| - sb.append("(");
|
| - bool firstParameter = true;
|
| - bool sawNamed = false;
|
| - bool sawPositional = false;
|
| - for (ParameterElement parameter in parameters) {
|
| - if (!firstParameter) {
|
| - sb.append(", ");
|
| - } else {
|
| - firstParameter = false;
|
| - }
|
| - // may be optional
|
| - ParameterKind parameterKind = parameter.parameterKind;
|
| - if (parameterKind == ParameterKind.NAMED) {
|
| - if (!sawNamed) {
|
| - sb.append("{");
|
| - sawNamed = true;
|
| - }
|
| - }
|
| - if (parameterKind == ParameterKind.POSITIONAL) {
|
| - if (!sawPositional) {
|
| - sb.append("[");
|
| - sawPositional = true;
|
| - }
|
| - }
|
| - // parameter
|
| - _appendParameterSource(sb, parameter.type, parameter.name);
|
| - // default value
|
| - if (defaultValueMap != null) {
|
| - String defaultSource = defaultValueMap[parameter];
|
| - if (defaultSource != null) {
|
| - if (sawPositional) {
|
| - sb.append(" = ");
|
| - } else {
|
| - sb.append(": ");
|
| - }
|
| - sb.append(defaultSource);
|
| - }
|
| - }
|
| - }
|
| - // close parameters
|
| - if (sawNamed) {
|
| - sb.append("}");
|
| - }
|
| - if (sawPositional) {
|
| - sb.append("]");
|
| - }
|
| - sb.append(")");
|
| - }
|
| -
|
| - void _appendType(SourceBuilder sb, DartType type, [String groupId]) {
|
| - if (type != null && !type.isDynamic) {
|
| - String typeSource = utils.getTypeSource(type);
|
| - if (groupId != null) {
|
| - sb.startPosition(groupId);
|
| - sb.append(typeSource);
|
| - sb.endPosition();
|
| - } else {
|
| - sb.append(typeSource);
|
| - }
|
| - sb.append(' ');
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * @return the string to display as the name of the given constructor in a proposal name.
|
| - */
|
| - String _getConstructorProposalName(ConstructorElement constructor) {
|
| - SourceBuilder proposalNameBuffer = new SourceBuilder.buffer();
|
| - proposalNameBuffer.append("super");
|
| - // may be named
|
| - String constructorName = constructor.displayName;
|
| - if (!constructorName.isEmpty) {
|
| - proposalNameBuffer.append(".");
|
| - proposalNameBuffer.append(constructorName);
|
| - }
|
| - // parameters
|
| - _appendParameters(proposalNameBuffer, constructor.parameters, null);
|
| - // done
|
| - return proposalNameBuffer.toString();
|
| - }
|
| -
|
| - /**
|
| - * Returns the [Type] with given name from the `dart:core` library.
|
| - */
|
| - DartType _getCoreType(String name) {
|
| - List<LibraryElement> libraries = unitLibraryElement.importedLibraries;
|
| - for (LibraryElement library in libraries) {
|
| - if (library.isDartCore) {
|
| - ClassElement classElement = library.getType(name);
|
| - if (classElement != null) {
|
| - return classElement.type;
|
| - }
|
| - return null;
|
| - }
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - Map<ParameterElement, String>
|
| - _getDefaultValueMap(List<ParameterElement> parameters) {
|
| - Map<ParameterElement, String> defaultSourceMap = {};
|
| - Map<Source, String> sourceContentMap = {};
|
| - for (ParameterElement parameter in parameters) {
|
| - SourceRange valueRange = parameter.defaultValueRange;
|
| - if (valueRange != null) {
|
| - Source source = parameter.source;
|
| - String sourceContent = sourceContentMap[source];
|
| - if (sourceContent == null) {
|
| - sourceContent = getSourceContent(parameter.context, source);
|
| - sourceContentMap[source] = sourceContent;
|
| - }
|
| - String valueSource =
|
| - sourceContent.substring(valueRange.offset, valueRange.end);
|
| - defaultSourceMap[parameter] = valueSource;
|
| - }
|
| - }
|
| - return defaultSourceMap;
|
| - }
|
| -
|
| - /**
|
| - * Returns an existing or just added [LinkedEditGroup] with [groupId].
|
| - */
|
| - LinkedEditGroup _getLinkedPosition(String groupId) {
|
| - LinkedEditGroup group = linkedPositionGroups[groupId];
|
| - if (group == null) {
|
| - group = new LinkedEditGroup(groupId);
|
| - linkedPositionGroups[groupId] = group;
|
| - }
|
| - return group;
|
| - }
|
| -
|
| - /**
|
| - * Returns `true` if [node] is in static context.
|
| - */
|
| - bool _inStaticContext() {
|
| - // constructor initializer cannot reference "this"
|
| - if (node.getAncestor((node) => node is ConstructorInitializer) != null) {
|
| - return true;
|
| - }
|
| - // field initializer cannot reference "this"
|
| - if (node.getAncestor((node) => node is FieldDeclaration) != null) {
|
| - return true;
|
| - }
|
| - // static method
|
| - MethodDeclaration method = node.getAncestor((node) {
|
| - return node is MethodDeclaration;
|
| - });
|
| - return method != null && method.isStatic;
|
| - }
|
| -
|
| - /**
|
| - * Returns a possible return [Type], may be `null` if cannot be inferred.
|
| - */
|
| - DartType _inferReturnType(MethodInvocation invocation) {
|
| - AstNode parent = invocation.parent;
|
| - // myFunction();
|
| - if (parent is ExpressionStatement) {
|
| - return VoidTypeImpl.instance;
|
| - }
|
| - // return myFunction();
|
| - if (parent is ReturnStatement) {
|
| - ExecutableElement executable = getEnclosingExecutableElement(invocation);
|
| - return executable != null ? executable.returnType : null;
|
| - }
|
| - // int v = myFunction();
|
| - if (parent is VariableDeclaration) {
|
| - VariableDeclaration variableDeclaration = parent;
|
| - if (variableDeclaration.initializer == invocation) {
|
| - VariableElement variableElement = variableDeclaration.element;
|
| - if (variableElement != null) {
|
| - return variableElement.type;
|
| - }
|
| - }
|
| - }
|
| - // v = myFunction();
|
| - if (parent is AssignmentExpression) {
|
| - AssignmentExpression assignment = parent;
|
| - if (assignment.rightHandSide == invocation) {
|
| - if (assignment.operator.type == TokenType.EQ) {
|
| - // v = myFunction();
|
| - Expression lhs = assignment.leftHandSide;
|
| - if (lhs != null) {
|
| - return lhs.bestType;
|
| - }
|
| - } else {
|
| - // v += myFunction();
|
| - MethodElement method = assignment.bestElement;
|
| - if (method != null) {
|
| - List<ParameterElement> parameters = method.parameters;
|
| - if (parameters.length == 1) {
|
| - return parameters[0].type;
|
| - }
|
| - }
|
| - }
|
| - }
|
| - }
|
| - // v + myFunction();
|
| - if (parent is BinaryExpression) {
|
| - BinaryExpression binary = parent;
|
| - MethodElement method = binary.bestElement;
|
| - if (method != null) {
|
| - if (binary.rightOperand == invocation) {
|
| - List<ParameterElement> parameters = method.parameters;
|
| - return parameters.length == 1 ? parameters[0].type : null;
|
| - }
|
| - }
|
| - }
|
| - // foo( myFunction() );
|
| - if (parent is ArgumentList) {
|
| - ParameterElement parameter = invocation.bestParameterElement;
|
| - return parameter != null ? parameter.type : null;
|
| - }
|
| - // bool
|
| - {
|
| - // assert( myFunction() );
|
| - if (parent is AssertStatement) {
|
| - AssertStatement statement = parent;
|
| - if (statement.condition == invocation) {
|
| - return coreTypeBool;
|
| - }
|
| - }
|
| - // if ( myFunction() ) {}
|
| - if (parent is IfStatement) {
|
| - IfStatement statement = parent;
|
| - if (statement.condition == invocation) {
|
| - return coreTypeBool;
|
| - }
|
| - }
|
| - // while ( myFunction() ) {}
|
| - if (parent is WhileStatement) {
|
| - WhileStatement statement = parent;
|
| - if (statement.condition == invocation) {
|
| - return coreTypeBool;
|
| - }
|
| - }
|
| - // do {} while ( myFunction() );
|
| - if (parent is DoStatement) {
|
| - DoStatement statement = parent;
|
| - if (statement.condition == invocation) {
|
| - return coreTypeBool;
|
| - }
|
| - }
|
| - // !myFunction()
|
| - if (parent is PrefixExpression) {
|
| - PrefixExpression prefixExpression = parent;
|
| - if (prefixExpression.operator.type == TokenType.BANG) {
|
| - return coreTypeBool;
|
| - }
|
| - }
|
| - // binary expression '&&' or '||'
|
| - if (parent is BinaryExpression) {
|
| - BinaryExpression binaryExpression = parent;
|
| - TokenType operatorType = binaryExpression.operator.type;
|
| - if (operatorType == TokenType.AMPERSAND_AMPERSAND ||
|
| - operatorType == TokenType.BAR_BAR) {
|
| - return coreTypeBool;
|
| - }
|
| - }
|
| - }
|
| - // we don't know
|
| - return null;
|
| - }
|
| -
|
| - /**
|
| - * Inserts the given [SourceBuilder] at its offset.
|
| - */
|
| - void _insertBuilder(SourceBuilder builder) {
|
| - String text = builder.toString();
|
| - _addInsertEdit(builder.offset, text);
|
| - // add linked positions
|
| - builder.linkedPositionGroups.forEach((LinkedEditGroup group) {
|
| - LinkedEditGroup fixGroup = _getLinkedPosition(group.id);
|
| - group.positions.forEach((Position position) {
|
| - fixGroup.addPosition(position, group.length);
|
| - });
|
| - group.suggestions.forEach((LinkedEditSuggestion suggestion) {
|
| - fixGroup.addSuggestion(suggestion);
|
| - });
|
| - });
|
| - }
|
| -
|
| -// void _addLinkedPositionProposal(String group,
|
| -// LinkedPositionProposal proposal) {
|
| -// List<LinkedPositionProposal> nodeProposals = linkedPositionProposals[group];
|
| -// if (nodeProposals == null) {
|
| -// nodeProposals = <LinkedPositionProposal>[];
|
| -// linkedPositionProposals[group] = nodeProposals;
|
| -// }
|
| -// nodeProposals.add(proposal);
|
| -// }
|
| -
|
| -// /**
|
| -// * Returns `true` if the given [ClassMember] is a part of a static method or
|
| -// * a field initializer.
|
| -// */
|
| -// bool _inStaticMemberContext2(ClassMember member) {
|
| -// if (member is MethodDeclaration) {
|
| -// return member.isStatic;
|
| -// }
|
| -// // field initializer cannot reference "this"
|
| -// if (member is FieldDeclaration) {
|
| -// return true;
|
| -// }
|
| -// return false;
|
| -// }
|
| -
|
| - _ConstructorLocation
|
| - _prepareNewConstructorLocation(ClassDeclaration classDeclaration) {
|
| - List<ClassMember> members = classDeclaration.members;
|
| - // find the last field/constructor
|
| - ClassMember lastFieldOrConstructor = null;
|
| - for (ClassMember member in members) {
|
| - if (member is FieldDeclaration || member is ConstructorDeclaration) {
|
| - lastFieldOrConstructor = member;
|
| - } else {
|
| - break;
|
| - }
|
| - }
|
| - // after the field/constructor
|
| - if (lastFieldOrConstructor != null) {
|
| - return new _ConstructorLocation(
|
| - "${eol}${eol}",
|
| - lastFieldOrConstructor.end,
|
| - "");
|
| - }
|
| - // at the beginning of the class
|
| - String suffix = members.isEmpty ? "" : eol;
|
| - return new _ConstructorLocation(
|
| - eol,
|
| - classDeclaration.leftBracket.end,
|
| - suffix);
|
| - }
|
| -
|
| - /**
|
| - * Removes any [ParenthesizedExpression] enclosing [expr].
|
| - *
|
| - * [exprPrecedence] - the effective precedence of [expr].
|
| - */
|
| - void _removeEnclosingParentheses(Expression expr, int exprPrecedence) {
|
| - while (expr.parent is ParenthesizedExpression) {
|
| - ParenthesizedExpression parenthesized =
|
| - expr.parent as ParenthesizedExpression;
|
| - if (getExpressionParentPrecedence(parenthesized) > exprPrecedence) {
|
| - break;
|
| - }
|
| - _addRemoveEdit(rf.rangeToken(parenthesized.leftParenthesis));
|
| - _addRemoveEdit(rf.rangeToken(parenthesized.rightParenthesis));
|
| - expr = parenthesized;
|
| - }
|
| - }
|
| -
|
| - void _updateFinderWithClassMembers(_ClosestElementFinder finder,
|
| - ClassElement clazz) {
|
| - if (clazz != null) {
|
| - List<Element> members = getMembers(clazz);
|
| - finder._updateList(members);
|
| - }
|
| - }
|
| -
|
| - static void _addSuperTypeProposals(SourceBuilder sb,
|
| - Set<DartType> alreadyAdded, DartType type) {
|
| - if (type != null &&
|
| - !alreadyAdded.contains(type) &&
|
| - type.element is ClassElement) {
|
| - alreadyAdded.add(type);
|
| - ClassElement element = type.element as ClassElement;
|
| - sb.addSuggestion(LinkedEditSuggestionKind.TYPE, element.name);
|
| - _addSuperTypeProposals(sb, alreadyAdded, element.supertype);
|
| - for (InterfaceType interfaceType in element.interfaces) {
|
| - _addSuperTypeProposals(sb, alreadyAdded, interfaceType);
|
| - }
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Attempts to convert the given absolute path into a "package" URI.
|
| - *
|
| - * [context] - the [AnalysisContext] to work in.
|
| - * [path] - the absolute path, not `null`.
|
| - *
|
| - * Returns the "package" URI, may be `null`.
|
| - */
|
| - static String _findPackageUri(AnalysisContext context, String path) {
|
| -// Source fileSource = new FileBasedSource.con1(path);
|
| - Source fileSource = new NonExistingSource(path, UriKind.FILE_URI);
|
| - Uri uri = context.sourceFactory.restoreUri(fileSource);
|
| - if (uri == null) {
|
| - return null;
|
| - }
|
| - return uri.toString();
|
| - }
|
| -
|
| - /**
|
| - * @return the suggestions for given [Type] and [DartExpression], not empty.
|
| - */
|
| - static List<String> _getArgumentNameSuggestions(Set<String> excluded,
|
| - DartType type, Expression expression, int index) {
|
| - List<String> suggestions =
|
| - getVariableNameSuggestionsForExpression(type, expression, excluded);
|
| - if (suggestions.length != 0) {
|
| - return suggestions;
|
| - }
|
| - return <String>["arg${index}"];
|
| - }
|
| -
|
| - /**
|
| - * Returns `true` if [node] is a type name.
|
| - */
|
| - static bool _mayBeTypeIdentifier(AstNode node) {
|
| - if (node is SimpleIdentifier) {
|
| - AstNode parent = node.parent;
|
| - if (parent is TypeName) {
|
| - return true;
|
| - }
|
| - if (parent is MethodInvocation) {
|
| - return parent.realTarget == node;
|
| - }
|
| - if (parent is PrefixedIdentifier) {
|
| - return parent.prefix == node;
|
| - }
|
| - }
|
| - return false;
|
| - }
|
| -}
|
| -
|
| -/**
|
| - * Helper for finding [Element] with name closest to the given.
|
| - */
|
| -class _ClosestElementFinder {
|
| - final String _targetName;
|
| - final Predicate<Element> _predicate;
|
| -
|
| - Element _element = null;
|
| - int _distance;
|
| -
|
| - _ClosestElementFinder(this._targetName, this._predicate, this._distance);
|
| -
|
| - void _update(Element element) {
|
| - if (_predicate(element)) {
|
| - int memberDistance = levenshtein(element.name, _targetName, _distance);
|
| - if (memberDistance < _distance) {
|
| - _element = element;
|
| - _distance = memberDistance;
|
| - }
|
| - }
|
| - }
|
| -
|
| - void _updateList(Iterable<Element> elements) {
|
| - for (Element element in elements) {
|
| - _update(element);
|
| - }
|
| - }
|
| -}
|
| -
|
| -/**
|
| - * Describes the location for a newly created [ConstructorDeclaration].
|
| - */
|
| -class _ConstructorLocation {
|
| - final String _prefix;
|
| - final int _offset;
|
| - final String _suffix;
|
| -
|
| - _ConstructorLocation(this._prefix, this._offset, this._suffix);
|
| -}
|
|
|