diff --git a/fixtures/workspaces/auto-fix/common-mistakes.md b/fixtures/workspaces/auto-fix/common-mistakes.md new file mode 100644 index 0000000000..ec342097e8 --- /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 0000000000..e69de29bb2 diff --git a/package.json b/package.json index beaab6567d..8b435829cd 100644 --- a/package.json +++ b/package.json @@ -425,6 +425,9 @@ }, "[css]": { "cSpell.fixSpellingWithRenameProvider": false + }, + "[scminput]": { + "cSpell.fixSpellingWithRenameProvider": false } }, "configuration": [ diff --git a/packages/client/src/commands.ts b/packages/client/src/commands.ts index 3aa188edc5..12aa44e8da 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)) { + 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}`)); }