diff --git a/Jakefile.js b/Jakefile.js index 17346e8bc1fc5..33abc52cf0fda 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -151,6 +151,7 @@ var servicesSources = [ "signatureHelp.ts", "symbolDisplay.ts", "transpile.ts", + // Formatting "formatting/formatting.ts", "formatting/formattingContext.ts", "formatting/formattingRequestKind.ts", @@ -166,7 +167,18 @@ var servicesSources = [ "formatting/rulesMap.ts", "formatting/rulesProvider.ts", "formatting/smartIndenter.ts", - "formatting/tokenRange.ts" + "formatting/tokenRange.ts", + // CodeFixes + "codeFixProvider.ts", + "codefixes/fixes.ts", + "codefixes/fixExtendsInterfaceBecomesImplements.ts", + "codefixes/fixClassIncorrectlyImplementsInterface.ts", + "codefixes/fixClassDoesntImplementInheritedAbstractMember.ts", + "codefixes/fixClassSuperMustPrecedeThisAccess.ts", + "codefixes/fixConstructorForDerivedNeedSuperCall.ts", + "codefixes/helpers.ts", + "codefixes/importFixes.ts", + "codefixes/unusedIdentifierFixes.ts" ].map(function (f) { return path.join(servicesDirectory, f); })); diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 26164a528f34b..e90e40967d369 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -79,9 +79,11 @@ namespace ts { getDeclaredTypeOfSymbol, getPropertiesOfType, getPropertyOfType, + getIndexInfoOfType, getSignaturesOfType, getIndexTypeOfType, getBaseTypes, + getTypeFromTypeNode, getReturnTypeOfSignature, getNonNullableType, getSymbolsInScope, @@ -90,6 +92,7 @@ namespace ts { getExportSpecifierLocalTargetSymbol, getTypeAtLocation: getTypeOfNode, getPropertySymbolOfDestructuringAssignment, + signatureToString, typeToString, getSymbolDisplayBuilder, symbolToString, @@ -1344,7 +1347,9 @@ namespace ts { return symbol.parent ? getFullyQualifiedName(symbol.parent) + "." + symbolToString(symbol) : symbolToString(symbol); } - // Resolves a qualified name and any involved aliases + /** + * Resolves a qualified name and any involved aliases. + */ function resolveEntityName(name: EntityNameOrEntityNameExpression, meaning: SymbolFlags, ignoreErrors?: boolean, dontResolveAlias?: boolean, location?: Node): Symbol | undefined { if (nodeIsMissing(name)) { return undefined; @@ -2085,7 +2090,7 @@ namespace ts { return result || types; } - function visibilityToString(flags: ModifierFlags) { + function visibilityToString(flags: ModifierFlags): string | undefined { if (flags === ModifierFlags.Private) { return "private"; } @@ -2463,26 +2468,6 @@ namespace ts { buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Value, SymbolFormatFlags.None, typeFormatFlags); } - function writeIndexSignature(info: IndexInfo, keyword: SyntaxKind) { - if (info) { - if (info.isReadonly) { - writeKeyword(writer, SyntaxKind.ReadonlyKeyword); - writeSpace(writer); - } - writePunctuation(writer, SyntaxKind.OpenBracketToken); - writer.writeParameter(info.declaration ? declarationNameToString(info.declaration.parameters[0].name) : "x"); - writePunctuation(writer, SyntaxKind.ColonToken); - writeSpace(writer); - writeKeyword(writer, keyword); - writePunctuation(writer, SyntaxKind.CloseBracketToken); - writePunctuation(writer, SyntaxKind.ColonToken); - writeSpace(writer); - writeType(info.type, TypeFormatFlags.None); - writePunctuation(writer, SyntaxKind.SemicolonToken); - writer.writeLine(); - } - } - function writePropertyWithModifiers(prop: Symbol) { if (isReadonlySymbol(prop)) { writeKeyword(writer, SyntaxKind.ReadonlyKeyword); @@ -2570,8 +2555,8 @@ namespace ts { writePunctuation(writer, SyntaxKind.SemicolonToken); writer.writeLine(); } - writeIndexSignature(resolved.stringIndexInfo, SyntaxKind.StringKeyword); - writeIndexSignature(resolved.numberIndexInfo, SyntaxKind.NumberKeyword); + buildIndexSignatureDisplay(resolved.stringIndexInfo, writer, IndexKind.String, enclosingDeclaration, globalFlags, symbolStack); + buildIndexSignatureDisplay(resolved.numberIndexInfo, writer, IndexKind.Number, enclosingDeclaration, globalFlags, symbolStack); for (const p of resolved.properties) { const t = getTypeOfSymbol(p); if (p.flags & (SymbolFlags.Function | SymbolFlags.Method) && !getPropertiesOfObjectType(t).length) { @@ -2762,6 +2747,11 @@ namespace ts { } function buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) { + const returnType = getReturnTypeOfSignature(signature); + if (flags & TypeFormatFlags.SuppressAnyReturnType && isTypeAny(returnType)) { + return; + } + if (flags & TypeFormatFlags.WriteArrowStyleSignature) { writeSpace(writer); writePunctuation(writer, SyntaxKind.EqualsGreaterThanToken); @@ -2775,7 +2765,6 @@ namespace ts { buildTypePredicateDisplay(signature.typePredicate, writer, enclosingDeclaration, flags, symbolStack); } else { - const returnType = getReturnTypeOfSignature(signature); buildTypeDisplay(returnType, writer, enclosingDeclaration, flags, symbolStack); } } @@ -2800,6 +2789,34 @@ namespace ts { buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, symbolStack); } + function buildIndexSignatureDisplay(info: IndexInfo, writer: SymbolWriter, kind: IndexKind, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]) { + if (info) { + if (info.isReadonly) { + writeKeyword(writer, SyntaxKind.ReadonlyKeyword); + writeSpace(writer); + } + writePunctuation(writer, SyntaxKind.OpenBracketToken); + writer.writeParameter(info.declaration ? declarationNameToString(info.declaration.parameters[0].name) : "x"); + writePunctuation(writer, SyntaxKind.ColonToken); + writeSpace(writer); + switch (kind) { + case IndexKind.Number: + writeKeyword(writer, SyntaxKind.NumberKeyword); + break; + case IndexKind.String: + writeKeyword(writer, SyntaxKind.StringKeyword); + break; + } + + writePunctuation(writer, SyntaxKind.CloseBracketToken); + writePunctuation(writer, SyntaxKind.ColonToken); + writeSpace(writer); + buildTypeDisplay(info.type, writer, enclosingDeclaration, globalFlags, symbolStack); + writePunctuation(writer, SyntaxKind.SemicolonToken); + writer.writeLine(); + } + } + return _displayBuilder || (_displayBuilder = { buildSymbolDisplay, buildTypeDisplay, @@ -2810,6 +2827,7 @@ namespace ts { buildDisplayForTypeParametersAndDelimiters, buildTypeParameterDisplayFromSymbol, buildSignatureDisplay, + buildIndexSignatureDisplay, buildReturnTypeDisplay }); } @@ -3765,11 +3783,13 @@ namespace ts { return signatures; } - // The base constructor of a class can resolve to - // undefinedType if the class has no extends clause, - // unknownType if an error occurred during resolution of the extends expression, - // nullType if the extends expression is the null value, or - // an object type with at least one construct signature. + /** + * The base constructor of a class can resolve to + * * undefinedType if the class has no extends clause, + * * unknownType if an error occurred during resolution of the extends expression, + * * nullType if the extends expression is the null value, or + * * an object type with at least one construct signature. + */ function getBaseConstructorTypeOfClass(type: InterfaceType): Type { if (!type.resolvedBaseConstructorType) { const baseTypeNode = getBaseTypeNodeOfClass(type); @@ -4250,7 +4270,7 @@ namespace ts { return type; } - function getTypeWithThisArgument(type: Type, thisArgument?: Type) { + function getTypeWithThisArgument(type: Type, thisArgument?: Type): Type { if (getObjectFlags(type) & ObjectFlags.Reference) { return createTypeReference((type).target, concatenate((type).typeArguments, [thisArgument || (type).target.thisType])); @@ -4476,6 +4496,9 @@ namespace ts { setStructuredTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); } + /** + * Converts an AnonymousType to a ResolvedType. + */ function resolveAnonymousTypeMembers(type: AnonymousType) { const symbol = type.symbol; if (type.target) { @@ -7238,10 +7261,12 @@ namespace ts { return false; } - // Compare two types and return - // Ternary.True if they are related with no assumptions, - // Ternary.Maybe if they are related with assumptions of other relationships, or - // Ternary.False if they are not related. + /** + * Compare two types and return + * * Ternary.True if they are related with no assumptions, + * * Ternary.Maybe if they are related with assumptions of other relationships, or + * * Ternary.False if they are not related. + */ function isRelatedTo(source: Type, target: Type, reportErrors?: boolean, headMessage?: DiagnosticMessage): Ternary { let result: Ternary; if (source.flags & TypeFlags.StringOrNumberLiteral && source.flags & TypeFlags.FreshLiteral) { diff --git a/src/compiler/core.ts b/src/compiler/core.ts index ceff135957940..4c402418f4973 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1060,7 +1060,7 @@ namespace ts { } } - function formatStringFromArgs(text: string, args: { [index: number]: string; }, baseIndex?: number): string { + export function formatStringFromArgs(text: string, args: { [index: number]: string; }, baseIndex?: number): string { baseIndex = baseIndex || 0; return text.replace(/{(\d+)}/g, (_match, index?) => args[+index + baseIndex]); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index b59921c29489b..a9faae5004e3a 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3195,23 +3195,19 @@ "category": "Message", "code": 90002 }, - "Change 'extends' to 'implements'": { + "Change 'extends' to 'implements'.": { "category": "Message", "code": 90003 }, - "Remove unused identifiers": { + "Remove unused identifiers.": { "category": "Message", "code": 90004 }, - "Implement interface on reference": { - "category": "Message", - "code": 90005 - }, - "Implement interface on class": { + "Implement interface '{0}'.": { "category": "Message", "code": 90006 }, - "Implement inherited abstract class": { + "Implement inherited abstract class.": { "category": "Message", "code": 90007 }, diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 1ee59149b2c5c..e035b4d39191b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -640,9 +640,9 @@ namespace ts { export interface ParameterDeclaration extends Declaration { kind: SyntaxKind.Parameter; - dotDotDotToken?: DotDotDotToken; // Present on rest parameter + dotDotDotToken?: DotDotDotToken; // Present on rest parameter name: BindingName; // Declared parameter name - questionToken?: QuestionToken; // Present on optional parameter + questionToken?: QuestionToken; // Present on optional parameter type?: TypeNode; // Optional type annotation initializer?: Expression; // Optional initializer } @@ -658,14 +658,14 @@ namespace ts { export interface PropertySignature extends TypeElement { kind: SyntaxKind.PropertySignature | SyntaxKind.JSDocRecordMember; name: PropertyName; // Declared property name - questionToken?: QuestionToken; // Present on optional property + questionToken?: QuestionToken; // Present on optional property type?: TypeNode; // Optional type annotation initializer?: Expression; // Optional initializer } export interface PropertyDeclaration extends ClassElement { kind: SyntaxKind.PropertyDeclaration; - questionToken?: QuestionToken; // Present for use with reporting a grammar error + questionToken?: QuestionToken; // Present for use with reporting a grammar error name: PropertyName; type?: TypeNode; initializer?: Expression; // Optional initializer @@ -2335,6 +2335,7 @@ namespace ts { getDeclaredTypeOfSymbol(symbol: Symbol): Type; getPropertiesOfType(type: Type): Symbol[]; getPropertyOfType(type: Type, propertyName: string): Symbol; + getIndexInfoOfType(type: Type, kind: IndexKind): IndexInfo; getSignaturesOfType(type: Type, kind: SignatureKind): Signature[]; getIndexTypeOfType(type: Type, kind: IndexKind): Type; getBaseTypes(type: InterfaceType): ObjectType[]; @@ -2348,6 +2349,8 @@ namespace ts { getExportSpecifierLocalTargetSymbol(location: ExportSpecifier): Symbol; getPropertySymbolOfDestructuringAssignment(location: Identifier): Symbol; getTypeAtLocation(node: Node): Type; + getTypeFromTypeNode(node: TypeNode): Type; + signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string; typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string; getSymbolDisplayBuilder(): SymbolDisplayBuilder; @@ -2391,6 +2394,7 @@ namespace ts { buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void; buildSignatureDisplay(signatures: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): void; + buildIndexSignatureDisplay(info: IndexInfo, writer: SymbolWriter, kind: IndexKind, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]): void; buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildTypePredicateDisplay(predicate: TypePredicate, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; @@ -2434,6 +2438,7 @@ namespace ts { InFirstTypeArgument = 0x00000100, // Writing first type argument of the instantiated type InTypeAlias = 0x00000200, // Writing type in type alias declaration UseTypeAliasValue = 0x00000400, // Serialize the type instead of using type-alias. This is needed when we emit declaration file. + SuppressAnyReturnType = 0x00000800, // If the return type is any-like, don't offer a return type. } export const enum SymbolFormatFlags { @@ -2865,7 +2870,7 @@ namespace ts { objectFlags: ObjectFlags; } - // Class and interface types (TypeFlags.Class and TypeFlags.Interface) + /** Class and interface types (TypeFlags.Class and TypeFlags.Interface). */ export interface InterfaceType extends ObjectType { typeParameters: TypeParameter[]; // Type parameters (undefined if non-generic) outerTypeParameters: TypeParameter[]; // Outer type parameters (undefined if none) @@ -2885,14 +2890,16 @@ namespace ts { declaredNumberIndexInfo: IndexInfo; // Declared numeric indexing info } - // Type references (TypeFlags.Reference). When a class or interface has type parameters or - // a "this" type, references to the class or interface are made using type references. The - // typeArguments property specifies the types to substitute for the type parameters of the - // class or interface and optionally includes an extra element that specifies the type to - // substitute for "this" in the resulting instantiation. When no extra argument is present, - // the type reference itself is substituted for "this". The typeArguments property is undefined - // if the class or interface has no type parameters and the reference isn't specifying an - // explicit "this" argument. + /** + * Type references (TypeFlags.Reference). When a class or interface has type parameters or + * a "this" type, references to the class or interface are made using type references. The + * typeArguments property specifies the types to substitute for the type parameters of the + * class or interface and optionally includes an extra element that specifies the type to + * substitute for "this" in the resulting instantiation. When no extra argument is present, + * the type reference itself is substituted for "this". The typeArguments property is undefined + * if the class or interface has no type parameters and the reference isn't specifying an + * explicit "this" argument. + */ export interface TypeReference extends ObjectType { target: GenericType; // Type reference target typeArguments: Type[]; // Type reference type arguments (undefined if none) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 6f491f6708fee..bee6634399599 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1778,7 +1778,7 @@ namespace ts { } } - export function getAncestor(node: Node, kind: SyntaxKind): Node { + export function getAncestor(node: Node | undefined, kind: SyntaxKind): Node { while (node) { if (node.kind === kind) { return node; diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 7c7a06db0b6c9..a88595f7a601e 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -44,6 +44,14 @@ namespace FourSlash { markers: Marker[]; + /** + * Inserted in source files by surrounding desired text + * in a range with `[|` and `|]`. For example, + * + * [|text in range|] + * + * is a range with `text in range` "selected". + */ ranges: Range[]; } @@ -1532,7 +1540,8 @@ namespace FourSlash { let runningOffset = 0; edits = edits.sort((a, b) => a.span.start - b.span.start); // Get a snapshot of the content of the file so we can make sure any formatting edits didn't destroy non-whitespace characters - const oldContent = this.getFileContent(this.activeFile.fileName); + const oldContent = this.getFileContent(fileName); + for (const edit of edits) { this.languageServiceAdapterHost.editScript(fileName, edit.span.start + runningOffset, ts.textSpanEnd(edit.span) + runningOffset, edit.newText); this.updateMarkersForEdit(fileName, edit.span.start + runningOffset, ts.textSpanEnd(edit.span) + runningOffset, edit.newText); @@ -1969,45 +1978,84 @@ namespace FourSlash { }); } - private getCodeFixes(errorCode?: number) { + /** + * Compares expected text to the text that would be in the sole range + * (ie: [|...|]) in the file after applying the codefix sole codefix + * in the source file. + * + * Because codefixes are only applied on the working file, it is unsafe + * to apply this more than once (consider a refactoring across files). + */ + public verifyRangeAfterCodeFix(expectedText: string, errorCode?: number) { + const ranges = this.getRanges(); + if (ranges.length !== 1) { + this.raiseError("Exactly one range should be specified in the testfile."); + } + const fileName = this.activeFile.fileName; - const diagnostics = this.getDiagnostics(fileName); - if (diagnostics.length === 0) { - this.raiseError("Errors expected."); - } + this.applyCodeFixActions(fileName, this.getCodeFixActions(fileName, errorCode)); - if (diagnostics.length > 1 && errorCode === undefined) { - this.raiseError("When there's more than one error, you must specify the errror to fix."); + const actualText = this.rangeText(ranges[0]); + + if (this.removeWhitespace(actualText) !== this.removeWhitespace(expectedText)) { + this.raiseError(`Actual text doesn't match expected text. Actual:\n'${actualText}'\nExpected:\n'${expectedText}'`); } + } - const diagnostic = !errorCode ? diagnostics[0] : ts.find(diagnostics, d => d.code == errorCode); + /** + * Applies fixes for the errors in fileName and compares the results to + * expectedContents after all fixes have been applied. - return this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.start + diagnostic.length, [diagnostic.code]); - } + * Note: applying one codefix may generate another (eg: remove duplicate implements + * may generate an extends -> interface conversion fix). + * @param expectedContents The contents of the file after the fixes are applied. + * @param fileName The file to check. If not supplied, the current open file is used. + */ + public verifyFileAfterCodeFix(expectedContents: string, fileName?: string) { + fileName = fileName ? fileName : this.activeFile.fileName; - public verifyCodeFixAtPosition(expectedText: string, errorCode?: number) { - const ranges = this.getRanges(); - if (ranges.length == 0) { - this.raiseError("At least one range should be specified in the testfile."); + this.applyCodeFixActions(fileName, this.getCodeFixActions(fileName)); + + const actualContents: string = this.getFileContent(fileName); + if (this.removeWhitespace(actualContents) !== this.removeWhitespace(expectedContents)) { + this.raiseError(`Actual text doesn't match expected text. Actual:\n${actualContents}\n\nExpected:\n${expectedContents}`); } + } - const actual = this.getCodeFixes(errorCode); + /** + * Rerieves a codefix satisfying the parameters, or undefined if no such codefix is found. + * @param fileName Path to file where error should be retrieved from. + */ + private getCodeFixActions(fileName: string, errorCode?: number): ts.CodeAction[] { + const diagnostics: ts.Diagnostic[] = this.getDiagnostics(fileName); - if (!actual || actual.length == 0) { - this.raiseError("No codefixes returned."); - } + let actions: ts.CodeAction[] = undefined; + for (const diagnostic of diagnostics) { - if (actual.length > 1) { - this.raiseError("More than 1 codefix returned."); + if (errorCode && errorCode !== diagnostic.code) { + continue; + } + + const newActions = this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.length, [diagnostic.code]); + if (newActions && newActions.length) { + actions = actions ? actions.concat(newActions) : newActions; + } } + return actions; + } - this.applyEdits(actual[0].changes[0].fileName, actual[0].changes[0].textChanges, /*isFormattingEdit*/ false); - const actualText = this.rangeText(ranges[0]); + private applyCodeFixActions(fileName: string, actions: ts.CodeAction[]): void { + if (!(actions && actions.length === 1)) { + this.raiseError(`Should find exactly one codefix, but ${actions ? actions.length : "none"} found.`); + } - if (this.removeWhitespace(actualText) !== this.removeWhitespace(expectedText)) { - this.raiseError(`Actual text doesn't match expected text. Actual: '${actualText}' Expected: '${expectedText}'`); + const fileChanges = ts.find(actions[0].changes, change => change.fileName === fileName); + if (!fileChanges) { + this.raiseError("The CodeFix found doesn't provide any changes in this file."); } + + this.applyEdits(fileChanges.fileName, fileChanges.textChanges, /*isFormattingEdit*/ false); } public verifyImportFixAtPosition(expectedTextArray: string[], errorCode?: number) { @@ -2016,7 +2064,7 @@ namespace FourSlash { this.raiseError("At least one range should be specified in the testfile."); } - const codeFixes = this.getCodeFixes(errorCode); + const codeFixes = this.getCodeFixActions(this.activeFile.fileName, errorCode); if (!codeFixes || codeFixes.length == 0) { this.raiseError("No codefixes returned."); @@ -2314,15 +2362,15 @@ namespace FourSlash { } } - public verifyCodeFixAvailable(negative: boolean, errorCode?: number) { - const fixes = this.getCodeFixes(errorCode); + public verifyCodeFixAvailable(negative: boolean) { + const codeFix = this.getCodeFixActions(this.activeFile.fileName); - if (negative && fixes && fixes.length > 0) { - this.raiseError(`verifyCodeFixAvailable failed - expected no fixes, actual: ${fixes.length}`); + if (negative && codeFix) { + this.raiseError(`verifyCodeFixAvailable failed - expected no fixes but found one.`); } - if (!negative && (fixes === undefined || fixes.length === 0)) { - this.raiseError(`verifyCodeFixAvailable failed - expected code fixes, actual: 0`); + if (!(negative || codeFix)) { + this.raiseError(`verifyCodeFixAvailable failed - expected code fixes but none found.`); } } @@ -3094,8 +3142,8 @@ namespace FourSlashInterface { this.state.verifyBraceCompletionAtPosition(this.negative, openingBrace); } - public codeFixAvailable(errorCode?: number) { - this.state.verifyCodeFixAvailable(this.negative, errorCode); + public codeFixAvailable() { + this.state.verifyCodeFixAvailable(this.negative); } } @@ -3280,8 +3328,8 @@ namespace FourSlashInterface { this.DocCommentTemplate(/*expectedText*/ undefined, /*expectedOffset*/ undefined, /*empty*/ true); } - public codeFixAtPosition(expectedText: string, errorCode?: number): void { - this.state.verifyCodeFixAtPosition(expectedText, errorCode); + public rangeAfterCodeFix(expectedText: string, errorCode?: number): void { + this.state.verifyRangeAfterCodeFix(expectedText, errorCode); } public importFixAtPosition(expectedTextArray: string[], errorCode?: number): void { diff --git a/src/harness/tsconfig.json b/src/harness/tsconfig.json index f4057057e4efd..6b83cf249a722 100644 --- a/src/harness/tsconfig.json +++ b/src/harness/tsconfig.json @@ -74,7 +74,18 @@ "../services/formatting/rulesProvider.ts", "../services/formatting/smartIndenter.ts", "../services/formatting/tokenRange.ts", - "harness.ts", + "../services/codeFixProvider.ts", + "../services/codefixes/fixes.ts", + "../services/codefixes/fixExtendsInterfaceBecomesImplements.ts", + "../services/codefixes/fixClassIncorrectlyImplementsInterface.ts", + "../services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts", + "../services/codefixes/fixClassSuperMustPrecedeThisAccess.ts", + "../services/codefixes/fixConstructorForDerivedNeedSuperCall.ts", + "../services/codefixes/helpers.ts", + "../services/codefixes/importFixes.ts", + "../services/codefixes/unusedIdentifierFixes.ts", + "../services/harness.ts", + "sourceMapRecorder.ts", "harnessLanguageService.ts", "fourslash.ts", diff --git a/src/services/codefixes/codeFixProvider.ts b/src/services/codeFixProvider.ts similarity index 100% rename from src/services/codefixes/codeFixProvider.ts rename to src/services/codeFixProvider.ts diff --git a/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts b/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts new file mode 100644 index 0000000000000..22546e55ecc50 --- /dev/null +++ b/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts @@ -0,0 +1,59 @@ +/* @internal */ +namespace ts.codefix { + registerCodeFix({ + errorCodes: [Diagnostics.Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2.code], + getCodeActions: getActionForClassLikeMissingAbstractMember + }); + + registerCodeFix({ + errorCodes: [Diagnostics.Non_abstract_class_expression_does_not_implement_inherited_abstract_member_0_from_class_1.code], + getCodeActions: getActionForClassLikeMissingAbstractMember + }); + + function getActionForClassLikeMissingAbstractMember(context: CodeFixContext): CodeAction[] | undefined { + const sourceFile = context.sourceFile; + const start = context.span.start; + // This is the identifier in the case of a class declaration + // or the class keyword token in the case of a class expression. + const token = getTokenAtPosition(sourceFile, start); + const checker = context.program.getTypeChecker(); + + if (isClassLike(token.parent)) { + const classDecl = token.parent as ClassLikeDeclaration; + const startPos = classDecl.members.pos; + + const classType = checker.getTypeAtLocation(classDecl) as InterfaceType; + const instantiatedExtendsType = checker.getBaseTypes(classType)[0]; + + // Note that this is ultimately derived from a map indexed by symbol names, + // so duplicates cannot occur. + const extendsSymbols = checker.getPropertiesOfType(instantiatedExtendsType); + const abstractAndNonPrivateExtendsSymbols = extendsSymbols.filter(symbolPointsToNonPrivateAndAbstractMember); + + const insertion = getMissingMembersInsertion(classDecl, abstractAndNonPrivateExtendsSymbols, checker, context.newLineCharacter); + + if (insertion.length) { + return [{ + description: getLocaleSpecificMessage(Diagnostics.Implement_inherited_abstract_class), + changes: [{ + fileName: sourceFile.fileName, + textChanges: [{ + span: { start: startPos, length: 0 }, + newText: insertion + }] + }] + }]; + } + } + + return undefined; + + } + + function symbolPointsToNonPrivateAndAbstractMember(symbol: Symbol): boolean { + const decls = symbol.getDeclarations(); + Debug.assert(!!(decls && decls.length > 0)); + const flags = getModifierFlags(decls[0]); + return !(flags & ModifierFlags.Private) && !!(flags & ModifierFlags.Abstract); + } +} \ No newline at end of file diff --git a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts new file mode 100644 index 0000000000000..42488dc2aed66 --- /dev/null +++ b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts @@ -0,0 +1,75 @@ +/* @internal */ +namespace ts.codefix { + registerCodeFix({ + errorCodes: [Diagnostics.Class_0_incorrectly_implements_interface_1.code], + getCodeActions: getActionForClassLikeIncorrectImplementsInterface + }); + + function getActionForClassLikeIncorrectImplementsInterface(context: CodeFixContext): CodeAction[] | undefined { + const sourceFile = context.sourceFile; + const start = context.span.start; + const token = getTokenAtPosition(sourceFile, start); + const checker = context.program.getTypeChecker(); + + const classDecl = getContainingClass(token); + if (!classDecl) { + return undefined; + } + + const startPos: number = classDecl.members.pos; + const classType = checker.getTypeAtLocation(classDecl); + const implementedTypeNodes = getClassImplementsHeritageClauseElements(classDecl); + + const hasNumericIndexSignature = !!checker.getIndexTypeOfType(classType, IndexKind.Number); + const hasStringIndexSignature = !!checker.getIndexTypeOfType(classType, IndexKind.String); + + const result: CodeAction[] = []; + for (const implementedTypeNode of implementedTypeNodes) { + const implementedType = checker.getTypeFromTypeNode(implementedTypeNode) as InterfaceType; + // Note that this is ultimately derived from a map indexed by symbol names, + // so duplicates cannot occur. + const implementedTypeSymbols = checker.getPropertiesOfType(implementedType); + const nonPrivateMembers = implementedTypeSymbols.filter(symbol => !(getModifierFlags(symbol.valueDeclaration) & ModifierFlags.Private)); + + let insertion = getMissingIndexSignatureInsertion(implementedType, IndexKind.Number, classDecl, hasNumericIndexSignature); + insertion += getMissingIndexSignatureInsertion(implementedType, IndexKind.String, classDecl, hasStringIndexSignature); + insertion += getMissingMembersInsertion(classDecl, nonPrivateMembers, checker, context.newLineCharacter); + + const message = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Implement_interface_0), [implementedTypeNode.getText()]); + if (insertion) { + pushAction(result, insertion, message); + } + } + + return result; + + function getMissingIndexSignatureInsertion(type: InterfaceType, kind: IndexKind, enclosingDeclaration: ClassLikeDeclaration, hasIndexSigOfKind: boolean) { + if (!hasIndexSigOfKind) { + const IndexInfoOfKind = checker.getIndexInfoOfType(type, kind); + if (IndexInfoOfKind) { + const writer = getSingleLineStringWriter(); + checker.getSymbolDisplayBuilder().buildIndexSignatureDisplay(IndexInfoOfKind, writer, kind, enclosingDeclaration); + const result = writer.string(); + releaseStringWriter(writer); + + return result; + } + } + return ""; + } + + function pushAction(result: CodeAction[], insertion: string, description: string): void { + const newAction: CodeAction = { + description: description, + changes: [{ + fileName: sourceFile.fileName, + textChanges: [{ + span: { start: startPos, length: 0 }, + newText: insertion + }] + }] + }; + result.push(newAction); + } + } +} \ No newline at end of file diff --git a/src/services/codefixes/superFixes.ts b/src/services/codefixes/fixClassSuperMustPrecedeThisAccess.ts similarity index 68% rename from src/services/codefixes/superFixes.ts rename to src/services/codefixes/fixClassSuperMustPrecedeThisAccess.ts index f117799f3e1c2..4528c48774d8c 100644 --- a/src/services/codefixes/superFixes.ts +++ b/src/services/codefixes/fixClassSuperMustPrecedeThisAccess.ts @@ -1,28 +1,5 @@ /* @internal */ namespace ts.codefix { - function getOpenBraceEnd(constructor: ConstructorDeclaration, sourceFile: SourceFile) { - // First token is the open curly, this is where we want to put the 'super' call. - return constructor.body.getFirstToken(sourceFile).getEnd(); - } - - registerCodeFix({ - errorCodes: [Diagnostics.Constructors_for_derived_classes_must_contain_a_super_call.code], - getCodeActions: (context: CodeFixContext) => { - const sourceFile = context.sourceFile; - const token = getTokenAtPosition(sourceFile, context.span.start); - - if (token.kind !== SyntaxKind.ConstructorKeyword) { - return undefined; - } - - const newPosition = getOpenBraceEnd(token.parent, sourceFile); - return [{ - description: getLocaleSpecificMessage(Diagnostics.Add_missing_super_call), - changes: [{ fileName: sourceFile.fileName, textChanges: [{ newText: "super();", span: { start: newPosition, length: 0 } }] }] - }]; - } - }); - registerCodeFix({ errorCodes: [Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class.code], getCodeActions: (context: CodeFixContext) => { diff --git a/src/services/codefixes/fixConstructorForDerivedNeedSuperCall.ts b/src/services/codefixes/fixConstructorForDerivedNeedSuperCall.ts new file mode 100644 index 0000000000000..0dede87cf2810 --- /dev/null +++ b/src/services/codefixes/fixConstructorForDerivedNeedSuperCall.ts @@ -0,0 +1,20 @@ +/* @internal */ +namespace ts.codefix { + registerCodeFix({ + errorCodes: [Diagnostics.Constructors_for_derived_classes_must_contain_a_super_call.code], + getCodeActions: (context: CodeFixContext) => { + const sourceFile = context.sourceFile; + const token = getTokenAtPosition(sourceFile, context.span.start); + + if (token.kind !== SyntaxKind.ConstructorKeyword) { + return undefined; + } + + const newPosition = getOpenBraceEnd(token.parent, sourceFile); + return [{ + description: getLocaleSpecificMessage(Diagnostics.Add_missing_super_call), + changes: [{ fileName: sourceFile.fileName, textChanges: [{ newText: "super();", span: { start: newPosition, length: 0 } }] }] + }]; + } + }); +} \ No newline at end of file diff --git a/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts b/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts new file mode 100644 index 0000000000000..1e72700ec01bf --- /dev/null +++ b/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts @@ -0,0 +1,49 @@ +/* @internal */ +namespace ts.codefix { + registerCodeFix({ + errorCodes: [Diagnostics.Cannot_extend_an_interface_0_Did_you_mean_implements.code], + getCodeActions: (context: CodeFixContext) => { + const sourceFile = context.sourceFile; + const start = context.span.start; + const token = getTokenAtPosition(sourceFile, start); + const classDeclNode = getContainingClass(token); + if (!(token.kind === SyntaxKind.Identifier && isClassLike(classDeclNode))) { + return undefined; + } + + const heritageClauses = classDeclNode.heritageClauses; + if (!(heritageClauses && heritageClauses.length > 0)) { + return undefined; + } + + const extendsToken = heritageClauses[0].getFirstToken(); + if (!(extendsToken && extendsToken.kind === SyntaxKind.ExtendsKeyword)) { + return undefined; + } + + let changeStart = extendsToken.getStart(sourceFile); + let changeEnd = extendsToken.getEnd(); + const textChanges: TextChange[] = [{ newText: " implements", span: { start: changeStart, length: changeEnd - changeStart } }]; + + // We replace existing keywords with commas. + for (let i = 1; i < heritageClauses.length; i++) { + const keywordToken = heritageClauses[i].getFirstToken(); + if (keywordToken) { + changeStart = keywordToken.getStart(sourceFile); + changeEnd = keywordToken.getEnd(); + textChanges.push({ newText: ",", span: { start: changeStart, length: changeEnd - changeStart } }); + } + } + + const result = [{ + description: getLocaleSpecificMessage(Diagnostics.Change_extends_to_implements), + changes: [{ + fileName: sourceFile.fileName, + textChanges: textChanges + }] + }]; + + return result; + } + }); +} diff --git a/src/services/codefixes/fixes.ts b/src/services/codefixes/fixes.ts index a38b196cb0078..10d6fa5015898 100644 --- a/src/services/codefixes/fixes.ts +++ b/src/services/codefixes/fixes.ts @@ -1,3 +1,9 @@ -/// -/// -/// +/// +/// +/// +/// +/// +/// +/// +/// + diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts new file mode 100644 index 0000000000000..d539ef0d68b5a --- /dev/null +++ b/src/services/codefixes/helpers.ts @@ -0,0 +1,156 @@ +/* @internal */ +namespace ts.codefix { + + /** + * Finds members of the resolved type that are missing in the class pointed to by class decl + * and generates source code for the missing members. + * @param possiblyMissingSymbols The collection of symbols to filter and then get insertions for. + * @returns Empty string iff there are no member insertions. + */ + export function getMissingMembersInsertion(classDeclaration: ClassLikeDeclaration, possiblyMissingSymbols: Symbol[], checker: TypeChecker, newlineChar: string): string { + const classMembers = classDeclaration.symbol.members; + const missingMembers = possiblyMissingSymbols.filter(symbol => !(symbol.getName() in classMembers)); + + let insertion = ""; + + for (const symbol of missingMembers) { + insertion = insertion.concat(getInsertionForMemberSymbol(symbol, classDeclaration, checker, newlineChar)); + } + return insertion; + } + + /** + * @returns Empty string iff there we can't figure out a representation for `symbol` in `enclosingDeclaration`. + */ + function getInsertionForMemberSymbol(symbol: Symbol, enclosingDeclaration: ClassLikeDeclaration, checker: TypeChecker, newlineChar: string): string { + // const name = symbol.getName(); + const type = checker.getTypeOfSymbolAtLocation(symbol, enclosingDeclaration); + const declarations = symbol.getDeclarations(); + if (!(declarations && declarations.length)) { + return ""; + } + + const declaration = declarations[0] as Declaration; + const name = declaration.name ? declaration.name.getText() : undefined; + const visibility = getVisibilityPrefix(getModifierFlags(declaration)); + + switch (declaration.kind) { + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.PropertySignature: + case SyntaxKind.PropertyDeclaration: + const typeString = checker.typeToString(type, enclosingDeclaration, TypeFormatFlags.None); + return `${visibility}${name}: ${typeString};${newlineChar}`; + + case SyntaxKind.MethodSignature: + case SyntaxKind.MethodDeclaration: + // The signature for the implementation appears as an entry in `signatures` iff + // there is only one signature. + // If there are overloads and an implementation signature, it appears as an + // extra declaration that isn't a signature for `type`. + // If there is more than one overload but no implementation signature + // (eg: an abstract method or interface declaration), there is a 1-1 + // correspondence of declarations and signatures. + const signatures = checker.getSignaturesOfType(type, SignatureKind.Call); + if (!(signatures && signatures.length > 0)) { + return ""; + } + if (declarations.length === 1) { + Debug.assert(signatures.length === 1); + const sigString = checker.signatureToString(signatures[0], enclosingDeclaration, TypeFormatFlags.SuppressAnyReturnType, SignatureKind.Call); + return `${visibility}${name}${sigString}${getMethodBodyStub(newlineChar)}`; + } + + let result = ""; + for (let i = 0; i < signatures.length; i++) { + const sigString = checker.signatureToString(signatures[i], enclosingDeclaration, TypeFormatFlags.SuppressAnyReturnType, SignatureKind.Call); + result += `${visibility}${name}${sigString};${newlineChar}`; + } + + // If there is a declaration with a body, it is the last declaration, + // and it isn't caught by `getSignaturesOfType`. + let bodySig: Signature | undefined = undefined; + if (declarations.length > signatures.length) { + bodySig = checker.getSignatureFromDeclaration(declarations[declarations.length - 1] as SignatureDeclaration); + } + else { + Debug.assert(declarations.length === signatures.length); + bodySig = createBodySignatureWithAnyTypes(signatures, enclosingDeclaration, checker); + } + const sigString = checker.signatureToString(bodySig, enclosingDeclaration, TypeFormatFlags.SuppressAnyReturnType, SignatureKind.Call); + result += `${visibility}${name}${sigString}${getMethodBodyStub(newlineChar)}`; + + return result; + default: + return ""; + } + } + + function createBodySignatureWithAnyTypes(signatures: Signature[], enclosingDeclaration: ClassLikeDeclaration, checker: TypeChecker): Signature { + const newSignatureDeclaration = createNode(SyntaxKind.CallSignature) as SignatureDeclaration; + newSignatureDeclaration.parent = enclosingDeclaration; + newSignatureDeclaration.name = signatures[0].getDeclaration().name; + + let maxNonRestArgs = -1; + let maxArgsIndex = 0; + let minArgumentCount = signatures[0].minArgumentCount; + let hasRestParameter = false; + for (let i = 0; i < signatures.length; i++) { + const sig = signatures[i]; + minArgumentCount = Math.min(sig.minArgumentCount, minArgumentCount); + hasRestParameter = hasRestParameter || sig.hasRestParameter; + const nonRestLength = sig.parameters.length - (sig.hasRestParameter ? 1 : 0); + if (nonRestLength > maxNonRestArgs) { + maxNonRestArgs = nonRestLength; + maxArgsIndex = i; + } + } + const maxArgsParameterSymbolNames = signatures[maxArgsIndex].getParameters().map(symbol => symbol.getName()); + + const optionalToken = createToken(SyntaxKind.QuestionToken); + + newSignatureDeclaration.parameters = createNodeArray(); + for (let i = 0; i < maxNonRestArgs; i++) { + const newParameter = createParameterDeclarationWithoutType(i, minArgumentCount, newSignatureDeclaration); + newSignatureDeclaration.parameters.push(newParameter); + } + + if (hasRestParameter) { + const restParameter = createParameterDeclarationWithoutType(maxNonRestArgs, minArgumentCount, newSignatureDeclaration); + restParameter.dotDotDotToken = createToken(SyntaxKind.DotDotDotToken); + newSignatureDeclaration.parameters.push(restParameter); + } + + return checker.getSignatureFromDeclaration(newSignatureDeclaration); + + function createParameterDeclarationWithoutType(index: number, minArgCount: number, enclosingSignatureDeclaration: SignatureDeclaration): ParameterDeclaration { + const newParameter = createNode(SyntaxKind.Parameter) as ParameterDeclaration; + + newParameter.symbol = new SymbolConstructor(SymbolFlags.FunctionScopedVariable, maxArgsParameterSymbolNames[index] || "rest"); + newParameter.symbol.valueDeclaration = newParameter; + newParameter.symbol.declarations = [newParameter]; + newParameter.parent = enclosingSignatureDeclaration; + if (index >= minArgCount) { + newParameter.questionToken = optionalToken; + } + + return newParameter; + } + } + + function getMethodBodyStub(newLineChar: string) { + return ` {${newLineChar}throw new Error('Method not implemented.');${newLineChar}}${newLineChar}`; + } + + function getVisibilityPrefix(flags: ModifierFlags): string { + if (flags & ModifierFlags.Public) { + return "public "; + } + else if (flags & ModifierFlags.Protected) { + return "protected "; + } + return ""; + } + + const SymbolConstructor = objectAllocator.getSymbolConstructor(); +} \ No newline at end of file diff --git a/src/services/services.ts b/src/services/services.ts index 7ad02de56e51b..72464793bffc1 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -24,7 +24,7 @@ /// /// /// -/// +/// /// namespace ts { diff --git a/src/services/tsconfig.json b/src/services/tsconfig.json index 502381b8be807..921ee7762f83b 100644 --- a/src/services/tsconfig.json +++ b/src/services/tsconfig.json @@ -87,7 +87,15 @@ "formatting/rulesProvider.ts", "formatting/smartIndenter.ts", "formatting/tokenRange.ts", - "codeFixes/codeFixProvider.ts", - "codeFixes/fixes.ts" + "codeFixProvider.ts", + "codefixes/fixExtendsInterfaceBecomesImplements.ts", + "codefixes/fixClassIncorrectlyImplementsInterface.ts", + "codefixes/fixClassDoesntImplementInheritedAbstractMember.ts", + "codefixes/fixClassSuperMustPrecedeThisAccess.ts", + "codefixes/fixConstructorForDerivedNeedSuperCall.ts", + "codefixes/fixes.ts", + "codefixes/helpers.ts", + "codefixes/importFixes.ts", + "codefixes/unusedIdentifierFixes.ts" ] -} +} \ No newline at end of file diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 2f52d747e239d..383708ab17888 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1359,4 +1359,9 @@ namespace ts { diagnostics: error ? concatenate(diagnostics, [error]) : diagnostics }; } -} + + export function getOpenBraceEnd(constructor: ConstructorDeclaration, sourceFile: SourceFile) { + // First token is the open curly, this is where we want to put the 'super' call. + return constructor.body.getFirstToken(sourceFile).getEnd(); + } +} \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixChangeExtendsToImplements.ts b/tests/cases/fourslash/codeFixChangeExtendsToImplements.ts new file mode 100644 index 0000000000000..bfaedf2818a9e --- /dev/null +++ b/tests/cases/fourslash/codeFixChangeExtendsToImplements.ts @@ -0,0 +1,6 @@ +/// + +//// interface I {} +//// [|/* */ class /* */ C /* */ extends /* */ I|]{} + +verify.rangeAfterCodeFix("/* */ class /* */ C /* */ implements /* */ I"); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixChangeExtendsToImplementsAbstractModifier.ts b/tests/cases/fourslash/codeFixChangeExtendsToImplementsAbstractModifier.ts new file mode 100644 index 0000000000000..5f5ca93c28fc8 --- /dev/null +++ b/tests/cases/fourslash/codeFixChangeExtendsToImplementsAbstractModifier.ts @@ -0,0 +1,8 @@ +/// + +//// interface I1 { } +//// interface I2 { } + +//// [|abstract class A extends I1 implements I2|] { } + +verify.rangeAfterCodeFix("abstract class A implements I1, I2"); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixChangeExtendsToImplementsTypeParams.ts b/tests/cases/fourslash/codeFixChangeExtendsToImplementsTypeParams.ts new file mode 100644 index 0000000000000..869bd1a5dc0a0 --- /dev/null +++ b/tests/cases/fourslash/codeFixChangeExtendsToImplementsTypeParams.ts @@ -0,0 +1,6 @@ +/// + +////interface I { x: X} +////[|class C extends I|]{} + +verify.rangeAfterCodeFix("class C implements I"); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixChangeExtendsToImplementsWithDecorator.ts b/tests/cases/fourslash/codeFixChangeExtendsToImplementsWithDecorator.ts new file mode 100644 index 0000000000000..9671f41def335 --- /dev/null +++ b/tests/cases/fourslash/codeFixChangeExtendsToImplementsWithDecorator.ts @@ -0,0 +1,13 @@ +/// + +//// interface I1 { } +//// interface I2 { } + +//// function sealed(constructor: Function) { +//// Object.seal(constructor); +//// Object.seal(constructor.prototype); +//// } + +//// @sealed +//// [|class A extends I1 implements I2 { }|] +verify.rangeAfterCodeFix("class A implements I1, I2 { }"); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassExprClassImplementClassFunctionVoidInferred.ts b/tests/cases/fourslash/codeFixClassExprClassImplementClassFunctionVoidInferred.ts new file mode 100644 index 0000000000000..bdf8ea3bd2540 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassExprClassImplementClassFunctionVoidInferred.ts @@ -0,0 +1,13 @@ +/// + +//// class A { +//// f() {} +//// } +//// +//// let B = class implements A {[| |]} + +verify.rangeAfterCodeFix(` +f(): void{ + throw new Error('Method not implemented.'); +} +`); diff --git a/tests/cases/fourslash/codeFixClassExprExtendsAbstractExpressionWithTypeArgs.ts b/tests/cases/fourslash/codeFixClassExprExtendsAbstractExpressionWithTypeArgs.ts new file mode 100644 index 0000000000000..a7690b4f5bf18 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassExprExtendsAbstractExpressionWithTypeArgs.ts @@ -0,0 +1,14 @@ +/// + +//// function foo(a: T) { +//// abstract class C { +//// abstract a: T | U; +//// } +//// return C; +//// } +//// +//// let B = class extends foo("s") {[| |]} + +verify.rangeAfterCodeFix(` +a: string | number; +`); diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractExpressionWithTypeArgs.ts b/tests/cases/fourslash/codeFixClassExtendAbstractExpressionWithTypeArgs.ts new file mode 100644 index 0000000000000..5796bea6fb485 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassExtendAbstractExpressionWithTypeArgs.ts @@ -0,0 +1,14 @@ +/// + +//// function foo(a: T) { +//// abstract class C { +//// abstract a: T | U; +//// } +//// return C; +//// } +//// +//// class B extends foo("s") {[| |]} + +verify.rangeAfterCodeFix(` +a: string | number; +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractGetter.ts b/tests/cases/fourslash/codeFixClassExtendAbstractGetter.ts new file mode 100644 index 0000000000000..8d79cce710e50 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassExtendAbstractGetter.ts @@ -0,0 +1,11 @@ +/// + +//// abstract class A { +//// abstract get b(): number; +//// } +//// +//// class C extends A {[| |]} + +verify.rangeAfterCodeFix(` + b: number; +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractGetterSetter.ts b/tests/cases/fourslash/codeFixClassExtendAbstractGetterSetter.ts new file mode 100644 index 0000000000000..fc0ac40062303 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassExtendAbstractGetterSetter.ts @@ -0,0 +1,17 @@ +/// + +//// abstract class A { +//// private _a: string; +//// +//// abstract get a(): string; +//// abstract set a(newName: string); +//// } +//// +//// // Don't need to add anything in this case. +//// abstract class B extends A {} +//// +//// class C extends A {[| |]} + +verify.rangeAfterCodeFix(` + a: string; +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractMethod.ts b/tests/cases/fourslash/codeFixClassExtendAbstractMethod.ts new file mode 100644 index 0000000000000..a657dfeb7188f --- /dev/null +++ b/tests/cases/fourslash/codeFixClassExtendAbstractMethod.ts @@ -0,0 +1,18 @@ +/// + +//// abstract class A { +//// abstract f(a: number, b: string): boolean; +//// abstract f(a: string, b: number): Function; +//// abstract f(a: string): Function; +//// } +//// +//// class C extends A {[| |]} + +verify.rangeAfterCodeFix(` + f(a: number, b: string): boolean; + f(a: string, b: number): Function; + f(a: string): Function; + f(a: any, b?: any) { + throw new Error('Method not implemented.'); + } +`); diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractMethodTypeParamsInstantiateNumber.ts b/tests/cases/fourslash/codeFixClassExtendAbstractMethodTypeParamsInstantiateNumber.ts new file mode 100644 index 0000000000000..bdf198b89e3d4 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassExtendAbstractMethodTypeParamsInstantiateNumber.ts @@ -0,0 +1,13 @@ +/// + +//// abstract class A { +//// abstract f(x: T): T; +//// } +//// +//// class C extends A {[| +//// |]} + +verify.rangeAfterCodeFix(`f(x: number): number{ + throw new Error('Method not implemented.'); +} +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractMethodTypeParamsInstantiateU.ts b/tests/cases/fourslash/codeFixClassExtendAbstractMethodTypeParamsInstantiateU.ts new file mode 100644 index 0000000000000..647a533c1c58c --- /dev/null +++ b/tests/cases/fourslash/codeFixClassExtendAbstractMethodTypeParamsInstantiateU.ts @@ -0,0 +1,13 @@ +/// + +//// abstract class A { +//// abstract f(x: T): T; +//// } +//// +//// class C extends A {[| +//// |]} + +verify.rangeAfterCodeFix(`f(x: U): U{ + throw new Error('Method not implemented.'); +} +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractPrivateProperty.ts b/tests/cases/fourslash/codeFixClassExtendAbstractPrivateProperty.ts new file mode 100644 index 0000000000000..d395272b36f18 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassExtendAbstractPrivateProperty.ts @@ -0,0 +1,15 @@ +/// + +//// abstract class A { +//// private abstract x: number; +//// } +//// +//// class C extends A {[| +//// |]} + +// We don't know how to fix this problem. We can: +// 1) Make x protected, and then insert. +// 2) Make x private, and then insert. +// 3) Make x not abstract. +// So we offer no fixes. +verify.not.codeFixAvailable(); diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractProperty.ts b/tests/cases/fourslash/codeFixClassExtendAbstractProperty.ts new file mode 100644 index 0000000000000..46de88f7511e4 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassExtendAbstractProperty.ts @@ -0,0 +1,12 @@ +/// + +//// abstract class A { +//// abstract x: number; +//// } +//// +//// class C extends A {[| +//// |]} + +verify.rangeAfterCodeFix(` +x: number; +`); diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractProtectedProperty.ts b/tests/cases/fourslash/codeFixClassExtendAbstractProtectedProperty.ts new file mode 100644 index 0000000000000..6d0571fce6b67 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassExtendAbstractProtectedProperty.ts @@ -0,0 +1,12 @@ +/// + +//// abstract class A { +//// protected abstract x: number; +//// } +//// +//// class C extends A {[| +//// |]} + +verify.rangeAfterCodeFix(` +protected x: number; +`); diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractPublicProperty.ts b/tests/cases/fourslash/codeFixClassExtendAbstractPublicProperty.ts new file mode 100644 index 0000000000000..917f75051f12e --- /dev/null +++ b/tests/cases/fourslash/codeFixClassExtendAbstractPublicProperty.ts @@ -0,0 +1,12 @@ +/// + +//// abstract class A { +//// public abstract x: number; +//// } +//// +//// class C extends A {[| +//// |]} + +verify.rangeAfterCodeFix(` +public x: number; +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractSetter.ts b/tests/cases/fourslash/codeFixClassExtendAbstractSetter.ts new file mode 100644 index 0000000000000..e8cb55fa6607f --- /dev/null +++ b/tests/cases/fourslash/codeFixClassExtendAbstractSetter.ts @@ -0,0 +1,11 @@ +/// + +//// abstract class A { +//// abstract set c(arg: number | string); +//// } +//// +//// class C extends A {[| |]} + +verify.rangeAfterCodeFix(` + c: string | number; +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractSomePropertiesPresent.ts b/tests/cases/fourslash/codeFixClassExtendAbstractSomePropertiesPresent.ts new file mode 100644 index 0000000000000..b6dd679bb7185 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassExtendAbstractSomePropertiesPresent.ts @@ -0,0 +1,16 @@ +/// + +//// abstract class A { +//// abstract x: number; +//// abstract y: number; +//// abstract z: number; +//// } +//// +//// class C extends A {[| |] +//// constructor(public x: number) { super(); } +//// y: number; +//// } + +verify.rangeAfterCodeFix(` +z: number; +`); diff --git a/tests/cases/fourslash/codeFixClassImplementClassAbstractGettersAndSetters.ts b/tests/cases/fourslash/codeFixClassImplementClassAbstractGettersAndSetters.ts new file mode 100644 index 0000000000000..df78803c5889e --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementClassAbstractGettersAndSetters.ts @@ -0,0 +1,20 @@ +/// + +//// abstract class A { +//// private _a: string; +//// +//// abstract get a(): string; +//// abstract set a(newName: string); +//// +//// abstract get b(): number; +//// +//// abstract set c(arg: number | string); +//// } +//// +//// class C implements A {[| |]} + +verify.rangeAfterCodeFix(` + a: string; + b: number; + c: string | number; +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementClassFunctionVoidInferred.ts b/tests/cases/fourslash/codeFixClassImplementClassFunctionVoidInferred.ts new file mode 100644 index 0000000000000..d9b9f57d4d252 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementClassFunctionVoidInferred.ts @@ -0,0 +1,13 @@ +/// + +//// class A { +//// f() {} +//// } +//// +//// class B implements A {[| |]} + +verify.rangeAfterCodeFix(` +f(): void{ + throw new Error('Method not implemented.'); +} +`); diff --git a/tests/cases/fourslash/codeFixClassImplementClassMethodViaHeritage.ts b/tests/cases/fourslash/codeFixClassImplementClassMethodViaHeritage.ts new file mode 100644 index 0000000000000..4365a160531e5 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementClassMethodViaHeritage.ts @@ -0,0 +1,18 @@ +/// + +//// class C1 { +//// f1() {} +//// } +//// +//// class C2 extends C1 { +//// +//// } +//// +//// class C3 implements C2 {[| +//// |]f2(){} +//// } + +verify.rangeAfterCodeFix(`f1(): void{ + throw new Error('Method not implemented.'); +} +`); diff --git a/tests/cases/fourslash/codeFixClassImplementClassMultipleSignatures1.ts b/tests/cases/fourslash/codeFixClassImplementClassMultipleSignatures1.ts new file mode 100644 index 0000000000000..82ecde6c41855 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementClassMultipleSignatures1.ts @@ -0,0 +1,14 @@ +/// + +//// class A { +//// method(a: number, b: string): boolean; +//// method(a: string | number, b?: string | number): boolean | Function { return true; } +//// +//// class C implements A {[| |]} + +verify.rangeAfterCodeFix(` + method(a: number, b: string): boolean; + method(a: string | number, b?: string | number): boolean | Function { + throw new Error('Method not implemented.'); + } +`); diff --git a/tests/cases/fourslash/codeFixClassImplementClassMultipleSignatures2.ts b/tests/cases/fourslash/codeFixClassImplementClassMultipleSignatures2.ts new file mode 100644 index 0000000000000..f187e0ca0f15d --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementClassMultipleSignatures2.ts @@ -0,0 +1,18 @@ +/// + +//// class A { +//// method(a: any, b: string): boolean; +//// method(a: string, b: number): Function; +//// method(a: string): Function; +//// method(a: string | number, b?: string | number): boolean | Function { return true; } +//// +//// class C implements A {[| |]} + +verify.rangeAfterCodeFix(` + method(a: any, b: string): boolean; + method(a: string, b: number): Function; + method(a: string): Function; + method(a: string | number, b?: string | number): boolean | Function { + throw new Error('Method not implemented.'); + } +`); diff --git a/tests/cases/fourslash/codeFixClassImplementClassPropertyModifiers.ts b/tests/cases/fourslash/codeFixClassImplementClassPropertyModifiers.ts new file mode 100644 index 0000000000000..a40ffc8aeb0f4 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementClassPropertyModifiers.ts @@ -0,0 +1,16 @@ +/// + +//// abstract class A { +//// abstract x: number; +//// private y: number; +//// protected z: number; +//// public w: number; +//// } +//// +//// class C implements A {[| |]} + +verify.rangeAfterCodeFix(` +x: number; +protected z: number; +public w: number; +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementDeepInheritance.ts b/tests/cases/fourslash/codeFixClassImplementDeepInheritance.ts new file mode 100644 index 0000000000000..e8b199b21af63 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementDeepInheritance.ts @@ -0,0 +1,63 @@ +/// + + +//// // Referenced throughout the inheritance chain. +//// interface I0 { a: number } +//// +//// class C1 implements I0 { a: number } +//// interface I1 { b: number } +//// interface I2 extends C1, I1 {} +//// +//// class C2 { c: number } +//// interface I3 {d: number} +//// class C3 extends C2 implements I0, I2, I3 { +//// a: number; +//// b: number; +//// d: number; +//// } +//// +//// interface I4 { e: number } +//// interface I5 { f: number } +//// class C4 extends C3 implements I0, I4, I5 { +//// e: number; +//// f: number; +//// } +//// +//// interface I6 extends C4 {} +//// class C5 implements I6 {[| +//// |]} + + +/** + * We want to check whether the search for member to replace actually searches through + * the various possible paths of the inheritance chain correctly, and that We + * don't issue duplicates for the same member. + * + * Our class DAG: + * + * C5 + * |-I6 + * |-C4 + * |-I4 + * |-I5 + * |------------------------ I0 + * |-C3 + * |-I2 + * |-I1 + * |-C1 + * |-------------------I0 + * |-I3 + * |-----------------------I0 + * |-C2 + */ + + +verify.rangeAfterCodeFix( +` +e: number; +f: number; +a: number; +b: number; +d: number; +c: number; +`); diff --git a/tests/cases/fourslash/codeFixClassImplementDefaultClass.ts b/tests/cases/fourslash/codeFixClassImplementDefaultClass.ts new file mode 100644 index 0000000000000..9f507c3dc606c --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementDefaultClass.ts @@ -0,0 +1,9 @@ +/// + +//// interface I { x: number; } +//// +//// export default class implements I {[| |]} + +verify.rangeAfterCodeFix(` +x: number; +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterface36.ts b/tests/cases/fourslash/codeFixClassImplementInterface36.ts new file mode 100644 index 0000000000000..f9fc48991fc25 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterface36.ts @@ -0,0 +1,20 @@ +/// + +//// abstract class C1 { +//// +//// } +//// +//// abstract class C2 { +//// abstract f1(); +//// } +//// +//// interface I1 extends C1, C2 {} +//// +//// class C3 implements I1 {[| +//// +//// |]} + +verify.rangeAfterCodeFix(`f1(){ + throw new Error('Method not implemented.'); +} +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterface39.ts b/tests/cases/fourslash/codeFixClassImplementInterface39.ts new file mode 100644 index 0000000000000..f81dea49782c5 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterface39.ts @@ -0,0 +1,18 @@ +/// + +//// namespace N1 { +//// export interface I1 { +//// f1():string; +//// } +//// } +//// interface I1 { +//// f1(); +//// } +//// +//// class C1 implements N1.I1 {[| +//// |]} + +verify.rangeAfterCodeFix(`f1(): string{ + throw new Error('Method not implemented.'); +} +`); diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceClassExpression.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceClassExpression.ts new file mode 100644 index 0000000000000..5b07a582c6cfc --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceClassExpression.ts @@ -0,0 +1,10 @@ +/// + + +//// interface I { x: number; } +//// +//// new class implements I {[| |]}; + +verify.rangeAfterCodeFix(` +x: number; +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceComputedPropertyLiterals.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceComputedPropertyLiterals.ts new file mode 100644 index 0000000000000..465f9a5b4f1b3 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceComputedPropertyLiterals.ts @@ -0,0 +1,21 @@ +/// + +//// interface I { +//// ["foo"](o: any): boolean; +//// ["x"]: boolean; +//// [1](): string; +//// [2]: boolean; +//// } +//// +//// class C implements I {[| |]} + +verify.rangeAfterCodeFix(` + [1](): string { + throw new Error('Method not implemented.'); + } + [2]: boolean; + ["foo"](o: any): boolean { + throw new Error('Method not implemented.'); + } + ["x"]: boolean; +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceComputedPropertyNameWellKnownSymbols.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceComputedPropertyNameWellKnownSymbols.ts new file mode 100644 index 0000000000000..7c1156acd78cc --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceComputedPropertyNameWellKnownSymbols.ts @@ -0,0 +1,52 @@ +/// + +// @lib: es2017 + +//// interface I { +//// [Symbol.hasInstance](o: any): boolean; +//// [Symbol.isConcatSpreadable]: boolean; +//// [Symbol.iterator](): any; +//// [Symbol.match]: boolean; +//// [Symbol.replace](...args); +//// [Symbol.search](str: string): number; +//// [Symbol.species](): Species; +//// [Symbol.split](str: string, limit?: number): string[]; +//// [Symbol.toPrimitive](hint: "number"): number; +//// [Symbol.toPrimitive](hint: "default"): number; +//// [Symbol.toPrimitive](hint: "string"): string; +//// [Symbol.toStringTag]: string; +//// [Symbol.unscopables]: any; +//// } +//// +//// class C implements I {[| |]} + +verify.rangeAfterCodeFix(` + [Symbol.hasInstance](o: any): boolean { + throw new Error('Method not implemented.'); + } + [Symbol.isConcatSpreadable]: boolean; + [Symbol.iterator]() { + throw new Error('Method not implemented.'); + } + [Symbol.match]: boolean; + [Symbol.replace](...args: {}) { + throw new Error('Method not implemented.'); + } + [Symbol.search](str: string): number { + throw new Error('Method not implemented.'); + } + [Symbol.species](): number { + throw new Error('Method not implemented.'); + } + [Symbol.split](str: string, limit?: number): {} { + throw new Error('Method not implemented.'); + } + [Symbol.toPrimitive](hint: "number"): number; + [Symbol.toPrimitive](hint: "default"): number; + [Symbol.toPrimitive](hint: "string"): string; + [Symbol.toPrimitive](hint: any) { + throw new Error('Method not implemented.'); + } + [Symbol.toStringTag]: string; + [Symbol.unscopables]: any; +`); diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceDuplicateMember1.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceDuplicateMember1.ts new file mode 100644 index 0000000000000..a2154de567aac --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceDuplicateMember1.ts @@ -0,0 +1,13 @@ +/// + +//// interface I1 { +//// x: number; +//// } +//// interface I2 { +//// x: number; +//// } +//// +//// class C implements I1,I2 {[| +//// |]} + +verify.codeFixAvailable(); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceDuplicateMember2.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceDuplicateMember2.ts new file mode 100644 index 0000000000000..ac90d51b07cfa --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceDuplicateMember2.ts @@ -0,0 +1,14 @@ +/// + +//// interface I1 { +//// x: number; +//// } +//// interface I2 { +//// x: number; +//// } +//// +//// class C implements I1,I2 { +//// x: number; +//// } + +verify.not.codeFixAvailable(); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceIndexSignaturesBoth.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceIndexSignaturesBoth.ts new file mode 100644 index 0000000000000..e47eeb6d5c17a --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceIndexSignaturesBoth.ts @@ -0,0 +1,14 @@ +/// + + +//// interface I { +//// [x: number]: I; +//// [y: string]: I; +//// } +//// +//// class C implements I {[| |]} + +verify.rangeAfterCodeFix(` + [x: number]: I; + [y: string]: I; +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceIndexSignaturesNoFix.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceIndexSignaturesNoFix.ts new file mode 100644 index 0000000000000..07896b4cdb37d --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceIndexSignaturesNoFix.ts @@ -0,0 +1,11 @@ +/// + +//// interface I4 { +//// [x: string, y: number]: number; +//// } +//// +//// class C implements I {[| |]} + +verify.not.codeFixAvailable(); + + diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceIndexSignaturesNumber.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceIndexSignaturesNumber.ts new file mode 100644 index 0000000000000..0f143442530bd --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceIndexSignaturesNumber.ts @@ -0,0 +1,12 @@ +/// + +//// interface I { +//// [x: number]: I; +//// } +//// +//// class C implements I {[| +//// |]} + +verify.rangeAfterCodeFix(` + [x: number]: I; +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceIndexSignaturesString.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceIndexSignaturesString.ts new file mode 100644 index 0000000000000..4b595c6eda7f3 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceIndexSignaturesString.ts @@ -0,0 +1,11 @@ +/// + +//// interface I { +//// [x: string]: X; +//// } +//// +//// class C implements I {[| |]} + +verify.rangeAfterCodeFix(` + [x: string]: number; +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceMethodWithParams.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceMethodWithParams.ts new file mode 100644 index 0000000000000..0ee842975e0c6 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceMethodWithParams.ts @@ -0,0 +1,14 @@ +/// + +//// interface I { +//// f(x: number, y: string): I +//// } +//// +//// class C implements I {[| +//// |]} + +verify.rangeAfterCodeFix(` +f(x: number,y: string): I { + throw new Error('Method not implemented.'); +} +`); diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleImplements1.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleImplements1.ts new file mode 100644 index 0000000000000..c8d61227c4928 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleImplements1.ts @@ -0,0 +1,19 @@ +/// + +//// interface I1 { +//// x: number; +//// } +//// interface I2 { +//// y: number; +//// } +//// +//// class C implements I1,I2 {[| +//// y: number; +//// |]} + +verify.rangeAfterCodeFix(` +x: number; +y: number; +`); + +verify.not.codeFixAvailable(); diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleImplements2.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleImplements2.ts new file mode 100644 index 0000000000000..d29b23998b8e6 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleImplements2.ts @@ -0,0 +1,19 @@ +/// + +//// interface I1 { +//// x: number; +//// } +//// interface I2 { +//// y: number; +//// } +//// +//// class C implements I1,I2 {[| +//// x: number; +//// |]} + +verify.rangeAfterCodeFix(` +y: number; +x: number; +`); + +verify.not.codeFixAvailable(); diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleImplementsIntersection1.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleImplementsIntersection1.ts new file mode 100644 index 0000000000000..321d41e463373 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleImplementsIntersection1.ts @@ -0,0 +1,13 @@ +/// + +//// interface I1 { +//// x: number; +//// } +//// interface I2 { +//// x: string; +//// } +//// +//// class C implements I1,I2 {[| +//// |]} + +verify.codeFixAvailable(); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleImplementsIntersection2.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleImplementsIntersection2.ts new file mode 100644 index 0000000000000..8f744e25cae19 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleImplementsIntersection2.ts @@ -0,0 +1,14 @@ +/// + +//// interface I1 { +//// x: number; +//// } +//// interface I2 { +//// x: string; +//// } +//// +//// class C implements I1,I2 { +//// x: string; +//// } + +verify.not.codeFixAvailable(); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleMembersAndPunctuation.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleMembersAndPunctuation.ts new file mode 100644 index 0000000000000..beab89c06a5c0 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleMembersAndPunctuation.ts @@ -0,0 +1,28 @@ +/// + +//// interface I1 { +//// x: number, +//// y: number +//// z: number; +//// f(), +//// g() +//// h(); +//// } +//// +//// class C1 implements I1 {[| +//// |]} + +verify.rangeAfterCodeFix(` +x: number; +y: number; +z: number; +f() { + throw new Error('Method not implemented.'); +} +g() { + throw new Error('Method not implemented.'); +} +h() { + throw new Error('Method not implemented.'); +} +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleSignatures.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleSignatures.ts new file mode 100644 index 0000000000000..bda58b3767dde --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleSignatures.ts @@ -0,0 +1,18 @@ +/// + +//// interface I { +//// method(a: number, b: string): boolean; +//// method(a: string, b: number): Function; +//// method(a: string): Function; +//// } +//// +//// class C implements I {[| |]} + +verify.rangeAfterCodeFix(` + method(a: number, b: string): boolean; + method(a: string, b: number): Function; + method(a: string): Function; + method(a: any, b?: any) { + throw new Error('Method not implemented.'); + } +`); diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleSignaturesRest1.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleSignaturesRest1.ts new file mode 100644 index 0000000000000..6e0a272a42a4c --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleSignaturesRest1.ts @@ -0,0 +1,18 @@ +/// + +//// interface I { +//// method(a: number, ...b: string[]): boolean; +//// method(a: string, ...b: number[]): Function; +//// method(a: string): Function; +//// } +//// +//// class C implements I {[| |]} + +verify.rangeAfterCodeFix(` + method(a: number, ...b: string[]): boolean; + method(a: string, ...b: number[]): Function; + method(a: string): Function; + method(a: any, ...b?: any[]) { + throw new Error('Method not implemented.'); + } +`); diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleSignaturesRest2.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleSignaturesRest2.ts new file mode 100644 index 0000000000000..7ba7ae2c98cee --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleSignaturesRest2.ts @@ -0,0 +1,18 @@ +/// + +//// interface I { +//// method(a: number, ...b: string[]): boolean; +//// method(a: string, b: number): Function; +//// method(a: string): Function; +//// } +//// +//// class C implements I {[| |]} + +verify.rangeAfterCodeFix(` + method(a: number, ...b: string[]): boolean; + method(a: string, b: number): Function; + method(a: string): Function; + method(a: any, b?: any, ...rest?: any[]) { + throw new Error('Method not implemented.'); + } +`); diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceNamespaceConflict.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceNamespaceConflict.ts new file mode 100644 index 0000000000000..4fea72aa48f90 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceNamespaceConflict.ts @@ -0,0 +1,17 @@ +/// + +//// namespace N1 { +//// export interface I1 { +//// x: number; +//// } +//// } +//// interface I1 { +//// f1(); +//// } +//// +//// class C1 implements N1.I1 {[| +//// |]} + +verify.rangeAfterCodeFix(` +x: number; +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterfacePropertyFromParentConstructorFunction.ts b/tests/cases/fourslash/codeFixClassImplementInterfacePropertyFromParentConstructorFunction.ts new file mode 100644 index 0000000000000..2a4ca4df92316 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfacePropertyFromParentConstructorFunction.ts @@ -0,0 +1,16 @@ +/// + +//// class A { +//// constructor(public x: number) { } +//// } +//// +//// class B implements A {[| |]} + +verify.not.codeFixAvailable(); + +// TODO: (arozga) Get this working. +/* +verify.rangeAfterCodeFix(` +public x: number; +`); +*/ diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceSomePropertiesPresent.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceSomePropertiesPresent.ts new file mode 100644 index 0000000000000..6e0658019f5d9 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceSomePropertiesPresent.ts @@ -0,0 +1,16 @@ +/// + +//// interface I { +//// x: number; +//// y: number; +//// z: number & { __iBrand: any }; +//// } +//// +//// class C implements I {[| |] +//// constructor(public x: number) { } +//// y: number; +//// } + +verify.rangeAfterCodeFix(` +z: number & { __iBrand: any; }; +`); diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceTypeParamInstantiateDeeply.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceTypeParamInstantiateDeeply.ts new file mode 100644 index 0000000000000..f76bd5dae9975 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceTypeParamInstantiateDeeply.ts @@ -0,0 +1,11 @@ +/// + +//// interface I { +//// x: { y: T, z: T[] }; +//// } +//// +//// class C implements I {[| |]} + +verify.rangeAfterCodeFix(` + x: { y: number; z: number[]; }; +`); diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceTypeParamInstantiateError.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceTypeParamInstantiateError.ts new file mode 100644 index 0000000000000..f4e433e9c0d9b --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceTypeParamInstantiateError.ts @@ -0,0 +1,13 @@ +/// + +//// interface I { +//// x: T; +//// } +//// +//// class C implements I { } + +verify.codeFixAvailable(); + +// TODO: (arozga) Don't know how to instantiate in codeFix +// if instantiation is invalid. +// verify.not.codeFixAvailable(); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceTypeParamInstantiateNumber.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceTypeParamInstantiateNumber.ts new file mode 100644 index 0000000000000..af0e7a162ee02 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceTypeParamInstantiateNumber.ts @@ -0,0 +1,11 @@ +/// + +//// interface I { +//// x: T; +//// } +//// +//// class C implements I {[| |]} + +verify.rangeAfterCodeFix(` + x: number; +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceTypeParamInstantiateT.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceTypeParamInstantiateT.ts new file mode 100644 index 0000000000000..45fa3fd40cae1 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceTypeParamInstantiateT.ts @@ -0,0 +1,11 @@ +/// + +//// interface I { +//// x: T; +//// } +//// +//// class C implements I {[| |]} + +verify.rangeAfterCodeFix(` + x: T; +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceTypeParamInstantiateU.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceTypeParamInstantiateU.ts new file mode 100644 index 0000000000000..16c35f4177380 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceTypeParamInstantiateU.ts @@ -0,0 +1,11 @@ +/// + +//// interface I { +//// x: T; +//// } +//// +//// class C implements I {[| |]} + +verify.rangeAfterCodeFix(` + x: U; +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceTypeParamInstantiation.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceTypeParamInstantiation.ts new file mode 100644 index 0000000000000..226aee4783390 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceTypeParamInstantiation.ts @@ -0,0 +1,9 @@ +/// + +//// interface I { +//// x: T; +//// } +//// +//// class C implements I { } + +verify.not.codeFixAvailable(); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceTypeParamMethod.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceTypeParamMethod.ts new file mode 100644 index 0000000000000..4d6afaefedcdf --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceTypeParamMethod.ts @@ -0,0 +1,12 @@ +/// + +//// interface I { +//// f(x: T); +//// } +//// +//// class C implements I {[| |]} + +verify.rangeAfterCodeFix(`f(x: T){ + throw new Error('Method not implemented.'); +} +`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceUndeclaredSymbol.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceUndeclaredSymbol.ts new file mode 100644 index 0000000000000..0acf60645c9c4 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceUndeclaredSymbol.ts @@ -0,0 +1,19 @@ +/// + +//// interface I { +//// x: T; +//// } +//// +//// class C implements I { } + +// T is not a declared symbol. There are a couple fixes: +// 1) Declare T. +// 2) Rename T to an existing symbol. +// 3) Make T a type parameter to I. +// +// In the latter two cases, it is premature to copy `x:T` into C. +// Since we can't guess the programmer's intent here, we do nothing. + +verify.codeFixAvailable(); +// TODO: (aozgaa) Acknowledge other errors on class/implemented interface/extended abstract class. +// verify.not.codeFixAvailable(); \ No newline at end of file diff --git a/tests/cases/fourslash/superFix2.ts b/tests/cases/fourslash/codeFixSuperAfterThis.ts similarity index 76% rename from tests/cases/fourslash/superFix2.ts rename to tests/cases/fourslash/codeFixSuperAfterThis.ts index 880b5d43167c4..2bff98ceca015 100644 --- a/tests/cases/fourslash/superFix2.ts +++ b/tests/cases/fourslash/codeFixSuperAfterThis.ts @@ -10,4 +10,4 @@ //// } ////} -verify.codeFixAtPosition("super(); this.a = 12;"); \ No newline at end of file +verify.rangeAfterCodeFix("super(); this.a = 12;"); \ No newline at end of file diff --git a/tests/cases/fourslash/server/codefix.ts b/tests/cases/fourslash/codeFixSuperCall.ts similarity index 73% rename from tests/cases/fourslash/server/codefix.ts rename to tests/cases/fourslash/codeFixSuperCall.ts index 9d0f42c9e4c6d..c918e74dc38b4 100644 --- a/tests/cases/fourslash/server/codefix.ts +++ b/tests/cases/fourslash/codeFixSuperCall.ts @@ -7,4 +7,4 @@ //// } ////} -verify.codeFixAtPosition('super();'); +verify.rangeAfterCodeFix('super();'); diff --git a/tests/cases/fourslash/superFix3.ts b/tests/cases/fourslash/codeFixSuperCallWithThisInside.ts similarity index 100% rename from tests/cases/fourslash/superFix3.ts rename to tests/cases/fourslash/codeFixSuperCallWithThisInside.ts diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 745a746db116b..683e4742839b1 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -208,7 +208,7 @@ declare namespace FourSlashInterface { noMatchingBracePositionInCurrentFile(bracePosition: number): void; DocCommentTemplate(expectedText: string, expectedOffset: number, empty?: boolean): void; noDocCommentTemplate(): void; - codeFixAtPosition(expectedText: string, errorCode?: number): void; + rangeAfterCodeFix(expectedText: string, errorCode?: number): void; importFixAtPosition(expectedTextArray: string[], errorCode?: number): void; navigationBar(json: any): void; diff --git a/tests/cases/fourslash/superFix1.ts b/tests/cases/fourslash/superFix1.ts deleted file mode 100644 index 7fbe2cb4fd7bd..0000000000000 --- a/tests/cases/fourslash/superFix1.ts +++ /dev/null @@ -1,10 +0,0 @@ -/// - -////class Base{ -////} -////class C extends Base{ -//// constructor() {[| |] -//// } -////} - -verify.codeFixAtPosition('super();'); diff --git a/tests/cases/fourslash/unusedClassInNamespace1.ts b/tests/cases/fourslash/unusedClassInNamespace1.ts index 586202ab0c7d4..e13c889d3279c 100644 --- a/tests/cases/fourslash/unusedClassInNamespace1.ts +++ b/tests/cases/fourslash/unusedClassInNamespace1.ts @@ -6,5 +6,5 @@ //// } //// } |] -verify.codeFixAtPosition(`namespace greeter { +verify.rangeAfterCodeFix(`namespace greeter { }`); diff --git a/tests/cases/fourslash/unusedClassInNamespace2.ts b/tests/cases/fourslash/unusedClassInNamespace2.ts index c182f4e3655dc..0b6b7504633ec 100644 --- a/tests/cases/fourslash/unusedClassInNamespace2.ts +++ b/tests/cases/fourslash/unusedClassInNamespace2.ts @@ -8,7 +8,7 @@ //// } //// } |] -verify.codeFixAtPosition(`namespace greeter { +verify.rangeAfterCodeFix(`namespace greeter { export class class2 { } }`); diff --git a/tests/cases/fourslash/unusedClassInNamespace3.ts b/tests/cases/fourslash/unusedClassInNamespace3.ts index 391c5e833efac..95e691d3ee1a9 100644 --- a/tests/cases/fourslash/unusedClassInNamespace3.ts +++ b/tests/cases/fourslash/unusedClassInNamespace3.ts @@ -16,7 +16,7 @@ //// } ////} |] -verify.codeFixAtPosition(`namespace Validation { +verify.rangeAfterCodeFix(`namespace Validation { class c1 { } diff --git a/tests/cases/fourslash/unusedClassInNamespace4.ts b/tests/cases/fourslash/unusedClassInNamespace4.ts index 5db5b1aefa65d..8b856379acbf0 100644 --- a/tests/cases/fourslash/unusedClassInNamespace4.ts +++ b/tests/cases/fourslash/unusedClassInNamespace4.ts @@ -16,7 +16,7 @@ //// } ////} |] -verify.codeFixAtPosition(`namespace Validation { +verify.rangeAfterCodeFix(`namespace Validation { class c1 { } diff --git a/tests/cases/fourslash/unusedConstantInFunction1.ts b/tests/cases/fourslash/unusedConstantInFunction1.ts index df37325780997..b0fe913e72246 100644 --- a/tests/cases/fourslash/unusedConstantInFunction1.ts +++ b/tests/cases/fourslash/unusedConstantInFunction1.ts @@ -5,6 +5,6 @@ //// const x: string = "x"; //// } |] -verify.codeFixAtPosition(`function f1 () { +verify.rangeAfterCodeFix(`function f1 () { }`); diff --git a/tests/cases/fourslash/unusedEnumInFunction1.ts b/tests/cases/fourslash/unusedEnumInFunction1.ts index 1d88f07ebf76b..ae72b7b3da61d 100644 --- a/tests/cases/fourslash/unusedEnumInFunction1.ts +++ b/tests/cases/fourslash/unusedEnumInFunction1.ts @@ -5,7 +5,7 @@ //// enum Directions { Up, Down} //// } |] -verify.codeFixAtPosition(`function f1 () { +verify.rangeAfterCodeFix(`function f1 () { } `); diff --git a/tests/cases/fourslash/unusedEnumInNamespace1.ts b/tests/cases/fourslash/unusedEnumInNamespace1.ts index 88e8e32d5f867..e856a084bfee4 100644 --- a/tests/cases/fourslash/unusedEnumInNamespace1.ts +++ b/tests/cases/fourslash/unusedEnumInNamespace1.ts @@ -7,5 +7,5 @@ //// } //// } |] -verify.codeFixAtPosition(`namespace greeter { +verify.rangeAfterCodeFix(`namespace greeter { }`); diff --git a/tests/cases/fourslash/unusedFunctionInNamespace1.ts b/tests/cases/fourslash/unusedFunctionInNamespace1.ts index e0f6b2e18ac15..8ebf1f7072aaf 100644 --- a/tests/cases/fourslash/unusedFunctionInNamespace1.ts +++ b/tests/cases/fourslash/unusedFunctionInNamespace1.ts @@ -6,5 +6,5 @@ //// }/*1*/ //// } |] -verify.codeFixAtPosition(`namespace greeter { +verify.rangeAfterCodeFix(`namespace greeter { }`); diff --git a/tests/cases/fourslash/unusedFunctionInNamespace2.ts b/tests/cases/fourslash/unusedFunctionInNamespace2.ts index c823777048e2e..5a2ac44d3d0e1 100644 --- a/tests/cases/fourslash/unusedFunctionInNamespace2.ts +++ b/tests/cases/fourslash/unusedFunctionInNamespace2.ts @@ -8,7 +8,7 @@ //// } ////} |] -verify.codeFixAtPosition(`namespace greeter { +verify.rangeAfterCodeFix(`namespace greeter { export function function2() { } }`); diff --git a/tests/cases/fourslash/unusedFunctionInNamespace3.ts b/tests/cases/fourslash/unusedFunctionInNamespace3.ts index 144e9f325b444..69df15cb3c7aa 100644 --- a/tests/cases/fourslash/unusedFunctionInNamespace3.ts +++ b/tests/cases/fourslash/unusedFunctionInNamespace3.ts @@ -8,5 +8,5 @@ //// } ////} |] -verify.codeFixAtPosition(`namespace Validation { +verify.rangeAfterCodeFix(`namespace Validation { }`); diff --git a/tests/cases/fourslash/unusedFunctionInNamespace4.ts b/tests/cases/fourslash/unusedFunctionInNamespace4.ts index 5b5995da9c745..36ceb319ff920 100644 --- a/tests/cases/fourslash/unusedFunctionInNamespace4.ts +++ b/tests/cases/fourslash/unusedFunctionInNamespace4.ts @@ -7,5 +7,5 @@ //// } ////} |] -verify.codeFixAtPosition(`namespace Validation { +verify.rangeAfterCodeFix(`namespace Validation { }`); diff --git a/tests/cases/fourslash/unusedFunctionInNamespace5.ts b/tests/cases/fourslash/unusedFunctionInNamespace5.ts index b839d9dcd976b..3c2f20ce082c7 100644 --- a/tests/cases/fourslash/unusedFunctionInNamespace5.ts +++ b/tests/cases/fourslash/unusedFunctionInNamespace5.ts @@ -21,7 +21,7 @@ //// export let a = function3; |] ////} -verify.codeFixAtPosition(`function function3() { +verify.rangeAfterCodeFix(`function function3() { function1(); } diff --git a/tests/cases/fourslash/unusedImports10FS.ts b/tests/cases/fourslash/unusedImports10FS.ts index f9d38e4cfb0ef..ea016b73cc2f0 100644 --- a/tests/cases/fourslash/unusedImports10FS.ts +++ b/tests/cases/fourslash/unusedImports10FS.ts @@ -12,5 +12,5 @@ //// [|import a = A;|] //// } -verify.codeFixAtPosition(""); +verify.rangeAfterCodeFix(""); diff --git a/tests/cases/fourslash/unusedImports11FS.ts b/tests/cases/fourslash/unusedImports11FS.ts index a18a4634d719b..c29b5612e8889 100644 --- a/tests/cases/fourslash/unusedImports11FS.ts +++ b/tests/cases/fourslash/unusedImports11FS.ts @@ -11,4 +11,4 @@ //// export function f2(s: string){}; //// export default f1; -verify.codeFixAtPosition('import * as s from "./file1";'); \ No newline at end of file +verify.rangeAfterCodeFix('import * as s from "./file1";'); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedImports12FS.ts b/tests/cases/fourslash/unusedImports12FS.ts index 4d8243eb4abf0..d86bc98c6cfac 100644 --- a/tests/cases/fourslash/unusedImports12FS.ts +++ b/tests/cases/fourslash/unusedImports12FS.ts @@ -10,4 +10,4 @@ //// export function f2(s: string){}; //// export default f1; -verify.codeFixAtPosition('import f1 from "./file1";'); \ No newline at end of file +verify.rangeAfterCodeFix('import f1 from "./file1";'); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedImports1FS.ts b/tests/cases/fourslash/unusedImports1FS.ts index d9fc17a244846..0fc2d36aac7ca 100644 --- a/tests/cases/fourslash/unusedImports1FS.ts +++ b/tests/cases/fourslash/unusedImports1FS.ts @@ -9,4 +9,4 @@ //// //// } -verify.codeFixAtPosition(''); +verify.rangeAfterCodeFix(''); diff --git a/tests/cases/fourslash/unusedImports2FS.ts b/tests/cases/fourslash/unusedImports2FS.ts index 6e3d9527c52e2..d2062fc49583c 100644 --- a/tests/cases/fourslash/unusedImports2FS.ts +++ b/tests/cases/fourslash/unusedImports2FS.ts @@ -16,4 +16,4 @@ //// //// } -verify.codeFixAtPosition(`import {Calculator} from "./file1"`); +verify.rangeAfterCodeFix(`import {Calculator} from "./file1"`); diff --git a/tests/cases/fourslash/unusedImports3FS.ts b/tests/cases/fourslash/unusedImports3FS.ts index 205666e971d84..98dc30c4336da 100644 --- a/tests/cases/fourslash/unusedImports3FS.ts +++ b/tests/cases/fourslash/unusedImports3FS.ts @@ -20,5 +20,5 @@ //// //// } -verify.codeFixAtPosition(`import {test, test2} from "./file1"`); +verify.rangeAfterCodeFix(`import {test, test2} from "./file1"`); diff --git a/tests/cases/fourslash/unusedImports4FS.ts b/tests/cases/fourslash/unusedImports4FS.ts index 302007748f442..4f7e888242906 100644 --- a/tests/cases/fourslash/unusedImports4FS.ts +++ b/tests/cases/fourslash/unusedImports4FS.ts @@ -21,4 +21,4 @@ //// //// } -verify.codeFixAtPosition(`import {Calculator, test2} from "./file1"`); \ No newline at end of file +verify.rangeAfterCodeFix(`import {Calculator, test2} from "./file1"`); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedImports5FS.ts b/tests/cases/fourslash/unusedImports5FS.ts index 1d68f6ae64383..15262df01fdcb 100644 --- a/tests/cases/fourslash/unusedImports5FS.ts +++ b/tests/cases/fourslash/unusedImports5FS.ts @@ -21,4 +21,4 @@ //// //// } -verify.codeFixAtPosition(`import {Calculator, test} from "./file1"`); \ No newline at end of file +verify.rangeAfterCodeFix(`import {Calculator, test} from "./file1"`); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedImports6FS.ts b/tests/cases/fourslash/unusedImports6FS.ts index a5c6744855af2..1d6a9a3232e95 100644 --- a/tests/cases/fourslash/unusedImports6FS.ts +++ b/tests/cases/fourslash/unusedImports6FS.ts @@ -17,4 +17,4 @@ //// //// } -verify.codeFixAtPosition(''); \ No newline at end of file +verify.rangeAfterCodeFix(''); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedImports7FS.ts b/tests/cases/fourslash/unusedImports7FS.ts index 23066ef538d55..1a23ea85925ca 100644 --- a/tests/cases/fourslash/unusedImports7FS.ts +++ b/tests/cases/fourslash/unusedImports7FS.ts @@ -13,4 +13,4 @@ //// export default function test2() { //// } -verify.codeFixAtPosition(''); \ No newline at end of file +verify.rangeAfterCodeFix(''); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedImports8FS.ts b/tests/cases/fourslash/unusedImports8FS.ts index 02564e359895d..81bdeda36aca7 100644 --- a/tests/cases/fourslash/unusedImports8FS.ts +++ b/tests/cases/fourslash/unusedImports8FS.ts @@ -21,4 +21,4 @@ //// //// } -verify.codeFixAtPosition(`import {Calculator as calc, test as t1} from "./file1"`); \ No newline at end of file +verify.rangeAfterCodeFix(`import {Calculator as calc, test as t1} from "./file1"`); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedImports9FS.ts b/tests/cases/fourslash/unusedImports9FS.ts index 324d57a1928c4..f81f9a9f5aec7 100644 --- a/tests/cases/fourslash/unusedImports9FS.ts +++ b/tests/cases/fourslash/unusedImports9FS.ts @@ -17,4 +17,4 @@ //// //// } -verify.codeFixAtPosition(""); \ No newline at end of file +verify.rangeAfterCodeFix(""); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedInterfaceInNamespace1.ts b/tests/cases/fourslash/unusedInterfaceInNamespace1.ts index 8d07a8c79121e..f979069690be2 100644 --- a/tests/cases/fourslash/unusedInterfaceInNamespace1.ts +++ b/tests/cases/fourslash/unusedInterfaceInNamespace1.ts @@ -6,6 +6,6 @@ //// } ////} |] -verify.codeFixAtPosition(` +verify.rangeAfterCodeFix(` namespace greeter { }`); diff --git a/tests/cases/fourslash/unusedInterfaceInNamespace2.ts b/tests/cases/fourslash/unusedInterfaceInNamespace2.ts index baa46c65a0ce6..7737f9ce24705 100644 --- a/tests/cases/fourslash/unusedInterfaceInNamespace2.ts +++ b/tests/cases/fourslash/unusedInterfaceInNamespace2.ts @@ -8,5 +8,5 @@ //// } |] ////} -verify.codeFixAtPosition(`export interface interface2 { +verify.rangeAfterCodeFix(`export interface interface2 { }`); diff --git a/tests/cases/fourslash/unusedLocalsInFunction1.ts b/tests/cases/fourslash/unusedLocalsInFunction1.ts index 2edd7c176e7dd..e74f5dbd96211 100644 --- a/tests/cases/fourslash/unusedLocalsInFunction1.ts +++ b/tests/cases/fourslash/unusedLocalsInFunction1.ts @@ -5,6 +5,6 @@ //// var x = 0; ////} |] -verify.codeFixAtPosition(` +verify.rangeAfterCodeFix(` function greeter() { }`); diff --git a/tests/cases/fourslash/unusedLocalsInFunction2.ts b/tests/cases/fourslash/unusedLocalsInFunction2.ts index b709432804118..83816e68038c9 100644 --- a/tests/cases/fourslash/unusedLocalsInFunction2.ts +++ b/tests/cases/fourslash/unusedLocalsInFunction2.ts @@ -6,4 +6,4 @@ //// x+1; ////} -verify.codeFixAtPosition("var x;"); +verify.rangeAfterCodeFix("var x;"); diff --git a/tests/cases/fourslash/unusedLocalsInFunction3.ts b/tests/cases/fourslash/unusedLocalsInFunction3.ts index 906517ee0a78b..7aa9b20a33ce3 100644 --- a/tests/cases/fourslash/unusedLocalsInFunction3.ts +++ b/tests/cases/fourslash/unusedLocalsInFunction3.ts @@ -7,4 +7,4 @@ //// z+1; ////} -verify.codeFixAtPosition("var x,z = 1;", 6133); +verify.rangeAfterCodeFix("var x,z = 1;", 6133); diff --git a/tests/cases/fourslash/unusedLocalsInFunction4.ts b/tests/cases/fourslash/unusedLocalsInFunction4.ts index 54d3223f23608..a458d6d824c93 100644 --- a/tests/cases/fourslash/unusedLocalsInFunction4.ts +++ b/tests/cases/fourslash/unusedLocalsInFunction4.ts @@ -7,4 +7,4 @@ //// z++; ////} -verify.codeFixAtPosition("var y = 0,z = 1;"); +verify.rangeAfterCodeFix("var y = 0,z = 1;"); diff --git a/tests/cases/fourslash/unusedLocalsInMethodFS1.ts b/tests/cases/fourslash/unusedLocalsInMethodFS1.ts index 43b782ce2661a..dc73ab86663b5 100644 --- a/tests/cases/fourslash/unusedLocalsInMethodFS1.ts +++ b/tests/cases/fourslash/unusedLocalsInMethodFS1.ts @@ -9,4 +9,4 @@ //// } ////} -verify.codeFixAtPosition("var y = 10;"); +verify.rangeAfterCodeFix("var y = 10;"); diff --git a/tests/cases/fourslash/unusedLocalsInMethodFS2.ts b/tests/cases/fourslash/unusedLocalsInMethodFS2.ts index 322cfad394007..012bf87a2222a 100644 --- a/tests/cases/fourslash/unusedLocalsInMethodFS2.ts +++ b/tests/cases/fourslash/unusedLocalsInMethodFS2.ts @@ -9,4 +9,4 @@ //// } ////} -verify.codeFixAtPosition("var y;"); +verify.rangeAfterCodeFix("var y;"); diff --git a/tests/cases/fourslash/unusedLocalsinConstructorFS1.ts b/tests/cases/fourslash/unusedLocalsinConstructorFS1.ts index 412b599b780a9..4ed58d3142d7f 100644 --- a/tests/cases/fourslash/unusedLocalsinConstructorFS1.ts +++ b/tests/cases/fourslash/unusedLocalsinConstructorFS1.ts @@ -8,5 +8,5 @@ //// } |] ////} -verify.codeFixAtPosition(`constructor() { +verify.rangeAfterCodeFix(`constructor() { }`); diff --git a/tests/cases/fourslash/unusedLocalsinConstructorFS2.ts b/tests/cases/fourslash/unusedLocalsinConstructorFS2.ts index eff9b7c8d54b5..eeaf66050d44a 100644 --- a/tests/cases/fourslash/unusedLocalsinConstructorFS2.ts +++ b/tests/cases/fourslash/unusedLocalsinConstructorFS2.ts @@ -10,7 +10,7 @@ //// }|] ////} -verify.codeFixAtPosition(` +verify.rangeAfterCodeFix(` constructor() { var used = "dummy"; used = used + "second part"; diff --git a/tests/cases/fourslash/unusedMethodInClass1.ts b/tests/cases/fourslash/unusedMethodInClass1.ts index 7795a4d15303e..a5e3789c8af7f 100644 --- a/tests/cases/fourslash/unusedMethodInClass1.ts +++ b/tests/cases/fourslash/unusedMethodInClass1.ts @@ -6,6 +6,6 @@ //// } ////} |] -verify.codeFixAtPosition(` +verify.rangeAfterCodeFix(` class greeter { }`); diff --git a/tests/cases/fourslash/unusedMethodInClass2.ts b/tests/cases/fourslash/unusedMethodInClass2.ts index 24b6fe155efb5..cce621236d4df 100644 --- a/tests/cases/fourslash/unusedMethodInClass2.ts +++ b/tests/cases/fourslash/unusedMethodInClass2.ts @@ -8,7 +8,7 @@ //// } ////} |] -verify.codeFixAtPosition(` +verify.rangeAfterCodeFix(` class greeter { public function2() { } diff --git a/tests/cases/fourslash/unusedMethodInClass3.ts b/tests/cases/fourslash/unusedMethodInClass3.ts index eab535fb5af66..ccf98c4bbc52b 100644 --- a/tests/cases/fourslash/unusedMethodInClass3.ts +++ b/tests/cases/fourslash/unusedMethodInClass3.ts @@ -6,6 +6,6 @@ //// } ////} |] -verify.codeFixAtPosition(` +verify.rangeAfterCodeFix(` class greeter { }`); diff --git a/tests/cases/fourslash/unusedMethodInClass4.ts b/tests/cases/fourslash/unusedMethodInClass4.ts index ee27ec331eb84..962b80f5bc142 100644 --- a/tests/cases/fourslash/unusedMethodInClass4.ts +++ b/tests/cases/fourslash/unusedMethodInClass4.ts @@ -8,5 +8,5 @@ //// } |] ////} -verify.codeFixAtPosition(`public function2(){ +verify.rangeAfterCodeFix(`public function2(){ }`); diff --git a/tests/cases/fourslash/unusedMethodInClass5.ts b/tests/cases/fourslash/unusedMethodInClass5.ts index 36ef3670cac0e..806e619817f89 100644 --- a/tests/cases/fourslash/unusedMethodInClass5.ts +++ b/tests/cases/fourslash/unusedMethodInClass5.ts @@ -5,4 +5,4 @@ //// private ["string"] (){} //// }|] -verify.codeFixAtPosition("class C { }"); \ No newline at end of file +verify.rangeAfterCodeFix("class C { }"); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedMethodInClass6.ts b/tests/cases/fourslash/unusedMethodInClass6.ts index 71fcb92d037b8..d223b3d6857ec 100644 --- a/tests/cases/fourslash/unusedMethodInClass6.ts +++ b/tests/cases/fourslash/unusedMethodInClass6.ts @@ -5,4 +5,4 @@ //// private "string" (){} //// }|] -verify.codeFixAtPosition("class C { }"); \ No newline at end of file +verify.rangeAfterCodeFix("class C { }"); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedNamespaceInNamespace.ts b/tests/cases/fourslash/unusedNamespaceInNamespace.ts index 41fe162ef1564..802336454c6f8 100644 --- a/tests/cases/fourslash/unusedNamespaceInNamespace.ts +++ b/tests/cases/fourslash/unusedNamespaceInNamespace.ts @@ -6,7 +6,7 @@ //// } //// }|] -verify.codeFixAtPosition(` +verify.rangeAfterCodeFix(` namespace A { } `); diff --git a/tests/cases/fourslash/unusedParameterInConstructor1.ts b/tests/cases/fourslash/unusedParameterInConstructor1.ts index f53c6d3e8bdde..36539e6649b80 100644 --- a/tests/cases/fourslash/unusedParameterInConstructor1.ts +++ b/tests/cases/fourslash/unusedParameterInConstructor1.ts @@ -5,4 +5,4 @@ //// [|constructor(private p1: string, public p2: boolean, public p3: any, p5)|] { p5; } //// } -verify.codeFixAtPosition("constructor(public p2: boolean, public p3: any, p5)"); \ No newline at end of file +verify.rangeAfterCodeFix("constructor(public p2: boolean, public p3: any, p5)"); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedParameterInConstructor2.ts b/tests/cases/fourslash/unusedParameterInConstructor2.ts index bd5f66ff96685..e822a2f248d0a 100644 --- a/tests/cases/fourslash/unusedParameterInConstructor2.ts +++ b/tests/cases/fourslash/unusedParameterInConstructor2.ts @@ -5,4 +5,4 @@ //// [|constructor(public p1: string, private p2: boolean, public p3: any, p5)|] { p5; } //// } -verify.codeFixAtPosition("constructor(public p1: string, public p3: any, p5)"); \ No newline at end of file +verify.rangeAfterCodeFix("constructor(public p1: string, public p3: any, p5)"); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedParameterInConstructor3.ts b/tests/cases/fourslash/unusedParameterInConstructor3.ts index 173e00113d8f0..1a9682aece38a 100644 --- a/tests/cases/fourslash/unusedParameterInConstructor3.ts +++ b/tests/cases/fourslash/unusedParameterInConstructor3.ts @@ -5,4 +5,4 @@ //// [|constructor(public p1: string, public p2: boolean, private p3: any, p5)|] { p5; } //// } -verify.codeFixAtPosition("constructor(public p1: string, public p2: boolean, p5)"); \ No newline at end of file +verify.rangeAfterCodeFix("constructor(public p1: string, public p2: boolean, p5)"); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedParameterInConstructor4.ts b/tests/cases/fourslash/unusedParameterInConstructor4.ts index 6d0223dc5f4fd..01df43718dac9 100644 --- a/tests/cases/fourslash/unusedParameterInConstructor4.ts +++ b/tests/cases/fourslash/unusedParameterInConstructor4.ts @@ -5,4 +5,4 @@ //// [|constructor(private readonly p2: boolean, p5)|] { p5; } //// } -verify.codeFixAtPosition("constructor(p5)"); \ No newline at end of file +verify.rangeAfterCodeFix("constructor(p5)"); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedParameterInFunction1.ts b/tests/cases/fourslash/unusedParameterInFunction1.ts index 2243af9f5f553..baaccbbd20f46 100644 --- a/tests/cases/fourslash/unusedParameterInFunction1.ts +++ b/tests/cases/fourslash/unusedParameterInFunction1.ts @@ -4,4 +4,4 @@ ////function [|greeter( x)|] { ////} -verify.codeFixAtPosition("greeter()"); +verify.rangeAfterCodeFix("greeter()"); diff --git a/tests/cases/fourslash/unusedParameterInFunction2.ts b/tests/cases/fourslash/unusedParameterInFunction2.ts index 493eafc572223..0e448c98fccc8 100644 --- a/tests/cases/fourslash/unusedParameterInFunction2.ts +++ b/tests/cases/fourslash/unusedParameterInFunction2.ts @@ -5,4 +5,4 @@ //// x++; ////} -verify.codeFixAtPosition("greeter(x)"); \ No newline at end of file +verify.rangeAfterCodeFix("greeter(x)"); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedParameterInFunction3.ts b/tests/cases/fourslash/unusedParameterInFunction3.ts index 6d79ba071b450..23f45475950fa 100644 --- a/tests/cases/fourslash/unusedParameterInFunction3.ts +++ b/tests/cases/fourslash/unusedParameterInFunction3.ts @@ -5,4 +5,4 @@ //// y++; ////} -verify.codeFixAtPosition("greeter(y)"); \ No newline at end of file +verify.rangeAfterCodeFix("greeter(y)"); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedParameterInFunction4.ts b/tests/cases/fourslash/unusedParameterInFunction4.ts index b536543fb6d59..1f98238d647ae 100644 --- a/tests/cases/fourslash/unusedParameterInFunction4.ts +++ b/tests/cases/fourslash/unusedParameterInFunction4.ts @@ -6,4 +6,4 @@ //// z++; ////} -verify.codeFixAtPosition("function greeter(x,z)"); \ No newline at end of file +verify.rangeAfterCodeFix("function greeter(x,z)"); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedParameterInLambda1.ts b/tests/cases/fourslash/unusedParameterInLambda1.ts index c462b7425694d..166d250fee755 100644 --- a/tests/cases/fourslash/unusedParameterInLambda1.ts +++ b/tests/cases/fourslash/unusedParameterInLambda1.ts @@ -6,4 +6,4 @@ //// [|return (x:number) => {}|] //// } -verify.codeFixAtPosition("return () => {}"); +verify.rangeAfterCodeFix("return () => {}"); diff --git a/tests/cases/fourslash/unusedTypeAliasInNamespace1.ts b/tests/cases/fourslash/unusedTypeAliasInNamespace1.ts index 593c0fe8cf433..2314ebbe447e9 100644 --- a/tests/cases/fourslash/unusedTypeAliasInNamespace1.ts +++ b/tests/cases/fourslash/unusedTypeAliasInNamespace1.ts @@ -6,6 +6,6 @@ //// export type nw = "No" | "Way"; //// } |] -verify.codeFixAtPosition(`namespace greeter { +verify.rangeAfterCodeFix(`namespace greeter { export type nw = "No" | "Way"; }`); diff --git a/tests/cases/fourslash/unusedTypeParametersInClass1.ts b/tests/cases/fourslash/unusedTypeParametersInClass1.ts index ab654a5150e73..322921ab47133 100644 --- a/tests/cases/fourslash/unusedTypeParametersInClass1.ts +++ b/tests/cases/fourslash/unusedTypeParametersInClass1.ts @@ -4,4 +4,4 @@ ////[|class greeter |] { ////} -verify.codeFixAtPosition("class greeter"); \ No newline at end of file +verify.rangeAfterCodeFix("class greeter"); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedTypeParametersInClass2.ts b/tests/cases/fourslash/unusedTypeParametersInClass2.ts index 8e860c10e049b..feaf9d3a14b77 100644 --- a/tests/cases/fourslash/unusedTypeParametersInClass2.ts +++ b/tests/cases/fourslash/unusedTypeParametersInClass2.ts @@ -5,4 +5,4 @@ //// public a: X; ////} -verify.codeFixAtPosition("class greeter"); \ No newline at end of file +verify.rangeAfterCodeFix("class greeter"); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedTypeParametersInClass3.ts b/tests/cases/fourslash/unusedTypeParametersInClass3.ts index 75ae98f53e0ed..b1151265fe351 100644 --- a/tests/cases/fourslash/unusedTypeParametersInClass3.ts +++ b/tests/cases/fourslash/unusedTypeParametersInClass3.ts @@ -6,4 +6,4 @@ //// public b: Z; ////} -verify.codeFixAtPosition("class greeter"); +verify.rangeAfterCodeFix("class greeter"); diff --git a/tests/cases/fourslash/unusedTypeParametersInFunction1.ts b/tests/cases/fourslash/unusedTypeParametersInFunction1.ts index 7177ed41c8445..a11156badaaa9 100644 --- a/tests/cases/fourslash/unusedTypeParametersInFunction1.ts +++ b/tests/cases/fourslash/unusedTypeParametersInFunction1.ts @@ -3,4 +3,4 @@ // @noUnusedLocals: true //// [|function f1() {}|] -verify.codeFixAtPosition("function f1() {}"); +verify.rangeAfterCodeFix("function f1() {}"); diff --git a/tests/cases/fourslash/unusedTypeParametersInFunction2.ts b/tests/cases/fourslash/unusedTypeParametersInFunction2.ts index 344ae303c75df..a011f093dab32 100644 --- a/tests/cases/fourslash/unusedTypeParametersInFunction2.ts +++ b/tests/cases/fourslash/unusedTypeParametersInFunction2.ts @@ -3,4 +3,4 @@ // @noUnusedLocals: true //// [|function f1(a: X) {a}|] -verify.codeFixAtPosition("function f1(a: X) {a}"); +verify.rangeAfterCodeFix("function f1(a: X) {a}"); diff --git a/tests/cases/fourslash/unusedTypeParametersInFunction3.ts b/tests/cases/fourslash/unusedTypeParametersInFunction3.ts index 746b174db18d9..6dc56ccc7cbfd 100644 --- a/tests/cases/fourslash/unusedTypeParametersInFunction3.ts +++ b/tests/cases/fourslash/unusedTypeParametersInFunction3.ts @@ -3,4 +3,4 @@ // @noUnusedLocals: true //// [|function f1(a: X) {a;var b:Z;b}|] -verify.codeFixAtPosition("function f1(a: X) {a;var b:Z;b}"); +verify.rangeAfterCodeFix("function f1(a: X) {a;var b:Z;b}"); diff --git a/tests/cases/fourslash/unusedTypeParametersInInterface1.ts b/tests/cases/fourslash/unusedTypeParametersInInterface1.ts index 70d8bc7800cd8..b5363b369be70 100644 --- a/tests/cases/fourslash/unusedTypeParametersInInterface1.ts +++ b/tests/cases/fourslash/unusedTypeParametersInInterface1.ts @@ -4,4 +4,4 @@ // @noUnusedParameters: true //// [|interface I {}|] -verify.codeFixAtPosition("interface I {}"); \ No newline at end of file +verify.rangeAfterCodeFix("interface I {}"); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedTypeParametersInLambda1.ts b/tests/cases/fourslash/unusedTypeParametersInLambda1.ts index 73d7067236850..01c1ebd24f52d 100644 --- a/tests/cases/fourslash/unusedTypeParametersInLambda1.ts +++ b/tests/cases/fourslash/unusedTypeParametersInLambda1.ts @@ -6,4 +6,4 @@ //// [|return (x:number) => {x}|] //// } -verify.codeFixAtPosition("return (x:number) => {x}"); +verify.rangeAfterCodeFix("return (x:number) => {x}"); diff --git a/tests/cases/fourslash/unusedTypeParametersInLambda2.ts b/tests/cases/fourslash/unusedTypeParametersInLambda2.ts index 77c802f5c44f3..e5a4acc31c53e 100644 --- a/tests/cases/fourslash/unusedTypeParametersInLambda2.ts +++ b/tests/cases/fourslash/unusedTypeParametersInLambda2.ts @@ -6,4 +6,4 @@ //// [|new (a: T): void;|] //// } -verify.codeFixAtPosition("new (a: T): void;"); +verify.rangeAfterCodeFix("new (a: T): void;"); diff --git a/tests/cases/fourslash/unusedTypeParametersInLambda3.ts b/tests/cases/fourslash/unusedTypeParametersInLambda3.ts index 0ecb0338be2ce..e6d866dcb6aaa 100644 --- a/tests/cases/fourslash/unusedTypeParametersInLambda3.ts +++ b/tests/cases/fourslash/unusedTypeParametersInLambda3.ts @@ -7,4 +7,4 @@ //// [|new (a: T): A;|] //// } -verify.codeFixAtPosition("new (a: T): A;"); +verify.rangeAfterCodeFix("new (a: T): A;"); diff --git a/tests/cases/fourslash/unusedTypeParametersInLambda4.ts b/tests/cases/fourslash/unusedTypeParametersInLambda4.ts index 5a226fc9005ef..04bd7c7e9becf 100644 --- a/tests/cases/fourslash/unusedTypeParametersInLambda4.ts +++ b/tests/cases/fourslash/unusedTypeParametersInLambda4.ts @@ -6,4 +6,4 @@ //// } //// [|var y: new (a:T)=>void;|] -verify.codeFixAtPosition("var y: new (a:T)=>void;"); \ No newline at end of file +verify.rangeAfterCodeFix("var y: new (a:T)=>void;"); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedTypeParametersInMethod1.ts b/tests/cases/fourslash/unusedTypeParametersInMethod1.ts index 7a9f04147d617..bc14952eca9b7 100644 --- a/tests/cases/fourslash/unusedTypeParametersInMethod1.ts +++ b/tests/cases/fourslash/unusedTypeParametersInMethod1.ts @@ -5,4 +5,4 @@ //// [|f1()|] {} //// } -verify.codeFixAtPosition("f1()"); \ No newline at end of file +verify.rangeAfterCodeFix("f1()"); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedTypeParametersInMethod2.ts b/tests/cases/fourslash/unusedTypeParametersInMethod2.ts index 3650cfbad98a0..c12fd53f66b0b 100644 --- a/tests/cases/fourslash/unusedTypeParametersInMethod2.ts +++ b/tests/cases/fourslash/unusedTypeParametersInMethod2.ts @@ -5,4 +5,4 @@ //// [|f1(a: U)|] {a;} //// } -verify.codeFixAtPosition("f1(a: U)"); \ No newline at end of file +verify.rangeAfterCodeFix("f1(a: U)"); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedTypeParametersInMethods1.ts b/tests/cases/fourslash/unusedTypeParametersInMethods1.ts index cb9b965ca4d45..d0b170491f5e1 100644 --- a/tests/cases/fourslash/unusedTypeParametersInMethods1.ts +++ b/tests/cases/fourslash/unusedTypeParametersInMethods1.ts @@ -5,4 +5,4 @@ //// [|public f1(a: X)|] { a; var b: Z; b } //// } -verify.codeFixAtPosition("public f1(a: X)"); +verify.rangeAfterCodeFix("public f1(a: X)"); diff --git a/tests/cases/fourslash/unusedVariableInBlocks.ts b/tests/cases/fourslash/unusedVariableInBlocks.ts index e9dedaef31eb0..2a33d0c4cf5c6 100644 --- a/tests/cases/fourslash/unusedVariableInBlocks.ts +++ b/tests/cases/fourslash/unusedVariableInBlocks.ts @@ -9,7 +9,7 @@ //// x;|] //// } -verify.codeFixAtPosition(`let x = 10; +verify.rangeAfterCodeFix(`let x = 10; { } x;`); diff --git a/tests/cases/fourslash/unusedVariableInClass1.ts b/tests/cases/fourslash/unusedVariableInClass1.ts index 82bb99016efd5..8b0ca0db727db 100644 --- a/tests/cases/fourslash/unusedVariableInClass1.ts +++ b/tests/cases/fourslash/unusedVariableInClass1.ts @@ -5,4 +5,4 @@ //// [|private greeting: string;|] ////} -verify.codeFixAtPosition(""); +verify.rangeAfterCodeFix(""); diff --git a/tests/cases/fourslash/unusedVariableInClass2.ts b/tests/cases/fourslash/unusedVariableInClass2.ts index c971092584a53..6503dd02872fe 100644 --- a/tests/cases/fourslash/unusedVariableInClass2.ts +++ b/tests/cases/fourslash/unusedVariableInClass2.ts @@ -6,4 +6,4 @@ //// private greeting: string;|] ////} -verify.codeFixAtPosition("public greeting1;"); +verify.rangeAfterCodeFix("public greeting1;"); diff --git a/tests/cases/fourslash/unusedVariableInClass3.ts b/tests/cases/fourslash/unusedVariableInClass3.ts index 8d2a62e7175b9..3ac306170a203 100644 --- a/tests/cases/fourslash/unusedVariableInClass3.ts +++ b/tests/cases/fourslash/unusedVariableInClass3.ts @@ -5,4 +5,4 @@ //// private X = function() {}; ////|]} -verify.codeFixAtPosition(""); +verify.rangeAfterCodeFix(""); diff --git a/tests/cases/fourslash/unusedVariableInForLoop1FS.ts b/tests/cases/fourslash/unusedVariableInForLoop1FS.ts index 0ee02ab43632d..760d8487b3438 100644 --- a/tests/cases/fourslash/unusedVariableInForLoop1FS.ts +++ b/tests/cases/fourslash/unusedVariableInForLoop1FS.ts @@ -7,5 +7,5 @@ //// } //// } -verify.codeFixAtPosition("for(; ;)"); +verify.rangeAfterCodeFix("for(; ;)"); diff --git a/tests/cases/fourslash/unusedVariableInForLoop2FS.ts b/tests/cases/fourslash/unusedVariableInForLoop2FS.ts index 1b1a0798c0445..a16f21e8417a4 100644 --- a/tests/cases/fourslash/unusedVariableInForLoop2FS.ts +++ b/tests/cases/fourslash/unusedVariableInForLoop2FS.ts @@ -7,4 +7,4 @@ //// } //// } -verify.codeFixAtPosition("for(var i = 0; ;i++)"); +verify.rangeAfterCodeFix("for(var i = 0; ;i++)"); diff --git a/tests/cases/fourslash/unusedVariableInForLoop3FS.ts b/tests/cases/fourslash/unusedVariableInForLoop3FS.ts index 4eed9599b1513..07d13307ca794 100644 --- a/tests/cases/fourslash/unusedVariableInForLoop3FS.ts +++ b/tests/cases/fourslash/unusedVariableInForLoop3FS.ts @@ -7,4 +7,4 @@ //// } //// } -verify.codeFixAtPosition("for(var i = 0, k=0; ;i++,k++)"); \ No newline at end of file +verify.rangeAfterCodeFix("for(var i = 0, k=0; ;i++,k++)"); \ No newline at end of file diff --git a/tests/cases/fourslash/unusedVariableInForLoop4FS.ts b/tests/cases/fourslash/unusedVariableInForLoop4FS.ts index 76e551612ba79..d54f8baaa3d5c 100644 --- a/tests/cases/fourslash/unusedVariableInForLoop4FS.ts +++ b/tests/cases/fourslash/unusedVariableInForLoop4FS.ts @@ -7,4 +7,4 @@ //// } //// } -verify.codeFixAtPosition("for(var j = 0, k=0; ;j++,k++)"); +verify.rangeAfterCodeFix("for(var j = 0, k=0; ;j++,k++)"); diff --git a/tests/cases/fourslash/unusedVariableInForLoop6FS.ts b/tests/cases/fourslash/unusedVariableInForLoop6FS.ts index 4187c3141b547..a7b8fbfb7c895 100644 --- a/tests/cases/fourslash/unusedVariableInForLoop6FS.ts +++ b/tests/cases/fourslash/unusedVariableInForLoop6FS.ts @@ -7,5 +7,5 @@ //// } //// } -verify.codeFixAtPosition("const {} of "); +verify.rangeAfterCodeFix("const {} of "); diff --git a/tests/cases/fourslash/unusedVariableInForLoop7FS.ts b/tests/cases/fourslash/unusedVariableInForLoop7FS.ts index 8fd0fee735e27..fa862594ff98b 100644 --- a/tests/cases/fourslash/unusedVariableInForLoop7FS.ts +++ b/tests/cases/fourslash/unusedVariableInForLoop7FS.ts @@ -9,4 +9,4 @@ ////} //// -verify.codeFixAtPosition(""); +verify.rangeAfterCodeFix(""); diff --git a/tests/cases/fourslash/unusedVariableInModule1.ts b/tests/cases/fourslash/unusedVariableInModule1.ts index 011434ce098df..85ca41952cc5d 100644 --- a/tests/cases/fourslash/unusedVariableInModule1.ts +++ b/tests/cases/fourslash/unusedVariableInModule1.ts @@ -6,4 +6,4 @@ //// [|var x: string;|] //// export var y: string; -verify.codeFixAtPosition(""); +verify.rangeAfterCodeFix(""); diff --git a/tests/cases/fourslash/unusedVariableInModule2.ts b/tests/cases/fourslash/unusedVariableInModule2.ts index db4519c8faac7..ac6e7120d8bd9 100644 --- a/tests/cases/fourslash/unusedVariableInModule2.ts +++ b/tests/cases/fourslash/unusedVariableInModule2.ts @@ -7,4 +7,4 @@ //// z; //// export var y: string; -verify.codeFixAtPosition("var z: number;"); +verify.rangeAfterCodeFix("var z: number;"); diff --git a/tests/cases/fourslash/unusedVariableInModule3.ts b/tests/cases/fourslash/unusedVariableInModule3.ts index bffffc768d355..428d234c164b4 100644 --- a/tests/cases/fourslash/unusedVariableInModule3.ts +++ b/tests/cases/fourslash/unusedVariableInModule3.ts @@ -6,4 +6,4 @@ //// [|var x = function f1() {}|] //// export var y: string; -verify.codeFixAtPosition(""); +verify.rangeAfterCodeFix(""); diff --git a/tests/cases/fourslash/unusedVariableInModule4.ts b/tests/cases/fourslash/unusedVariableInModule4.ts index 6a1be9fe5b89a..8f23d56b03c02 100644 --- a/tests/cases/fourslash/unusedVariableInModule4.ts +++ b/tests/cases/fourslash/unusedVariableInModule4.ts @@ -7,4 +7,4 @@ //// x; //// export var y: string; -verify.codeFixAtPosition(`var x = function f1() {}`); +verify.rangeAfterCodeFix(`var x = function f1() {}`); diff --git a/tests/cases/fourslash/unusedVariableInNamespace1.ts b/tests/cases/fourslash/unusedVariableInNamespace1.ts index caf778bc0da76..c9f38473a5151 100644 --- a/tests/cases/fourslash/unusedVariableInNamespace1.ts +++ b/tests/cases/fourslash/unusedVariableInNamespace1.ts @@ -5,4 +5,4 @@ //// [|let a = "dummy entry";|] ////} -verify.codeFixAtPosition(""); +verify.rangeAfterCodeFix(""); diff --git a/tests/cases/fourslash/unusedVariableInNamespace2.ts b/tests/cases/fourslash/unusedVariableInNamespace2.ts index fbb9e2d6a0c2b..992c229014aef 100644 --- a/tests/cases/fourslash/unusedVariableInNamespace2.ts +++ b/tests/cases/fourslash/unusedVariableInNamespace2.ts @@ -9,4 +9,4 @@ //// } ////} -verify.codeFixAtPosition(`let a = "dummy entry", c = 0;`); +verify.rangeAfterCodeFix(`let a = "dummy entry", c = 0;`); diff --git a/tests/cases/fourslash/unusedVariableInNamespace3.ts b/tests/cases/fourslash/unusedVariableInNamespace3.ts index 33e501d0c0def..0039036b2f8bc 100644 --- a/tests/cases/fourslash/unusedVariableInNamespace3.ts +++ b/tests/cases/fourslash/unusedVariableInNamespace3.ts @@ -9,4 +9,4 @@ //// } ////} -verify.codeFixAtPosition(`let a = "dummy entry", b;`); +verify.rangeAfterCodeFix(`let a = "dummy entry", b;`);