• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

streetsidesoftware / cspell / 22018174886

14 Feb 2026 01:22PM UTC coverage: 92.949% (-0.04%) from 92.985%
22018174886

push

github

web-flow
chore: bump eslint-plugin-unicorn from 62.0.0 to 63.0.0 (#8566)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

9117 of 10894 branches covered (83.69%)

18244 of 19628 relevant lines covered (92.95%)

30692.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.08
/packages/cspell-lib/src/lib/spellCheckFile.ts
1
import type { CSpellSettingsWithSourceTrace, CSpellUserSettings } from '@cspell/cspell-types';
2
import type { ICSpellConfigFile } from 'cspell-config-lib';
3
import { satisfiesCSpellConfigFile } from 'cspell-config-lib';
4

5
import type { Document, DocumentWithText } from './Document/index.js';
6
import { isBinaryDoc } from './Document/isBinaryDoc.js';
7
import { documentToTextDocument, resolveDocument } from './Document/resolveDocument.js';
8
import { createTextDocument } from './Models/TextDocument.js';
9
import { toValidationIssueRPC, type ValidationIssueRPC } from './Models/ValidationIssue.js';
10
import { createPerfTimer } from './perf/index.js';
11
import type { ImportFileRefWithError } from './Settings/index.js';
12
import { determineTextDocumentSettings } from './textValidation/determineTextDocumentSettings.js';
13
import type { DocumentValidatorOptions } from './textValidation/index.js';
14
import { DocumentValidator } from './textValidation/index.js';
15
import { isError } from './util/errors.js';
16
import type { Uri } from './util/IUri.js';
17
import { toUri } from './util/Uri.js';
18
import type { ValidateTextOptions, ValidationIssue } from './validator.js';
19

20
export interface SpellCheckFileOptions extends ValidateTextOptions, Pick<CSpellUserSettings, 'unknownWords'> {
21
    /**
22
     * Optional path to a configuration file.
23
     * If given, it will be used instead of searching for a configuration file.
24
     */
25
    configFile?: string;
26
    /**
27
     * File encoding
28
     * @defaultValue 'utf-8'
29
     */
30
    encoding?: BufferEncoding;
31
    /**
32
     * Prevents searching for local configuration files
33
     * By default the spell checker looks for configuration files
34
     * starting at the location of given filename.
35
     * If `configFile` is defined it will still be loaded instead of searching.
36
     * `false` will override the value in `settings.noConfigSearch`.
37
     * @defaultValue undefined
38
     */
39
    noConfigSearch?: boolean;
40
}
41

42
export interface SpellCheckFileOptionsRPC extends SpellCheckFileOptions {
43
    measurePerf?: boolean;
44
}
45

46
export interface SpellCheckFilePerf extends Record<string, number | undefined> {
47
    loadTimeMs?: number;
48
    prepareTimeMs?: number;
49
    checkTimeMs?: number;
50
    totalTimeMs?: number;
51
}
52

53
export interface SpellCheckFileResult {
54
    document: Document | DocumentWithText;
55
    settingsUsed: CSpellSettingsWithSourceTrace;
56
    localConfigFilepath: string | undefined;
57
    options: SpellCheckFileOptions;
58
    issues: ValidationIssue[];
59
    checked: boolean;
60
    errors: Error[] | undefined;
61
    configErrors?: ImportFileRefWithError[] | undefined;
62
    dictionaryErrors?: Map<string, Error[]> | undefined;
63
    perf?: SpellCheckFilePerf;
64
}
65

66
interface DocumentReferenceRPC extends Pick<Document, 'uri'> {
67
    text?: undefined;
68
    languageId?: undefined;
69
    locale?: undefined;
70
}
71

72
export interface SpellCheckFileResultRPC {
73
    /**
74
     * The document that was checked.
75
     *
76
     * **Note:** the text will be missing to avoid sending large amounts of text over the RPC channel.
77
     * If the text is needed, the document should be reloaded using the URI.
78
     */
79
    document: DocumentReferenceRPC;
80
    issues?: ValidationIssueRPC[] | undefined;
81
    checked: boolean;
82
    errors?: Error[] | undefined;
83
    configErrors?: ImportFileRefWithError[] | undefined;
84
    dictionaryErrors?: Map<string, Error[]> | undefined;
85
    perf?: SpellCheckFilePerf | undefined;
86
}
87

88
/**
89
 * Spell Check a file
90
 * @param file - absolute path to file to read and check.
91
 * @param options - options to control checking
92
 * @param settings - default settings to use.
93
 */
94
export function spellCheckFile(
95
    file: string | Uri | URL,
96
    options: SpellCheckFileOptions,
97
    settingsOrConfigFile: CSpellUserSettings | ICSpellConfigFile,
98
): Promise<SpellCheckFileResult> {
99
    const doc: Document = {
14✔
100
        uri: toUri(file).toString(),
101
    };
102
    return spellCheckDocument(doc, options, settingsOrConfigFile);
14✔
103
}
104

105
/**
106
 * Spell Check a Document.
107
 * @param document - document to be checked. If `document.text` is `undefined` the file will be loaded
108
 * @param options - options to control checking
109
 * @param settings - default settings to use.
110
 */
111
export async function spellCheckDocument(
112
    document: Document | DocumentWithText,
113
    options: SpellCheckFileOptions,
114
    settingsOrConfigFile: CSpellUserSettings | ICSpellConfigFile,
115
): Promise<SpellCheckFileResult> {
116
    const settingsUsed = satisfiesCSpellConfigFile(settingsOrConfigFile)
45✔
117
        ? settingsOrConfigFile.settings
118
        : settingsOrConfigFile;
119
    if (isBinaryDoc(document)) {
45✔
120
        return {
5✔
121
            document,
122
            options,
123
            settingsUsed,
124
            localConfigFilepath: undefined,
125
            issues: [],
126
            checked: false,
127
            errors: undefined,
128
        };
129
    }
130
    try {
40✔
131
        const timer = createPerfTimer('loadFile');
40✔
132
        const doc = await resolveDocument(document).finally(() => timer.end());
40✔
133
        if (isBinaryDoc(doc)) {
35!
134
            return {
×
135
                document,
136
                options,
137
                settingsUsed,
138
                localConfigFilepath: undefined,
139
                issues: [],
140
                checked: false,
141
                errors: undefined,
142
            };
143
        }
144
        const result = await spellCheckFullDocument(doc, options, settingsOrConfigFile);
35✔
145
        const perf = result.perf || {};
35!
146
        perf.loadTimeMs = timer.elapsed;
35✔
147
        result.perf = perf;
35✔
148
        return result;
35✔
149
    } catch (e) {
150
        const errors = isError(e) ? [e] : [];
5!
151
        return {
5✔
152
            document,
153
            options,
154
            settingsUsed,
155
            localConfigFilepath: undefined,
156
            issues: [],
157
            checked: false,
158
            errors,
159
        };
160
    }
161
}
162

163
/**
164
 * Spell Check a Document.
165
 * @param document - document to be checked. If `document.text` is `undefined` the file will be loaded
166
 * @param options - options to control checking
167
 * @param settings - default settings to use.
168
 */
169
export async function spellCheckDocumentRPC(
170
    document: Document | DocumentWithText,
171
    options: SpellCheckFileOptionsRPC,
172
    settingsOrConfigFile: CSpellUserSettings | ICSpellConfigFile,
173
): Promise<SpellCheckFileResultRPC> {
174
    const { issues, checked, errors, configErrors, dictionaryErrors, perf } = await spellCheckDocument(
5✔
175
        document,
176
        options,
177
        settingsOrConfigFile,
178
    );
179

180
    const result: SpellCheckFileResultRPC = {
5✔
181
        document: { uri: document.uri },
182
        checked,
183
    };
184

185
    if (issues.length) {
5✔
186
        result.issues = issues.map(toValidationIssueRPC);
1✔
187
    }
188

189
    if (errors?.length) {
5✔
190
        result.errors = errors;
1✔
191
    }
192

193
    if (configErrors?.length) {
5✔
194
        result.configErrors = configErrors;
1✔
195
    }
196
    if (dictionaryErrors?.size) {
5✔
197
        result.dictionaryErrors = dictionaryErrors;
1✔
198
    }
199

200
    if (perf && options.measurePerf) {
5✔
201
        result.perf = perf;
1✔
202
    }
203

204
    return result;
5✔
205
}
206

207
async function spellCheckFullDocument(
208
    document: DocumentWithText,
209
    options: SpellCheckFileOptions,
210
    settingsOrConfigFile: CSpellUserSettings | ICSpellConfigFile,
211
): Promise<SpellCheckFileResult> {
212
    // if (options.skipValidation) {
213
    //     return {
214
    //         document,
215
    //         options,
216
    //         settingsUsed: settings,
217
    //         localConfigFilepath: undefined,
218
    //         issues: [],
219
    //         checked: true,
220
    //         errors: undefined,
221
    //     };
222
    // }
223

224
    const perf: SpellCheckFilePerf = {};
35✔
225
    const timer = createPerfTimer('spellCheckFullDocument', (elapsed) => (perf.totalTimeMs = elapsed));
35✔
226
    const timerCheck = createPerfTimer('check', (elapsed) => (perf.checkTimeMs = elapsed));
35✔
227
    const timerPrepare = createPerfTimer('prepare', (elapsed) => (perf.prepareTimeMs = elapsed));
35✔
228

229
    const doc = documentToTextDocument(document);
35✔
230
    const docValOptions: DocumentValidatorOptions = options;
35✔
231
    const docValidator = await DocumentValidator.create(doc, docValOptions, settingsOrConfigFile).finally(() =>
35✔
232
        timerPrepare.end(),
35✔
233
    );
234
    Object.assign(perf, Object.fromEntries(Object.entries(docValidator.perfTiming).map(([k, v]) => ['_' + k, v])));
258✔
235

236
    const prep = docValidator._getPreparations();
35✔
237

238
    if (docValidator.errors.length) {
35✔
239
        const settingsUsed =
240
            prep?.localConfig ||
3!
241
            (satisfiesCSpellConfigFile(settingsOrConfigFile) ? settingsOrConfigFile.settings : settingsOrConfigFile);
×
242

243
        return {
3✔
244
            document,
245
            options,
246
            settingsUsed,
247
            localConfigFilepath: prep?.localConfigFilepath,
248
            issues: [],
249
            checked: false,
250
            errors: docValidator.errors,
251
            configErrors: docValidator.getConfigErrors(),
252
            dictionaryErrors: docValidator.getDictionaryErrors(),
253
            perf,
254
        };
255
    }
256

257
    timerCheck.start();
32✔
258
    const issues = docValidator.checkDocument();
32✔
259
    timerCheck.end();
32✔
260

261
    Object.assign(perf, Object.fromEntries(Object.entries(docValidator.perfTiming).map(([k, v]) => ['_' + k, v])));
268✔
262

263
    const result: SpellCheckFileResult = {
32✔
264
        document,
265
        options,
266
        settingsUsed: docValidator.getFinalizedDocSettings(),
267
        localConfigFilepath: prep?.localConfigFilepath,
268
        issues,
269
        checked: docValidator.shouldCheckDocument(),
270
        errors: undefined,
271
        configErrors: docValidator.getConfigErrors(),
272
        dictionaryErrors: docValidator.getDictionaryErrors(),
273
        perf,
274
    };
275
    timer.end();
32✔
276
    return result;
32✔
277
}
278

279
export interface DetermineFinalDocumentSettingsResult {
280
    document: DocumentWithText;
281
    settings: CSpellSettingsWithSourceTrace;
282
}
283

284
/**
285
 * Combines all relevant setting values into a final configuration to be used for spell checking.
286
 * It applies any overrides and appropriate language settings by taking into account the document type (languageId)
287
 * the locale (natural language) and any in document settings.
288
 *
289
 * Note: this method will not search for configuration files. Configuration files should already be merged into `settings`.
290
 * It is NOT necessary to include the cspell defaultSettings or globalSettings. They will be applied within this function.
291
 * @param document - The document to be spell checked. Note: if the URI doesn't have a path, overrides cannot be applied.
292
 *   `locale` - if defined will be used unless it is overridden by an in-document setting.
293
 *   `languageId` - if defined will be used to select appropriate file type dictionaries.
294
 * @param settings - The near final settings. Should already be the combination of all configuration files.
295
 */
296
export async function determineFinalDocumentSettings(
297
    document: DocumentWithText,
298
    settings: CSpellUserSettings,
299
): Promise<DetermineFinalDocumentSettingsResult> {
300
    const doc = createTextDocument({
9✔
301
        uri: document.uri,
302
        content: document.text,
303
        languageId: document.languageId,
304
        locale: document.locale,
305
    });
306
    return {
9✔
307
        document,
308
        settings: await determineTextDocumentSettings(doc, settings),
309
    };
310
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc