From e465802e2fc3562374e4a6603b6103dd326072c1 Mon Sep 17 00:00:00 2001 From: Jason Dent Date: Tue, 14 Mar 2023 15:39:54 +0100 Subject: [PATCH 1/4] fix: Do not use rename provider fixes #2574 --- package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package.json b/package.json index beaab6567..8b435829c 100644 --- a/package.json +++ b/package.json @@ -425,6 +425,9 @@ }, "[css]": { "cSpell.fixSpellingWithRenameProvider": false + }, + "[scminput]": { + "cSpell.fixSpellingWithRenameProvider": false } }, "configuration": [ From 830f4992e381e9cfca9c91f7d7f0b28b0e97d263 Mon Sep 17 00:00:00 2001 From: Jason Dent Date: Tue, 14 Mar 2023 16:52:22 +0100 Subject: [PATCH 2/4] Add a fixture --- .../workspaces/auto-fix/common-mistakes.md | 53 +++++++++++++++++++ .../workspaces/auto-fix/cspell.config.yaml | 0 2 files changed, 53 insertions(+) create mode 100644 fixtures/workspaces/auto-fix/common-mistakes.md create mode 100644 fixtures/workspaces/auto-fix/cspell.config.yaml diff --git a/fixtures/workspaces/auto-fix/common-mistakes.md b/fixtures/workspaces/auto-fix/common-mistakes.md new file mode 100644 index 000000000..ec342097e --- /dev/null +++ b/fixtures/workspaces/auto-fix/common-mistakes.md @@ -0,0 +1,53 @@ +# Commonly misspelled English words + +[Wikipedia: Commonly misspelled English words](https://en.wikipedia.org/wiki/Commonly_misspelled_English_words) + +Commonly misspelled English words[1] (UK: misspelt words) are words that are often unintentionally misspelled in general writing. A selected list of common words is presented below, under Documented list of common misspellings. Although the word common is subjective depending on the situation, the focus is on general writing, rather than in a specific field. Accepted spellings also vary by country or region, with some rejecting the American or British variants as incorrect for the region.[1][2][3] + +Within a particular field of study, such as computer graphics, other words might be more common for misspelling, such as "pixel" misspelled as "pixle" (or variants "cesium" and "caesium"). Sometimes words are purposely misspelled, as a form in slang, abbreviations, or in song lyrics, etc. + +In general writing, some words are frequently misspelled, such as the incorrect spelling "concensus"[4] for "consensus"[5] found in numerous webpages.[4] Other common misspellings include "equiptment" (for "equipment"),[4][6] "independant" (for "independent"),[4][7] "readible" (for readable),[3][8] or "usible" (for usable or useable).[3][4][9][10] + +Unlimited misspellings +Because many words can be extended with prefixes (such as "un-" or "anti-" or "re-") or suffixes (such as "-ly" or "-ing" or "-ness"), a comprehensive list of words prone to misspelling would contain thousands of variations from combining prefixes or suffixes (or both) added to the root words. To limit the scope to common words, the top 350 words are considered (according to various sources). + +Documented list of common misspellings +The following list, of about 350 words, is based on documented lists[4][10] of the top 100, 200, or 400[3] most commonly misspelled words in all variants of the English language, rather than listing every conceivable misspelled word. Some words are followed by examples of misspellings: + +A–B +absence – absense, absentse, abcense, absance[3][10] +acceptable – acceptible[4] +accidentally/accidently – accidentaly[4] +accommodate – accomodate, acommodate[3][4] +achieve – acheive[3] +acknowledge – acknowlege, aknowledge[3] +acquaintance – acquaintence, aquaintance[3] +acquire – aquire, adquire[4] +acquit – aquit[4] +acreage – acrage, acerage[3] +address – adress[3] +adultery – adultary[3] +advisable – adviseable, advizable[3] +affect – effect [3] (both words exist, but are distinct) +aggression – agression[1] +aggressive – agressive[1] +allegiance – allegaince, allegience, alegiance[3] +almost – allmost[3] +a lot – alot (must be two words), allot[4] +amateur – amatuer, amature[4] +annually – anually, annualy[3] +apparent – apparant, aparent, apparrent, aparrent[4] +arctic – artic[3] +argument – arguement[1][4] +atheist – athiest, athist[3][4] +awful – awfull, aweful[3] +because – becuase, becasue[3] +beautiful – beatiful[3] +becoming – becomeing[3] +beginning – begining[3] +believe – beleive[4] +bellwether – bellweather[3][4] +benefit - benifit[3] +buoy – bouy[3] +buoyant – bouyant[3] +business – buisness[1] diff --git a/fixtures/workspaces/auto-fix/cspell.config.yaml b/fixtures/workspaces/auto-fix/cspell.config.yaml new file mode 100644 index 000000000..e69de29bb From 702c4ed7ee33e28a7aeecaae65d7a0027cb06cd1 Mon Sep 17 00:00:00 2001 From: Jason Dent Date: Tue, 14 Mar 2023 16:53:16 +0100 Subject: [PATCH 3/4] refactor: Use the workspace to apply edits. --- packages/client/src/commands.ts | 70 ++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/packages/client/src/commands.ts b/packages/client/src/commands.ts index 3aa188edc..e3d20c309 100644 --- a/packages/client/src/commands.ts +++ b/packages/client/src/commands.ts @@ -12,13 +12,14 @@ import { Range, Selection, TextDocument, + TextEdit, TextEditorRevealType, Uri, window, workspace, WorkspaceEdit, } from 'vscode'; -import { TextEdit } from 'vscode-languageclient/node'; +import { TextEdit as LsTextEdit } from 'vscode-languageclient/node'; import { ClientSideCommandHandlerApi, SpellCheckerSettingsProperties } from './client'; import * as di from './di'; @@ -87,6 +88,7 @@ const commandsFromServer: ClientSideCommandHandlerApi = { }; type CommandHandler = { + // eslint-disable-next-line @typescript-eslint/no-explicit-any [key in string]: (...params: any[]) => void | Promise; }; @@ -178,41 +180,37 @@ const propertyUseReferenceProviderWithRename: SpellCheckerSettingsProperties = ' const propertyUseReferenceProviderRemove: SpellCheckerSettingsProperties = 'advanced.feature.useReferenceProviderRemove'; function handlerApplyTextEdits() { - return async function applyTextEdits(uri: string, documentVersion: number, edits: TextEdit[]): Promise { + return async function handleApplyTextEdits(uri: string, documentVersion: number, edits: LsTextEdit[]): Promise { const client = di.get('client').client; - const textEditor = window.activeTextEditor; - if (!textEditor || textEditor.document.uri.toString() !== uri) return; - if (textEditor.document.version !== documentVersion) { + const doc = workspace.textDocuments.find((doc) => doc.uri.toString() === uri); + + if (!doc) return; + + if (doc.version !== documentVersion) { return pVoid( window.showInformationMessage('Spelling changes are outdated and cannot be applied to the document.'), 'handlerApplyTextEdits' ); } - const cfg = workspace.getConfiguration(Settings.sectionCSpell, textEditor.document); - if (cfg.get(propertyFixSpellingWithRenameProvider) && edits.length === 1) { - const useReference = !!cfg.get(propertyUseReferenceProviderWithRename); - const removeRegExp = toConfigToRegExp(cfg.get(propertyUseReferenceProviderRemove) as string | undefined); - // console.log(`${propertyFixSpellingWithRenameProvider} Enabled`); - const edit = edits[0]; - const range = client.protocol2CodeConverter.asRange(edit.range); - if (await attemptRename(textEditor.document, range, edit.newText, { useReference, removeRegExp })) { - return; + if (edits.length === 1) { + const cfg = workspace.getConfiguration(Settings.sectionCSpell, doc); + if (cfg.get(propertyFixSpellingWithRenameProvider) && edits.length === 1) { + const useReference = !!cfg.get(propertyUseReferenceProviderWithRename); + const removeRegExp = toConfigToRegExp(cfg.get(propertyUseReferenceProviderRemove) as string | undefined); + // console.log(`${propertyFixSpellingWithRenameProvider} Enabled`); + const edit = client.protocol2CodeConverter.asTextEdit(edits[0]); + if (await attemptRename(doc, edit, { useReference, removeRegExp })) { + return; + } } } - return textEditor - .edit((mutator) => { - for (const edit of edits) { - mutator.replace(client.protocol2CodeConverter.asRange(edit.range), edit.newText); - } - }) - .then((success) => - success - ? undefined - : pVoid(window.showErrorMessage('Failed to apply spelling changes to the document.'), 'handlerApplyTextEdits2') - ); + const success = await applyTextEdits(doc.uri, edits); + return success + ? undefined + : pVoid(window.showErrorMessage('Failed to apply spelling changes to the document.'), 'handlerApplyTextEdits2'); }; } @@ -221,7 +219,8 @@ interface UseRefInfo { removeRegExp: RegExp | undefined; } -async function attemptRename(document: TextDocument, range: Range, text: string, refInfo: UseRefInfo): Promise { +async function attemptRename(document: TextDocument, edit: TextEdit, refInfo: UseRefInfo): Promise { + const { range, newText: text } = edit; if (range.start.line !== range.end.line) { return false; } @@ -249,6 +248,22 @@ async function attemptRename(document: TextDocument, range: Range, text: string, } } +async function applyTextEdits(uri: Uri, edits: LsTextEdit[]): Promise { + const client = di.get('client').client; + function toTextEdit(edit: LsTextEdit): TextEdit { + return client.protocol2CodeConverter.asTextEdit(edit); + } + + const wsEdit = new WorkspaceEdit(); + const textEdits: TextEdit[] = edits.map(toTextEdit); + wsEdit.set(uri, textEdits); + try { + return await workspace.applyEdit(wsEdit); + } catch (e) { + return false; + } +} + async function findLocalReference(uri: Uri, range: Range): Promise { try { const locations = (await commands.executeCommand('vscode.executeReferenceProvider', uri, range.start)) as Location[]; @@ -288,7 +303,8 @@ function addWordsToDictionaryTarget(words: string[], dictTarget: DictionaryTarge // return handleErrors(di.get('dictionaryHelper').removeWordFromDictionary(words, dictTarget)); // } -function registerCmd(cmd: string, fn: (...args: any[]) => any): Disposable { +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function registerCmd(cmd: string, fn: (...args: any[]) => unknown): Disposable { return commands.registerCommand(cmd, catchErrors(fn, `Register command: ${cmd}`)); } From 05bd093e195134ee09fc4f8ab67b6fad48dca865 Mon Sep 17 00:00:00 2001 From: Jason Dent Date: Tue, 14 Mar 2023 17:43:36 +0100 Subject: [PATCH 4/4] Update commands.ts --- packages/client/src/commands.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/commands.ts b/packages/client/src/commands.ts index e3d20c309..12aa44e8d 100644 --- a/packages/client/src/commands.ts +++ b/packages/client/src/commands.ts @@ -196,7 +196,7 @@ function handlerApplyTextEdits() { if (edits.length === 1) { const cfg = workspace.getConfiguration(Settings.sectionCSpell, doc); - if (cfg.get(propertyFixSpellingWithRenameProvider) && edits.length === 1) { + if (cfg.get(propertyFixSpellingWithRenameProvider)) { const useReference = !!cfg.get(propertyUseReferenceProviderWithRename); const removeRegExp = toConfigToRegExp(cfg.get(propertyUseReferenceProviderRemove) as string | undefined); // console.log(`${propertyFixSpellingWithRenameProvider} Enabled`);