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 |
index fe24a149c11e9aefea5e54efb1de33a92b2bc858..0f9eb9495fcb4ff59262eb7aa7ef22b908283f62 100644 |
--- a/pkg/analysis_services/lib/src/correction/fix.dart |
+++ b/pkg/analysis_services/lib/src/correction/fix.dart |
@@ -13,12 +13,14 @@ import 'package:analysis_services/search/search_engine.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/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/source.dart'; |
import 'package:analyzer/src/generated/utilities_dart.dart'; |
@@ -28,13 +30,17 @@ import 'package:analyzer/src/generated/utilities_dart.dart'; |
*/ |
class FixProcessor { |
final SearchEngine searchEngine; |
+ final Source source; |
final String file; |
final CompilationUnit unit; |
final AnalysisError error; |
+ CompilationUnitElement unitElement; |
+ LibraryElement unitLibraryElement; |
final List<Edit> edits = <Edit>[]; |
final Map<String, LinkedPositionGroup> linkedPositionGroups = <String, |
LinkedPositionGroup>{}; |
+ Position endPosition = null; |
final List<Fix> fixes = <Fix>[]; |
CorrectionUtils utils; |
@@ -45,7 +51,18 @@ class FixProcessor { |
AstNode coveredNode; |
- FixProcessor(this.searchEngine, this.file, this.unit, this.error); |
+ FixProcessor(this.searchEngine, this.source, this.file, this.unit, this.error) |
+ { |
+ unitElement = unit.element; |
+ unitLibraryElement = unitElement.library; |
+ } |
+ |
+ 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); |
@@ -69,11 +86,10 @@ class FixProcessor { |
CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT) { |
_addFix_createConstructorSuperExplicit(); |
} |
-// if (identical( |
-// errorCode, |
-// CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT)) { |
-// _addFix_createConstructorSuperImplicit(); |
-// } |
+ if (errorCode == |
+ CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT) { |
+ _addFix_createConstructorSuperImplicit(); |
+ } |
if (errorCode == |
CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT) { |
_addFix_createConstructorSuperExplicit(); |
@@ -139,11 +155,11 @@ class FixProcessor { |
_addFix_createClass(); |
_addFix_undefinedClass_useSimilar(); |
} |
-// if (identical(errorCode, StaticWarningCode.UNDEFINED_IDENTIFIER)) { |
-// _addFix_createFunction_forFunctionType(); |
-// _addFix_importLibrary_withType(); |
-// _addFix_importLibrary_withTopLevelVariable(); |
-// } |
+ 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(); |
@@ -156,15 +172,15 @@ class FixProcessor { |
// _addFix_undefinedFunction_useSimilar(); |
// _addFix_undefinedFunction_create(); |
// } |
-// if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_GETTER)) { |
-// _addFix_createFunction_forFunctionType(); |
-// } |
-// if (identical(errorCode, HintCode.UNDEFINED_METHOD) || |
-// identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) { |
-// _addFix_undefinedMethod_useSimilar(); |
-// _addFix_undefinedMethod_create(); |
-// _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; |
} |
@@ -181,11 +197,17 @@ class FixProcessor { |
change.add(fileEdit); |
linkedPositionGroups.values.forEach( |
(group) => change.addLinkedPositionGroup(group)); |
+ change.endPosition = endPosition; |
// add Fix |
Fix fix = new Fix(kind, change); |
fixes.add(fix); |
+ // clear |
+ edits.clear(); |
+ linkedPositionGroups.clear(); |
+ endPosition = null; |
} |
+ |
void _addFix_addPackageDependency() { |
// TODO(scheglov) implement |
// if (node is SimpleStringLiteral && node.parent is NamespaceDirective) { |
@@ -208,18 +230,17 @@ class FixProcessor { |
// } |
} |
+ |
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 |
- String eol = utils.endOfLine; |
CompilationUnitMember enclosingMember = |
node.getAncestor((node) => node is CompilationUnitMember); |
int offset = enclosingMember.end; |
@@ -250,7 +271,6 @@ class FixProcessor { |
} |
} |
- |
void _addFix_createConstructorSuperExplicit() { |
ConstructorDeclaration targetConstructor = |
node.parent as ConstructorDeclaration; |
@@ -319,79 +339,75 @@ class FixProcessor { |
} |
void _addFix_createConstructorSuperImplicit() { |
- // TODO(scheglov) implement |
-// 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 |
-// JavaStringBuilder parametersBuffer = new JavaStringBuilder(); |
-// JavaStringBuilder argumentsBuffer = new JavaStringBuilder(); |
-// 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 |
-// String eol = utils.endOfLine; |
-// QuickFixProcessorImpl_NewConstructorLocation targetLocation = |
-// _prepareNewConstructorLocation(targetClassNode, eol); |
-// SourceBuilder sb = new SourceBuilder.con1(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); |
-// } |
-// _addInsertEdit3(sb); |
-// // add proposal |
-// String proposalName = _getConstructorProposalName(superConstructor); |
-// _addFix( |
-// FixKind.CREATE_CONSTRUCTOR_SUPER, |
-// [proposalName]); |
-// } |
+ 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() { |
@@ -428,8 +444,6 @@ class FixProcessor { |
if (instanceCreation == null) { |
return; |
} |
- // prepare environment |
- String eol = utils.endOfLine; |
// prepare target |
DartType targetType = typeName.type; |
if (targetType is! InterfaceType) { |
@@ -438,8 +452,8 @@ class FixProcessor { |
ClassElement targetElement = targetType.element as ClassElement; |
String targetFile = targetElement.source.fullName; |
ClassDeclaration targetClass = targetElement.node; |
- QuickFixProcessorImpl_NewConstructorLocation targetLocation = |
- _prepareNewConstructorLocation(targetClass, eol); |
+ _ConstructorLocation targetLocation = |
+ _prepareNewConstructorLocation(targetClass); |
// build method source |
SourceBuilder sb = new SourceBuilder(targetFile, targetLocation._offset); |
{ |
@@ -485,8 +499,6 @@ class FixProcessor { |
if (instanceCreation == null) { |
return; |
} |
- // prepare environment |
- String eol = utils.endOfLine; |
// prepare target interface type |
DartType targetType = constructorName.type.type; |
if (targetType is! InterfaceType) { |
@@ -495,8 +507,8 @@ class FixProcessor { |
ClassElement targetElement = targetType.element as ClassElement; |
String targetFile = targetElement.source.fullName; |
ClassDeclaration targetClass = targetElement.node; |
- QuickFixProcessorImpl_NewConstructorLocation targetLocation = |
- _prepareNewConstructorLocation(targetClass, eol); |
+ _ConstructorLocation targetLocation = |
+ _prepareNewConstructorLocation(targetClass); |
// build method source |
SourceBuilder sb = new SourceBuilder(targetFile, targetLocation._offset); |
{ |
@@ -527,173 +539,156 @@ class FixProcessor { |
} |
void _addFix_createFunction_forFunctionType() { |
- // TODO(scheglov) implement |
-// if (node is SimpleIdentifier) { |
-// SimpleIdentifier nameNode = node as SimpleIdentifier; |
-// // prepare argument expression (to get parameter) |
-// ClassElement targetElement; |
-// Expression argument; |
-// { |
-// Expression target = CorrectionUtils.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); |
-// } |
-// } |
+ 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) { |
- // TODO(scheglov) implement |
-// // sort by name |
-// missingOverrides.sort( |
-// (Element firstElement, Element secondElement) => |
-// ObjectUtils.compare(firstElement.displayName, secondElement.displayName)); |
-// // add elements |
-// ClassDeclaration targetClass = node.parent as ClassDeclaration; |
-// bool isFirst = true; |
-// for (ExecutableElement missingOverride in missingOverrides) { |
-// _addFix_createMissingOverrides_single( |
-// targetClass, |
-// missingOverride, |
-// isFirst); |
-// isFirst = false; |
-// } |
-// // add proposal |
-// _addFix( |
-// FixKind.CREATE_MISSING_OVERRIDES, |
-// [missingOverrides.length]); |
+ // sort by name |
+ missingOverrides.sort((Element firstElement, Element secondElement) { |
+ return compareStrings( |
+ firstElement.displayName, |
+ secondElement.displayName); |
+ }); |
+ // TODO |
+ 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 |
+ endPosition = new Position(file, insertOffset, 0); |
+ _insertBuilder(sb); |
+ _addFix(FixKind.CREATE_MISSING_OVERRIDES, [missingOverrides.length]); |
} |
- void _addFix_createMissingOverrides_single(ClassDeclaration targetClass, |
- ExecutableElement missingOverride, bool isFirst) { |
- // TODO(scheglov) implement |
-// // prepare environment |
-// String eol = utils.endOfLine; |
-// String prefix = utils.getIndent(1); |
-// String prefix2 = utils.getIndent(2); |
-// int insertOffset = targetClass.end - 1; |
-// // prepare source |
-// JavaStringBuilder sb = new JavaStringBuilder(); |
-// // may be empty line |
-// if (!isFirst || !targetClass.members.isEmpty) { |
-// sb.append(eol); |
-// } |
-// // 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 if (isMethod || isSetter) { |
-// List<ParameterElement> parameters = missingOverride.parameters; |
-// _appendParameters(sb, parameters); |
-// sb.append(" {"); |
-// // TO-DO |
-// sb.append(eol); |
-// sb.append(prefix2); |
-// if (isMethod) { |
-// sb.append("// TODO: implement ${missingOverride.displayName}"); |
-// } else { |
-// sb.append("// TODO: implement ${missingOverride.displayName}"); |
-// } |
-// sb.append(eol); |
-// // close method |
-// sb.append(prefix); |
-// sb.append("}"); |
-// } |
-// sb.append(eol); |
-// // done |
-// _addInsertEdit(insertOffset, sb.toString()); |
-// // maybe set end range |
-// if (_endRange == null) { |
-// _endRange = SourceRangeFactory.rangeStartLength(insertOffset, 0); |
-// } |
+ 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() { |
- // TODO(scheglov) implement |
-// ClassDeclaration targetClass = node.parent as ClassDeclaration; |
-// // prepare environment |
-// String eol = utils.endOfLine; |
-// String prefix = utils.getIndent(1); |
-// int insertOffset = targetClass.end - 1; |
-// // prepare source |
-// SourceBuilder sb = new SourceBuilder.con1(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 |
-// _addInsertEdit3(sb); |
-// _endRange = SourceRangeFactory.rangeStartLength(insertOffset, 0); |
-// // add proposal |
-// _addFix(FixKind.CREATE_NO_SUCH_METHOD, []); |
+ 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); |
+ endPosition = new Position(file, insertOffset, 0); |
+ // add proposal |
+ _addFix(FixKind.CREATE_NO_SUCH_METHOD, []); |
} |
+ |
void _addFix_createPart() { |
// TODO(scheglov) implement |
// if (node is SimpleStringLiteral && node.parent is PartDirective) { |
@@ -712,7 +707,6 @@ class FixProcessor { |
// // prepare new source |
// String source; |
// { |
-// String eol = utils.endOfLine; |
// String libraryName = _unitLibraryElement.displayName; |
// source = "part of ${libraryName};${eol}${eol}"; |
// } |
@@ -737,7 +731,6 @@ class FixProcessor { |
// String prefix; |
// String suffix; |
// { |
-// String eol = utils.endOfLine; |
// // if no directives |
// prefix = ""; |
// suffix = eol; |
@@ -1077,7 +1070,6 @@ class FixProcessor { |
// return; |
// } |
// // prepare environment |
-// String eol = utils.endOfLine; |
// int insertOffset; |
// String sourcePrefix; |
// AstNode enclosingMember = |
@@ -1151,213 +1143,80 @@ class FixProcessor { |
} |
void _addFix_undefinedMethod_create() { |
- // TODO(scheglov) implement |
-// if (node is SimpleIdentifier && node.parent is MethodInvocation) { |
-// String name = (node as SimpleIdentifier).name; |
-// MethodInvocation invocation = node.parent as MethodInvocation; |
-// // prepare environment |
-// String eol = utils.endOfLine; |
-// 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 = _inStaticMemberContext2(enclosingMember); |
-// prefix = utils.getNodePrefix(enclosingMember); |
-// insertOffset = enclosingMember.end; |
-// sourcePrefix = "${eol}${prefix}${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 = "${prefix}${eol}"; |
-// } |
-// sourceSuffix = eol; |
-// } |
-// // build method source |
-// SourceBuilder sb = new SourceBuilder.con1(insertOffset); |
-// { |
-// sb.append(sourcePrefix); |
-// sb.append(prefix); |
-// // may be "static" |
-// if (staticModifier) { |
-// sb.append("static "); |
-// } |
-// // may be return type |
-// { |
-// DartType type = |
-// _addFix_undefinedMethod_create_getReturnType(invocation); |
-// if (type != null) { |
-// String typeSource = utils.getTypeSource2(type); |
-// if (typeSource != "dynamic") { |
-// sb.startPosition("RETURN_TYPE"); |
-// sb.append(typeSource); |
-// sb.endPosition(); |
-// sb.append(" "); |
-// } |
-// } |
-// } |
-// // 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 |
-// _addInsertEdit(insertOffset, sb.toString()); |
-// // add linked positions |
-// if (targetSource == _source) { |
-// _addLinkedPosition("NAME", sb, SourceRangeFactory.rangeNode(node)); |
-// } |
-// _addLinkedPositions(sb); |
-// // add proposal |
-// _addUnitCorrectionProposal2( |
-// targetSource, |
-// FixKind.CREATE_METHOD, |
-// [name]); |
-// } |
- } |
- |
- /** |
- * @return the possible return [Type], may be <code>null</code> if can not be identified. |
- */ |
- DartType |
- _addFix_undefinedMethod_create_getReturnType(MethodInvocation invocation) { |
- // TODO(scheglov) implement |
-// AstNode parent = invocation.parent; |
-// // myFunction(); |
-// if (parent is ExpressionStatement) { |
-// return VoidTypeImpl.instance; |
-// } |
-// // return myFunction(); |
-// if (parent is ReturnStatement) { |
-// ExecutableElement executable = |
-// CorrectionUtils.getEnclosingExecutableElement(invocation); |
-// return executable != null ? executable.returnType : null; |
-// } |
-// // int v = myFunction(); |
-// if (parent is VariableDeclaration) { |
-// VariableDeclaration variableDeclaration = parent; |
-// if (identical(variableDeclaration.initializer, invocation)) { |
-// VariableElement variableElement = variableDeclaration.element; |
-// if (variableElement != null) { |
-// return variableElement.type; |
-// } |
-// } |
-// } |
-// // v = myFunction(); |
-// if (parent is AssignmentExpression) { |
-// AssignmentExpression assignment = parent; |
-// if (identical(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 (identical(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 (identical(statement.condition, invocation)) { |
-// return coreTypeBool; |
-// } |
-// } |
-// // if ( myFunction() ) {} |
-// if (parent is IfStatement) { |
-// IfStatement statement = parent; |
-// if (identical(statement.condition, invocation)) { |
-// return coreTypeBool; |
-// } |
-// } |
-// // while ( myFunction() ) {} |
-// if (parent is WhileStatement) { |
-// WhileStatement statement = parent; |
-// if (identical(statement.condition, invocation)) { |
-// return coreTypeBool; |
-// } |
-// } |
-// // do {} while ( myFunction() ); |
-// if (parent is DoStatement) { |
-// DoStatement statement = parent; |
-// if (identical(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; |
+ 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}${prefix}${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, |
@@ -1517,6 +1376,143 @@ class FixProcessor { |
} |
/** |
+ * 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) { |
@@ -1531,20 +1527,20 @@ class FixProcessor { |
edits.add(edit); |
} |
- void _appendParameterSource(StringBuffer sb, DartType type, String name) { |
+ void _appendParameterSource(SourceBuilder sb, DartType type, String name) { |
String parameterSource = utils.getParameterSource(type, name); |
- sb.write(parameterSource); |
+ sb.append(parameterSource); |
} |
- void _appendParameters(StringBuffer sb, List<ParameterElement> parameters, |
+ void _appendParameters(SourceBuilder sb, List<ParameterElement> parameters, |
Map<ParameterElement, String> defaultValueMap) { |
- sb.write("("); |
+ sb.append("("); |
bool firstParameter = true; |
bool sawNamed = false; |
bool sawPositional = false; |
for (ParameterElement parameter in parameters) { |
if (!firstParameter) { |
- sb.write(", "); |
+ sb.append(", "); |
} else { |
firstParameter = false; |
} |
@@ -1552,13 +1548,13 @@ class FixProcessor { |
ParameterKind parameterKind = parameter.parameterKind; |
if (parameterKind == ParameterKind.NAMED) { |
if (!sawNamed) { |
- sb.write("{"); |
+ sb.append("{"); |
sawNamed = true; |
} |
} |
if (parameterKind == ParameterKind.POSITIONAL) { |
if (!sawPositional) { |
- sb.write("["); |
+ sb.append("["); |
sawPositional = true; |
} |
} |
@@ -1569,45 +1565,49 @@ class FixProcessor { |
String defaultSource = defaultValueMap[parameter]; |
if (defaultSource != null) { |
if (sawPositional) { |
- sb.write(" = "); |
+ sb.append(" = "); |
} else { |
- sb.write(": "); |
+ sb.append(": "); |
} |
- sb.write(defaultSource); |
+ sb.append(defaultSource); |
} |
} |
} |
// close parameters |
if (sawNamed) { |
- sb.write("}"); |
+ sb.append("}"); |
} |
if (sawPositional) { |
- sb.write("]"); |
+ sb.append("]"); |
} |
- sb.write(")"); |
+ sb.append(")"); |
} |
-// void _addLinkedPositionProposal(String group, |
-// LinkedPositionProposal proposal) { |
-// List<LinkedPositionProposal> nodeProposals = linkedPositionProposals[group]; |
-// if (nodeProposals == null) { |
-// nodeProposals = <LinkedPositionProposal>[]; |
-// linkedPositionProposals[group] = nodeProposals; |
-// } |
-// nodeProposals.add(proposal); |
-// } |
+ 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) { |
- StringBuffer proposalNameBuffer = new StringBuffer(); |
- proposalNameBuffer.write("super"); |
+ SourceBuilder proposalNameBuffer = new SourceBuilder.buffer(); |
+ proposalNameBuffer.append("super"); |
// may be named |
String constructorName = constructor.displayName; |
if (!constructorName.isEmpty) { |
- proposalNameBuffer.write("."); |
- proposalNameBuffer.write(constructorName); |
+ proposalNameBuffer.append("."); |
+ proposalNameBuffer.append(constructorName); |
} |
// parameters |
_appendParameters(proposalNameBuffer, constructor.parameters, null); |
@@ -1616,6 +1616,201 @@ class FixProcessor { |
} |
/** |
+ * 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 `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 (identical(variableDeclaration.initializer, invocation)) { |
+ VariableElement variableElement = variableDeclaration.element; |
+ if (variableElement != null) { |
+ return variableElement.type; |
+ } |
+ } |
+ } |
+ // v = myFunction(); |
+ if (parent is AssignmentExpression) { |
+ AssignmentExpression assignment = parent; |
+ if (identical(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 (identical(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 (identical(statement.condition, invocation)) { |
+ return coreTypeBool; |
+ } |
+ } |
+ // if ( myFunction() ) {} |
+ if (parent is IfStatement) { |
+ IfStatement statement = parent; |
+ if (identical(statement.condition, invocation)) { |
+ return coreTypeBool; |
+ } |
+ } |
+ // while ( myFunction() ) {} |
+ if (parent is WhileStatement) { |
+ WhileStatement statement = parent; |
+ if (identical(statement.condition, invocation)) { |
+ return coreTypeBool; |
+ } |
+ } |
+ // do {} while ( myFunction() ); |
+ if (parent is DoStatement) { |
+ DoStatement statement = parent; |
+ if (identical(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; |
+ } |
+ |
+// 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; |
+// } |
+ |
+ /** |
* Inserts the given [SourceBuilder] at its offset. |
*/ |
void _insertBuilder(SourceBuilder builder) { |
@@ -1629,8 +1824,8 @@ class FixProcessor { |
}); |
} |
- QuickFixProcessorImpl_NewConstructorLocation |
- _prepareNewConstructorLocation(ClassDeclaration classDeclaration, String eol) { |
+ _ConstructorLocation |
+ _prepareNewConstructorLocation(ClassDeclaration classDeclaration) { |
List<ClassMember> members = classDeclaration.members; |
// find the last field/constructor |
ClassMember lastFieldOrConstructor = null; |
@@ -1643,14 +1838,14 @@ class FixProcessor { |
} |
// after the field/constructor |
if (lastFieldOrConstructor != null) { |
- return new QuickFixProcessorImpl_NewConstructorLocation( |
+ return new _ConstructorLocation( |
"${eol}${eol}", |
lastFieldOrConstructor.end, |
""); |
} |
// at the beginning of the class |
String suffix = members.isEmpty ? "" : eol; |
- return new QuickFixProcessorImpl_NewConstructorLocation( |
+ return new _ConstructorLocation( |
eol, |
classDeclaration.leftBracket.end, |
suffix); |
@@ -1728,11 +1923,10 @@ class FixProcessor { |
* |
* TODO(scheglov) rename |
*/ |
-class QuickFixProcessorImpl_NewConstructorLocation { |
+class _ConstructorLocation { |
final String _prefix; |
final int _offset; |
final String _suffix; |
- QuickFixProcessorImpl_NewConstructorLocation(this._prefix, this._offset, |
- this._suffix); |
+ _ConstructorLocation(this._prefix, this._offset, this._suffix); |
} |