From cf93827cf4e9ba1ab878fbaada222a47d90ed05f Mon Sep 17 00:00:00 2001 From: Lyu Jason Date: Wed, 3 Mar 2021 13:37:00 +0800 Subject: [PATCH 1/2] support missing funciton declaration quick fix (typescript 4.2) --- .../features/CodeActionsProvider.ts | 52 ++++++++++------ .../features/CodeActionsProvider.test.ts | 60 ++++++++++++++++++- .../typescript/testfiles/codeactions.svelte | 1 + 3 files changed, 94 insertions(+), 19 deletions(-) diff --git a/packages/language-server/src/plugins/typescript/features/CodeActionsProvider.ts b/packages/language-server/src/plugins/typescript/features/CodeActionsProvider.ts index dac8c9d6b..5dff9a8b4 100644 --- a/packages/language-server/src/plugins/typescript/features/CodeActionsProvider.ts +++ b/packages/language-server/src/plugins/typescript/features/CodeActionsProvider.ts @@ -171,6 +171,14 @@ export class CodeActionsProviderImpl implements CodeActionsProvider { ); } + if (fix.fixName === 'fixMissingFunctionDeclaration') { + originalRange = this.checkEndOfFileCodeInsert( + originalRange, + range, + document + ); + } + return TextEdit.replace(originalRange, edit.newText); }) ); @@ -327,23 +335,12 @@ export class CodeActionsProviderImpl implements CodeActionsProvider { TextDocumentEdit.create( VersionedTextDocumentIdentifier.create(document.uri, 0), edit.textChanges.map((edit) => { - let range = mapRangeToOriginal(fragment, convertRange(fragment, edit.span)); - // Some refactorings place the new code at the end of svelte2tsx' render function, - // which is unmapped. In this case, add it to the end of the script tag ourselves. - if (range.start.line < 0 || range.end.line < 0) { - if (isRangeInTag(originalRange, document.scriptInfo)) { - range = Range.create( - document.scriptInfo.endPos, - document.scriptInfo.endPos - ); - } else if (isRangeInTag(originalRange, document.moduleScriptInfo)) { - range = Range.create( - document.moduleScriptInfo.endPos, - document.moduleScriptInfo.endPos - ); - } - } - return TextEdit.replace(range, edit.newText); + const range = mapRangeToOriginal(fragment, convertRange(fragment, edit.span)); + + return TextEdit.replace( + this.checkEndOfFileCodeInsert(range, originalRange, document), + edit.newText + ); }) ) ); @@ -351,6 +348,27 @@ export class CodeActionsProviderImpl implements CodeActionsProvider { return { documentChanges }; } + /** + * Some refactorings place the new code at the end of svelte2tsx' render function, + * which is unmapped. In this case, add it to the end of the script tag ourselves. + */ + private checkEndOfFileCodeInsert(resultRange: Range, targetRange: Range, document: Document) { + if (resultRange.start.line < 0 || resultRange.end.line < 0) { + if (isRangeInTag(targetRange, document.scriptInfo)) { + resultRange = Range.create( + document.scriptInfo.endPos, + document.scriptInfo.endPos + ); + } else if (isRangeInTag(targetRange, document.moduleScriptInfo)) { + resultRange = Range.create( + document.moduleScriptInfo.endPos, + document.moduleScriptInfo.endPos + ); + } + } + return resultRange; + } + private getLSAndTSDoc(document: Document) { return this.lsAndTsDocResolver.getLSAndTSDoc(document); } diff --git a/packages/language-server/test/plugins/typescript/features/CodeActionsProvider.test.ts b/packages/language-server/test/plugins/typescript/features/CodeActionsProvider.test.ts index 2630bc70f..7733d3fc0 100644 --- a/packages/language-server/test/plugins/typescript/features/CodeActionsProvider.test.ts +++ b/packages/language-server/test/plugins/typescript/features/CodeActionsProvider.test.ts @@ -95,6 +95,62 @@ describe('CodeActionsProvider', () => { ]); }); + it('provides quickfix for missing function', async () => { + const { provider, document } = setup('codeactions.svelte'); + + const codeActions = await provider.getCodeActions( + document, + Range.create(Position.create(9, 0), Position.create(9, 3)), + { + diagnostics: [ + { + code: 2304, + message: "Cannot find name 'abc'.", + range: Range.create(Position.create(9, 0), Position.create(9, 3)), + source: 'ts' + } + ], + only: [CodeActionKind.QuickFix] + } + ); + + (codeActions[0]?.edit?.documentChanges?.[0])?.edits.forEach( + (edit) => (edit.newText = harmonizeNewLines(edit.newText)) + ); + + assert.deepStrictEqual(codeActions, [ + { + edit: { + documentChanges: [ + { + edits: [ + { + newText: "\n\nfunction abc() {\nthrow new Error('Function not implemented.');\n}\n", + range: { + start: { + character: 0, + line: 10 + }, + end: { + character: 0, + line: 10 + } + } + } + ], + textDocument: { + uri: getUri('codeactions.svelte'), + version: 0 + } + } + ] + }, + kind: CodeActionKind.QuickFix, + title: "Add missing function declaration 'abc'" + } + ]); + }); + it('organizes imports', async () => { const { provider, document } = setup('codeactions.svelte'); @@ -428,11 +484,11 @@ describe('CodeActionsProvider', () => { range: { start: { character: 0, - line: 9 + line: 10 }, end: { character: 0, - line: 9 + line: 10 } } } diff --git a/packages/language-server/test/plugins/typescript/testfiles/codeactions.svelte b/packages/language-server/test/plugins/typescript/testfiles/codeactions.svelte index c7ff8b71e..f38f7368b 100644 --- a/packages/language-server/test/plugins/typescript/testfiles/codeactions.svelte +++ b/packages/language-server/test/plugins/typescript/testfiles/codeactions.svelte @@ -7,4 +7,5 @@ import {D} from 'd'; let a = true; A;C; let b = Math.random() > 0.5 ? true : false; +abc(); From 7bcfd15c875fdd6428ff111ef8a9172b675822bd Mon Sep 17 00:00:00 2001 From: Lyu Jason Date: Wed, 3 Mar 2021 13:42:03 +0800 Subject: [PATCH 2/2] format --- .../src/plugins/typescript/features/CodeActionsProvider.ts | 5 +---- .../plugins/typescript/features/CodeActionsProvider.test.ts | 3 ++- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/language-server/src/plugins/typescript/features/CodeActionsProvider.ts b/packages/language-server/src/plugins/typescript/features/CodeActionsProvider.ts index 5dff9a8b4..b731accc0 100644 --- a/packages/language-server/src/plugins/typescript/features/CodeActionsProvider.ts +++ b/packages/language-server/src/plugins/typescript/features/CodeActionsProvider.ts @@ -355,10 +355,7 @@ export class CodeActionsProviderImpl implements CodeActionsProvider { private checkEndOfFileCodeInsert(resultRange: Range, targetRange: Range, document: Document) { if (resultRange.start.line < 0 || resultRange.end.line < 0) { if (isRangeInTag(targetRange, document.scriptInfo)) { - resultRange = Range.create( - document.scriptInfo.endPos, - document.scriptInfo.endPos - ); + resultRange = Range.create(document.scriptInfo.endPos, document.scriptInfo.endPos); } else if (isRangeInTag(targetRange, document.moduleScriptInfo)) { resultRange = Range.create( document.moduleScriptInfo.endPos, diff --git a/packages/language-server/test/plugins/typescript/features/CodeActionsProvider.test.ts b/packages/language-server/test/plugins/typescript/features/CodeActionsProvider.test.ts index 7733d3fc0..13f701011 100644 --- a/packages/language-server/test/plugins/typescript/features/CodeActionsProvider.test.ts +++ b/packages/language-server/test/plugins/typescript/features/CodeActionsProvider.test.ts @@ -125,7 +125,8 @@ describe('CodeActionsProvider', () => { { edits: [ { - newText: "\n\nfunction abc() {\nthrow new Error('Function not implemented.');\n}\n", + newText: + "\n\nfunction abc() {\nthrow new Error('Function not implemented.');\n}\n", range: { start: { character: 0,