cspell 5.10.0 → 5.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +7 -0
- package/dist/cli-reporter.d.ts +9 -1
- package/dist/cli-reporter.js +58 -27
- package/dist/fileHelper.d.ts +11 -3
- package/dist/lint.d.ts +1 -10
- package/dist/lint.js +46 -45
- package/dist/options.d.ts +14 -0
- package/dist/util/cache/DiskCache.d.ts +13 -0
- package/dist/util/cache/DiskCache.js +51 -0
- package/dist/util/cache/DummyCache.d.ts +10 -0
- package/dist/util/cache/DummyCache.js +19 -0
- package/dist/util/cache/getConfigHash.d.ts +6 -0
- package/dist/util/cache/getConfigHash.js +26 -0
- package/dist/util/cache/hash.d.ts +5 -0
- package/dist/util/cache/hash.js +16 -0
- package/dist/util/cache/index.d.ts +22 -0
- package/dist/util/cache/index.js +20 -0
- package/dist/util/glob.js +1 -1
- package/dist/util/timer.d.ts +1 -1
- package/dist/util/timer.js +4 -15
- package/package.json +14 -9
package/dist/app.js
CHANGED
|
@@ -32,6 +32,7 @@ const table_1 = require("./util/table");
|
|
|
32
32
|
const traceEmitter_1 = require("./traceEmitter");
|
|
33
33
|
const cli_reporter_1 = require("./cli-reporter");
|
|
34
34
|
const errors_1 = require("./util/errors");
|
|
35
|
+
const cache_1 = require("./util/cache");
|
|
35
36
|
var errors_2 = require("./util/errors");
|
|
36
37
|
Object.defineProperty(exports, "CheckFailed", { enumerable: true, get: function () { return errors_2.CheckFailed; } });
|
|
37
38
|
// interface InitOptions extends Options {}
|
|
@@ -71,6 +72,12 @@ async function run(program, argv) {
|
|
|
71
72
|
// .option('--force', 'Force the exit value to always be 0')
|
|
72
73
|
.option('--legacy', 'Legacy output')
|
|
73
74
|
.option('--local <local>', 'Deprecated -- Use: --locale')
|
|
75
|
+
.option('--cache', 'Only check changed files', false)
|
|
76
|
+
.addOption(new commander.Option('--cache-strategy <strategy>', 'Strategy to use for detecting changed files').choices([
|
|
77
|
+
'metadata',
|
|
78
|
+
'content',
|
|
79
|
+
]))
|
|
80
|
+
.option('--cache-location <path>', `Path to the cache file or directory`, cache_1.DEFAULT_CACHE_LOCATION)
|
|
74
81
|
.addHelpText('after', usage)
|
|
75
82
|
.arguments('[files...]')
|
|
76
83
|
.action((files, options) => {
|
package/dist/cli-reporter.d.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import type { CSpellReporter } from '@cspell/cspell-types';
|
|
1
|
+
import type { CSpellReporter, Issue } from '@cspell/cspell-types';
|
|
2
2
|
import { Options } from './app';
|
|
3
|
+
export interface ReporterIssue extends Issue {
|
|
4
|
+
filename: string;
|
|
5
|
+
}
|
|
3
6
|
export declare function getReporter(options: Options): CSpellReporter;
|
|
7
|
+
declare function formatIssue(templateStr: string, issue: ReporterIssue, maxIssueTextWidth: number): string;
|
|
8
|
+
export declare const __testing__: {
|
|
9
|
+
formatIssue: typeof formatIssue;
|
|
10
|
+
};
|
|
11
|
+
export {};
|
|
4
12
|
//# sourceMappingURL=cli-reporter.d.ts.map
|
package/dist/cli-reporter.js
CHANGED
|
@@ -19,15 +19,16 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
19
19
|
return result;
|
|
20
20
|
};
|
|
21
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
-
exports.getReporter = void 0;
|
|
22
|
+
exports.__testing__ = exports.getReporter = void 0;
|
|
23
23
|
const chalk = require("chalk");
|
|
24
24
|
const cspell_lib_1 = require("cspell-lib");
|
|
25
25
|
const path = __importStar(require("path"));
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
const
|
|
26
|
+
const vscode_uri_1 = require("vscode-uri");
|
|
27
|
+
const templateIssue = `{green $filename}:{yellow $row:$col} - $message ({red $text})`;
|
|
28
|
+
const templateIssueWithSuggestions = `{green $filename}:{yellow $row:$col} - $message ({red $text}) Suggestions: {yellow [$suggestions]}`;
|
|
29
|
+
const templateIssueWithContext = `{green $filename}:{yellow $row:$col} $padRowCol- $message ({red $text})$padContext -- {gray $contextLeft}{red {underline $text}}{gray $contextRight}`;
|
|
30
|
+
const templateIssueWithContextWithSuggestions = `{green $filename}:{yellow $row:$col} $padRowCol- $message ({red $text})$padContext -- {gray $contextLeft}{red {underline $text}}{gray $contextRight}\n\t Suggestions: {yellow [$suggestions]}`;
|
|
31
|
+
const templateIssueLegacy = `${chalk.green('$filename')}[$row, $col]: $message: ${chalk.red('$text')}`;
|
|
31
32
|
const templateIssueWordsOnly = '$text';
|
|
32
33
|
function genIssueEmitter(template) {
|
|
33
34
|
const defaultWidth = 10;
|
|
@@ -57,6 +58,13 @@ function relativeFilename(filename, cwd = process.cwd()) {
|
|
|
57
58
|
return filename;
|
|
58
59
|
return '.' + path.sep + rel;
|
|
59
60
|
}
|
|
61
|
+
function relativeUriFilename(uri, fsPathRoot) {
|
|
62
|
+
const fsPath = vscode_uri_1.URI.parse(uri).fsPath;
|
|
63
|
+
const rel = path.relative(fsPathRoot, fsPath);
|
|
64
|
+
if (rel.startsWith('..'))
|
|
65
|
+
return fsPath;
|
|
66
|
+
return '.' + path.sep + rel;
|
|
67
|
+
}
|
|
60
68
|
function reportProgress(p) {
|
|
61
69
|
if (p.type !== 'ProgressFileComplete') {
|
|
62
70
|
return;
|
|
@@ -98,13 +106,15 @@ function getReporter(options) {
|
|
|
98
106
|
var _a;
|
|
99
107
|
(_a = emitters[msgType]) === null || _a === void 0 ? void 0 : _a.call(emitters, message);
|
|
100
108
|
}
|
|
101
|
-
const root = options.root || process.cwd();
|
|
109
|
+
const root = vscode_uri_1.URI.file(options.root || process.cwd());
|
|
110
|
+
const fsPathRoot = root.fsPath;
|
|
102
111
|
function relativeIssue(fn) {
|
|
103
|
-
|
|
104
|
-
|
|
112
|
+
const fnFilename = options.relative
|
|
113
|
+
? (uri) => relativeUriFilename(uri, fsPathRoot)
|
|
114
|
+
: (uri) => vscode_uri_1.URI.parse(uri).fsPath;
|
|
105
115
|
return (i) => {
|
|
106
|
-
const
|
|
107
|
-
r
|
|
116
|
+
const filename = i.uri ? fnFilename(i.uri) : '';
|
|
117
|
+
const r = { ...i, filename };
|
|
108
118
|
fn(r);
|
|
109
119
|
};
|
|
110
120
|
}
|
|
@@ -129,7 +139,7 @@ function formatIssue(templateStr, issue, maxIssueTextWidth) {
|
|
|
129
139
|
function clean(t) {
|
|
130
140
|
return t.replace(/\s+/, ' ');
|
|
131
141
|
}
|
|
132
|
-
const { uri = '', row, col, text, context, offset } = issue;
|
|
142
|
+
const { uri = '', filename, row, col, text, context, offset } = issue;
|
|
133
143
|
const contextLeft = clean(context.text.slice(0, offset - context.offset));
|
|
134
144
|
const contextRight = clean(context.text.slice(offset + text.length - context.offset));
|
|
135
145
|
const contextFull = clean(context.text);
|
|
@@ -139,22 +149,21 @@ function formatIssue(templateStr, issue, maxIssueTextWidth) {
|
|
|
139
149
|
const padRowCol = ' '.repeat(Math.max(1, 8 - (rowText.length + colText.length)));
|
|
140
150
|
const suggestions = ((_a = issue.suggestions) === null || _a === void 0 ? void 0 : _a.join(', ')) || '';
|
|
141
151
|
const message = issue.isFlagged ? '{yellow Forbidden word}' : 'Unknown word';
|
|
152
|
+
const substitutions = {
|
|
153
|
+
$col: colText,
|
|
154
|
+
$contextFull: contextFull,
|
|
155
|
+
$contextLeft: contextLeft,
|
|
156
|
+
$contextRight: contextRight,
|
|
157
|
+
$filename: filename,
|
|
158
|
+
$padContext: padContext,
|
|
159
|
+
$padRowCol: padRowCol,
|
|
160
|
+
$row: rowText,
|
|
161
|
+
$suggestions: suggestions,
|
|
162
|
+
$text: text,
|
|
163
|
+
$uri: uri,
|
|
164
|
+
};
|
|
142
165
|
const t = template(templateStr.replace(/\$message/g, message));
|
|
143
|
-
return chalk(t)
|
|
144
|
-
.replace(/\$\{col\}/g, colText)
|
|
145
|
-
.replace(/\$\{row\}/g, rowText)
|
|
146
|
-
.replace(/\$\{text\}/g, text)
|
|
147
|
-
.replace(/\$\{uri\}/g, uri)
|
|
148
|
-
.replace(/\$col/g, colText)
|
|
149
|
-
.replace(/\$contextFull/g, contextFull)
|
|
150
|
-
.replace(/\$contextLeft/g, contextLeft)
|
|
151
|
-
.replace(/\$contextRight/g, contextRight)
|
|
152
|
-
.replace(/\$padContext/g, padContext)
|
|
153
|
-
.replace(/\$padRowCol/g, padRowCol)
|
|
154
|
-
.replace(/\$row/g, rowText)
|
|
155
|
-
.replace(/\$suggestions/g, suggestions)
|
|
156
|
-
.replace(/\$text/g, text)
|
|
157
|
-
.replace(/\$uri/g, uri);
|
|
166
|
+
return substitute(chalk(t), substitutions);
|
|
158
167
|
}
|
|
159
168
|
class TS extends Array {
|
|
160
169
|
constructor(s) {
|
|
@@ -165,4 +174,26 @@ class TS extends Array {
|
|
|
165
174
|
function template(s) {
|
|
166
175
|
return new TS(s);
|
|
167
176
|
}
|
|
177
|
+
function substitute(text, substitutions) {
|
|
178
|
+
const subs = [];
|
|
179
|
+
for (const [match, replaceWith] of Object.entries(substitutions)) {
|
|
180
|
+
const len = match.length;
|
|
181
|
+
for (let i = text.indexOf(match); i >= 0; i = text.indexOf(match, i + 1)) {
|
|
182
|
+
subs.push([i, i + len, replaceWith]);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
subs.sort((a, b) => a[0] - b[0]);
|
|
186
|
+
let i = 0;
|
|
187
|
+
function sub(r) {
|
|
188
|
+
const [a, b, t] = r;
|
|
189
|
+
const prefix = text.slice(i, a);
|
|
190
|
+
i = b;
|
|
191
|
+
return prefix + t;
|
|
192
|
+
}
|
|
193
|
+
const parts = subs.map(sub);
|
|
194
|
+
return parts.join('') + text.slice(i);
|
|
195
|
+
}
|
|
196
|
+
exports.__testing__ = {
|
|
197
|
+
formatIssue,
|
|
198
|
+
};
|
|
168
199
|
//# sourceMappingURL=cli-reporter.js.map
|
package/dist/fileHelper.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { GlobOptions } from './util/glob';
|
|
2
|
-
import { CSpellUserSettings, Document } from 'cspell-lib';
|
|
2
|
+
import { CSpellUserSettings, Document, Issue } from 'cspell-lib';
|
|
3
3
|
export interface ConfigInfo {
|
|
4
4
|
source: string;
|
|
5
5
|
config: CSpellUserSettings;
|
|
@@ -13,10 +13,18 @@ export interface FileConfigInfo {
|
|
|
13
13
|
export declare function readConfig(configFile: string | undefined, root: string | undefined): Promise<ConfigInfo>;
|
|
14
14
|
export interface FileInfo {
|
|
15
15
|
filename: string;
|
|
16
|
-
text
|
|
16
|
+
text?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface FileResult {
|
|
19
|
+
fileInfo: FileInfo;
|
|
20
|
+
processed: boolean;
|
|
21
|
+
issues: Issue[];
|
|
22
|
+
errors: number;
|
|
23
|
+
configErrors: number;
|
|
24
|
+
elapsedTimeMs: number;
|
|
17
25
|
}
|
|
18
26
|
export declare function fileInfoToDocument(fileInfo: FileInfo, languageId: string | undefined, locale: string | undefined): Document;
|
|
19
|
-
export declare function readFileInfo(filename: string, encoding?: string): Promise<FileInfo
|
|
27
|
+
export declare function readFileInfo(filename: string, encoding?: string): Promise<Required<FileInfo>>;
|
|
20
28
|
export declare function readFile(filename: string, encoding?: string): Promise<string>;
|
|
21
29
|
/**
|
|
22
30
|
* Looks for matching glob patterns or stdin
|
package/dist/lint.d.ts
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RunResult } from '@cspell/cspell-types';
|
|
2
2
|
import { CSpellApplicationConfiguration } from './CSpellApplicationConfiguration';
|
|
3
|
-
import { FileInfo } from './fileHelper';
|
|
4
|
-
export interface FileResult {
|
|
5
|
-
fileInfo: FileInfo;
|
|
6
|
-
processed: boolean;
|
|
7
|
-
issues: Issue[];
|
|
8
|
-
errors: number;
|
|
9
|
-
configErrors: number;
|
|
10
|
-
elapsedTimeMs: number;
|
|
11
|
-
}
|
|
12
3
|
export declare function runLint(cfg: CSpellApplicationConfiguration): Promise<RunResult>;
|
|
13
4
|
//# sourceMappingURL=lint.d.ts.map
|
package/dist/lint.js
CHANGED
|
@@ -27,6 +27,7 @@ const path = __importStar(require("path"));
|
|
|
27
27
|
const util_1 = require("util");
|
|
28
28
|
const vscode_uri_1 = require("vscode-uri");
|
|
29
29
|
const fileHelper_1 = require("./fileHelper");
|
|
30
|
+
const cache_1 = require("./util/cache");
|
|
30
31
|
const errors_1 = require("./util/errors");
|
|
31
32
|
const glob_1 = require("./util/glob");
|
|
32
33
|
const reporters_1 = require("./util/reporters");
|
|
@@ -39,11 +40,17 @@ async function runLint(cfg) {
|
|
|
39
40
|
const lintResult = await run();
|
|
40
41
|
await reporter.result(lintResult);
|
|
41
42
|
return lintResult;
|
|
42
|
-
async function processFile(
|
|
43
|
+
async function processFile(filename, configInfo, cache) {
|
|
43
44
|
var _a, _b, _c, _d;
|
|
45
|
+
const cachedResult = await cache.getCachedLintResults(filename, configInfo);
|
|
46
|
+
if (cachedResult) {
|
|
47
|
+
reporter.debug(`Filename: ${filename}, using cache`);
|
|
48
|
+
return cachedResult;
|
|
49
|
+
}
|
|
50
|
+
const fileInfo = await (0, fileHelper_1.readFileInfo)(filename);
|
|
44
51
|
const doc = (0, fileHelper_1.fileInfoToDocument)(fileInfo, cfg.options.languageId, cfg.locale);
|
|
45
|
-
const {
|
|
46
|
-
reporter.debug(`Filename: ${
|
|
52
|
+
const { text } = fileInfo;
|
|
53
|
+
reporter.debug(`Filename: ${filename}, LanguageIds: ${(_a = doc.languageId) !== null && _a !== void 0 ? _a : 'default'}`);
|
|
47
54
|
const result = {
|
|
48
55
|
fileInfo,
|
|
49
56
|
issues: [],
|
|
@@ -52,7 +59,7 @@ async function runLint(cfg) {
|
|
|
52
59
|
configErrors: 0,
|
|
53
60
|
elapsedTimeMs: 0,
|
|
54
61
|
};
|
|
55
|
-
const
|
|
62
|
+
const getElapsedTimeMs = (0, timer_1.getTimeMeasurer)();
|
|
56
63
|
let spellResult = {};
|
|
57
64
|
reporter.info(`Checking: ${filename}, File type: ${(_b = doc.languageId) !== null && _b !== void 0 ? _b : 'auto'}, Language: ${(_c = doc.locale) !== null && _c !== void 0 ? _c : 'default'}`, cspell_types_1.MessageTypes.Info);
|
|
58
65
|
try {
|
|
@@ -60,13 +67,13 @@ async function runLint(cfg) {
|
|
|
60
67
|
const r = await cspell.spellCheckDocument(doc, validateOptions, configInfo.config);
|
|
61
68
|
spellResult = r;
|
|
62
69
|
result.processed = r.checked;
|
|
63
|
-
result.issues = cspell.Text.calculateTextDocumentOffsets(
|
|
70
|
+
result.issues = cspell.Text.calculateTextDocumentOffsets(doc.uri, text, r.issues).map(mapIssue);
|
|
64
71
|
}
|
|
65
72
|
catch (e) {
|
|
66
73
|
reporter.error(`Failed to process "${filename}"`, (0, errors_1.toError)(e));
|
|
67
74
|
result.errors += 1;
|
|
68
75
|
}
|
|
69
|
-
result.elapsedTimeMs =
|
|
76
|
+
result.elapsedTimeMs = getElapsedTimeMs();
|
|
70
77
|
const config = (_d = spellResult.settingsUsed) !== null && _d !== void 0 ? _d : {};
|
|
71
78
|
result.configErrors += await reportConfigurationErrors(config);
|
|
72
79
|
const debugCfg = { config: { ...config, source: null }, source: spellResult.localConfigFilepath };
|
|
@@ -76,59 +83,52 @@ async function runLint(cfg) {
|
|
|
76
83
|
reporter.info(`Checked: ${filename}, File type: ${config.languageId}, Language: ${config.language} ... Issues: ${result.issues.length} ${elapsed}S`, cspell_types_1.MessageTypes.Info);
|
|
77
84
|
reporter.info(`Config file Used: ${spellResult.localConfigFilepath || configInfo.source}`, cspell_types_1.MessageTypes.Info);
|
|
78
85
|
reporter.info(`Dictionaries Used: ${dictionaries.join(', ')}`, cspell_types_1.MessageTypes.Info);
|
|
86
|
+
cache.setCachedLintResults(result, configInfo);
|
|
79
87
|
return result;
|
|
80
88
|
}
|
|
81
|
-
function mapIssue(tdo) {
|
|
89
|
+
function mapIssue({ doc: _, ...tdo }) {
|
|
82
90
|
const context = cfg.showContext
|
|
83
91
|
? extractContext(tdo, cfg.showContext)
|
|
84
92
|
: { text: tdo.line.text.trimEnd(), offset: tdo.line.offset };
|
|
85
93
|
return { ...tdo, context };
|
|
86
94
|
}
|
|
87
|
-
/**
|
|
88
|
-
* The file loader is written this way to cause files to be loaded in parallel while the previous one is being processed.
|
|
89
|
-
* @param fileNames names of files to load one at a time.
|
|
90
|
-
*/
|
|
91
|
-
function* fileLoader(fileNames) {
|
|
92
|
-
for (const filename of fileNames) {
|
|
93
|
-
const file = (0, fileHelper_1.readFileInfo)(filename);
|
|
94
|
-
yield file;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
95
|
async function processFiles(files, configInfo, fileCount) {
|
|
98
96
|
const status = runResult();
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
97
|
+
const cache = (0, cache_1.createCache)(cfg);
|
|
98
|
+
const emitProgress = (filename, fileNum, result) => reporter.progress({
|
|
99
|
+
type: 'ProgressFileComplete',
|
|
100
|
+
fileNum,
|
|
101
|
+
fileCount,
|
|
102
|
+
filename,
|
|
103
|
+
elapsedTimeMs: result === null || result === void 0 ? void 0 : result.elapsedTimeMs,
|
|
104
|
+
processed: result === null || result === void 0 ? void 0 : result.processed,
|
|
105
|
+
numErrors: result === null || result === void 0 ? void 0 : result.issues.length,
|
|
106
|
+
});
|
|
107
|
+
async function* loadAndProcessFiles() {
|
|
108
|
+
for (let i = 0; i < files.length; i++) {
|
|
109
|
+
const filename = files[i];
|
|
110
|
+
const result = await processFile(filename, configInfo, cache);
|
|
111
|
+
yield { filename, fileNum: i + 1, result };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
for await (const fileP of loadAndProcessFiles()) {
|
|
115
|
+
const { filename, fileNum, result } = await fileP;
|
|
116
|
+
if (!result.fileInfo.text) {
|
|
117
|
+
emitProgress(filename, fileNum);
|
|
115
118
|
continue;
|
|
116
119
|
}
|
|
117
|
-
|
|
118
|
-
const { elapsedTimeMs } = await (0, timer_1.measurePromise)(p);
|
|
119
|
-
const result = await p;
|
|
120
|
-
emitProgress(elapsedTimeMs, result.processed, result.issues.length);
|
|
120
|
+
emitProgress(filename, fileNum, result);
|
|
121
121
|
// Show the spelling errors after emitting the progress.
|
|
122
122
|
result.issues.filter(cfg.uniqueFilter).forEach((issue) => reporter.issue(issue));
|
|
123
|
-
const r = await p;
|
|
124
123
|
status.files += 1;
|
|
125
|
-
if (
|
|
126
|
-
status.filesWithIssues.add(
|
|
127
|
-
status.issues +=
|
|
128
|
-
status.errors +=
|
|
124
|
+
if (result.issues.length || result.errors) {
|
|
125
|
+
status.filesWithIssues.add(filename);
|
|
126
|
+
status.issues += result.issues.length;
|
|
127
|
+
status.errors += result.errors;
|
|
129
128
|
}
|
|
130
|
-
status.errors +=
|
|
129
|
+
status.errors += result.configErrors;
|
|
131
130
|
}
|
|
131
|
+
cache.reconcile();
|
|
132
132
|
return status;
|
|
133
133
|
}
|
|
134
134
|
async function reportConfigurationErrors(config) {
|
|
@@ -190,9 +190,10 @@ async function runLint(cfg) {
|
|
|
190
190
|
const globsToExclude = (configInfo.config.ignorePaths || []).concat(excludeGlobs);
|
|
191
191
|
const globMatcher = (0, glob_1.buildGlobMatcher)(globsToExclude, root, true);
|
|
192
192
|
const ignoreGlobs = (0, glob_1.extractGlobsFromMatcher)(globMatcher);
|
|
193
|
-
|
|
193
|
+
// cspell:word nodir
|
|
194
|
+
const globOptions = { root, cwd: root, ignore: ignoreGlobs.concat(normalizedExcludes), nodir: true };
|
|
194
195
|
const files = filterFiles(await (0, fileHelper_1.findFiles)(fileGlobs, globOptions), globMatcher);
|
|
195
|
-
return processFiles(
|
|
196
|
+
return processFiles(files, configInfo, files.length);
|
|
196
197
|
}
|
|
197
198
|
function header(files, cliExcludes) {
|
|
198
199
|
const formattedFiles = files.length > 100 ? files.slice(0, 100).concat(['...']) : files;
|
package/dist/options.d.ts
CHANGED
|
@@ -33,6 +33,20 @@ export interface CSpellApplicationOptions extends BaseOptions {
|
|
|
33
33
|
* Show suggestions for spelling errors.
|
|
34
34
|
*/
|
|
35
35
|
showSuggestions?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Store the info about processed files in order to only operate on the changed ones.
|
|
38
|
+
*/
|
|
39
|
+
cache?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Path to the cache location. Can be a file or a directory.
|
|
42
|
+
* If none specified .cspellcache will be used.
|
|
43
|
+
* The file will be created in the directory where the cspell command is executed.
|
|
44
|
+
*/
|
|
45
|
+
cacheLocation?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Strategy to use for detecting changed files, default: metadata
|
|
48
|
+
*/
|
|
49
|
+
cacheStrategy?: 'metadata' | 'content';
|
|
36
50
|
}
|
|
37
51
|
export declare type TraceOptions = BaseOptions;
|
|
38
52
|
export interface BaseOptions {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ConfigInfo, FileResult } from '../../fileHelper';
|
|
2
|
+
import { CSpellLintResultCache } from '.';
|
|
3
|
+
/**
|
|
4
|
+
* Caches cspell results on disk
|
|
5
|
+
*/
|
|
6
|
+
export declare class DiskCache implements CSpellLintResultCache {
|
|
7
|
+
private fileEntryCache;
|
|
8
|
+
constructor(cacheFileLocation: string, useCheckSum: boolean);
|
|
9
|
+
getCachedLintResults(filename: string, configInfo: ConfigInfo): Promise<FileResult | undefined>;
|
|
10
|
+
setCachedLintResults({ fileInfo, elapsedTimeMs: _, ...result }: FileResult, configInfo: ConfigInfo): void;
|
|
11
|
+
reconcile(): void;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=DiskCache.d.ts.map
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DiskCache = void 0;
|
|
4
|
+
const file_entry_cache_1 = require("file-entry-cache");
|
|
5
|
+
const fileHelper_1 = require("../../fileHelper");
|
|
6
|
+
const getConfigHash_1 = require("./getConfigHash");
|
|
7
|
+
/**
|
|
8
|
+
* Caches cspell results on disk
|
|
9
|
+
*/
|
|
10
|
+
class DiskCache {
|
|
11
|
+
constructor(cacheFileLocation, useCheckSum) {
|
|
12
|
+
this.fileEntryCache = (0, file_entry_cache_1.create)(cacheFileLocation, undefined, useCheckSum);
|
|
13
|
+
}
|
|
14
|
+
async getCachedLintResults(filename, configInfo) {
|
|
15
|
+
const fileDescriptor = this.fileEntryCache.getFileDescriptor(filename);
|
|
16
|
+
const meta = fileDescriptor.meta;
|
|
17
|
+
// Cached lint results are valid if and only if:
|
|
18
|
+
// 1. The file is present in the filesystem
|
|
19
|
+
// 2. The file has not changed since the time it was previously linted
|
|
20
|
+
// 3. The CSpell configuration has not changed since the time the file was previously linted
|
|
21
|
+
// If any of these are not true, we will not reuse the lint results.
|
|
22
|
+
if (fileDescriptor.notFound ||
|
|
23
|
+
fileDescriptor.changed ||
|
|
24
|
+
!meta ||
|
|
25
|
+
meta.configHash !== (0, getConfigHash_1.getConfigHash)(configInfo)) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
// Skip reading empty files and files without lint error
|
|
29
|
+
const hasErrors = meta.result.errors > 0 || meta.result.configErrors > 0 || meta.result.issues.length > 0;
|
|
30
|
+
const shouldReadFile = meta.size !== 0 && hasErrors;
|
|
31
|
+
return {
|
|
32
|
+
...meta.result,
|
|
33
|
+
elapsedTimeMs: 0,
|
|
34
|
+
fileInfo: shouldReadFile ? await (0, fileHelper_1.readFileInfo)(filename) : { filename },
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
setCachedLintResults({ fileInfo, elapsedTimeMs: _, ...result }, configInfo) {
|
|
38
|
+
const fileDescriptor = this.fileEntryCache.getFileDescriptor(fileInfo.filename);
|
|
39
|
+
const meta = fileDescriptor.meta;
|
|
40
|
+
if (fileDescriptor.notFound || !meta) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
meta.result = result;
|
|
44
|
+
meta.configHash = (0, getConfigHash_1.getConfigHash)(configInfo);
|
|
45
|
+
}
|
|
46
|
+
reconcile() {
|
|
47
|
+
this.fileEntryCache.reconcile();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.DiskCache = DiskCache;
|
|
51
|
+
//# sourceMappingURL=DiskCache.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CSpellLintResultCache } from '.';
|
|
2
|
+
/**
|
|
3
|
+
* Dummy cache implementation that should be usd if caching option is disabled.
|
|
4
|
+
*/
|
|
5
|
+
export declare class DummyCache implements CSpellLintResultCache {
|
|
6
|
+
getCachedLintResults(): Promise<undefined>;
|
|
7
|
+
setCachedLintResults(): void;
|
|
8
|
+
reconcile(): void;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=DummyCache.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DummyCache = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Dummy cache implementation that should be usd if caching option is disabled.
|
|
6
|
+
*/
|
|
7
|
+
class DummyCache {
|
|
8
|
+
getCachedLintResults() {
|
|
9
|
+
return Promise.resolve(undefined);
|
|
10
|
+
}
|
|
11
|
+
setCachedLintResults() {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
reconcile() {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.DummyCache = DummyCache;
|
|
19
|
+
//# sourceMappingURL=DummyCache.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getConfigHash = void 0;
|
|
7
|
+
const fast_json_stable_stringify_1 = __importDefault(require("fast-json-stable-stringify"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const hash_1 = require("./hash");
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
11
|
+
const { version } = require(path_1.default.join(__dirname, '..', '..', '..', 'package.json'));
|
|
12
|
+
const configHashes = new WeakMap();
|
|
13
|
+
/**
|
|
14
|
+
* Hashes ConfigInfo and cspell version for using in DiskCache
|
|
15
|
+
*/
|
|
16
|
+
function getConfigHash(configInfo) {
|
|
17
|
+
const cachedHash = configHashes.get(configInfo);
|
|
18
|
+
if (cachedHash !== undefined) {
|
|
19
|
+
return cachedHash;
|
|
20
|
+
}
|
|
21
|
+
const hashValue = (0, hash_1.hash)(`${version}_${(0, fast_json_stable_stringify_1.default)(configInfo)}`);
|
|
22
|
+
configHashes.set(configInfo, hashValue);
|
|
23
|
+
return hashValue;
|
|
24
|
+
}
|
|
25
|
+
exports.getConfigHash = getConfigHash;
|
|
26
|
+
//# sourceMappingURL=getConfigHash.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.hash = void 0;
|
|
7
|
+
// cspell:word imurmurhash
|
|
8
|
+
const imurmurhash_1 = __importDefault(require("imurmurhash"));
|
|
9
|
+
/**
|
|
10
|
+
* Hash the given string using MurmurHash3
|
|
11
|
+
*/
|
|
12
|
+
function hash(str) {
|
|
13
|
+
return (0, imurmurhash_1.default)(str).result().toString(36);
|
|
14
|
+
}
|
|
15
|
+
exports.hash = hash;
|
|
16
|
+
//# sourceMappingURL=hash.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { CSpellApplicationConfiguration } from '../../CSpellApplicationConfiguration';
|
|
2
|
+
import type { ConfigInfo, FileResult } from '../../fileHelper';
|
|
3
|
+
export declare const DEFAULT_CACHE_LOCATION = ".cspellcache";
|
|
4
|
+
export interface CSpellLintResultCache {
|
|
5
|
+
/**
|
|
6
|
+
* Retrieve cached lint results for a given file name, if present in the cache.
|
|
7
|
+
*/
|
|
8
|
+
getCachedLintResults(filename: string, configInfo: ConfigInfo): Promise<FileResult | undefined>;
|
|
9
|
+
/**
|
|
10
|
+
* Set the cached lint results.
|
|
11
|
+
*/
|
|
12
|
+
setCachedLintResults(result: FileResult, configInfo: ConfigInfo): void;
|
|
13
|
+
/**
|
|
14
|
+
* Persists the in-memory cache to disk.
|
|
15
|
+
*/
|
|
16
|
+
reconcile(): void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Creates CSpellLintResultCache (disk cache if caching is enabled in config or dummy otherwise)
|
|
20
|
+
*/
|
|
21
|
+
export declare function createCache(cfg: CSpellApplicationConfiguration): CSpellLintResultCache;
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createCache = exports.DEFAULT_CACHE_LOCATION = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const DummyCache_1 = require("./DummyCache");
|
|
9
|
+
const DiskCache_1 = require("./DiskCache");
|
|
10
|
+
// cspell:word cspellcache
|
|
11
|
+
exports.DEFAULT_CACHE_LOCATION = '.cspellcache';
|
|
12
|
+
/**
|
|
13
|
+
* Creates CSpellLintResultCache (disk cache if caching is enabled in config or dummy otherwise)
|
|
14
|
+
*/
|
|
15
|
+
function createCache(cfg) {
|
|
16
|
+
const { cache, cacheLocation = exports.DEFAULT_CACHE_LOCATION, cacheStrategy = 'metadata' } = cfg.options;
|
|
17
|
+
return cache ? new DiskCache_1.DiskCache(path_1.default.resolve(cfg.root, cacheLocation), cacheStrategy === 'content') : new DummyCache_1.DummyCache();
|
|
18
|
+
}
|
|
19
|
+
exports.createCache = createCache;
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
package/dist/util/glob.js
CHANGED
|
@@ -66,7 +66,7 @@ function _globP(pattern, state) {
|
|
|
66
66
|
}
|
|
67
67
|
resolve(matches);
|
|
68
68
|
};
|
|
69
|
-
const options = state.glob
|
|
69
|
+
const options = { ...(state.glob || {}), ...state.options };
|
|
70
70
|
state.glob = (0, glob_1.default)(pattern, options, cb);
|
|
71
71
|
});
|
|
72
72
|
}
|
package/dist/util/timer.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export interface MeasurePromiseResult {
|
|
|
2
2
|
elapsedTimeMs: number;
|
|
3
3
|
success: boolean;
|
|
4
4
|
}
|
|
5
|
-
export declare function
|
|
5
|
+
export declare function getTimeMeasurer(): () => number;
|
|
6
6
|
export declare function elapsedTimeMsFrom(relativeTo: [number, number]): number;
|
|
7
7
|
export declare function hrTimeToMs(hrTime: [number, number]): number;
|
|
8
8
|
//# sourceMappingURL=timer.d.ts.map
|
package/dist/util/timer.js
CHANGED
|
@@ -1,22 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.hrTimeToMs = exports.elapsedTimeMsFrom = exports.
|
|
4
|
-
|
|
3
|
+
exports.hrTimeToMs = exports.elapsedTimeMsFrom = exports.getTimeMeasurer = void 0;
|
|
4
|
+
function getTimeMeasurer() {
|
|
5
5
|
const start = process.hrtime();
|
|
6
|
-
|
|
7
|
-
try {
|
|
8
|
-
await p;
|
|
9
|
-
}
|
|
10
|
-
catch (e) {
|
|
11
|
-
success = false;
|
|
12
|
-
}
|
|
13
|
-
const elapsedTimeMs = hrTimeToMs(process.hrtime(start));
|
|
14
|
-
return {
|
|
15
|
-
elapsedTimeMs,
|
|
16
|
-
success,
|
|
17
|
-
};
|
|
6
|
+
return () => hrTimeToMs(process.hrtime(start));
|
|
18
7
|
}
|
|
19
|
-
exports.
|
|
8
|
+
exports.getTimeMeasurer = getTimeMeasurer;
|
|
20
9
|
function elapsedTimeMsFrom(relativeTo) {
|
|
21
10
|
return hrTimeToMs(process.hrtime(relativeTo));
|
|
22
11
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cspell",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.11.1",
|
|
4
4
|
"description": "A Spelling Checker for Code!",
|
|
5
5
|
"funding": "https://github.com/streetsidesoftware/cspell?sponsor=1",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -72,27 +72,32 @@
|
|
|
72
72
|
"chalk": "^4.1.2",
|
|
73
73
|
"commander": "^8.2.0",
|
|
74
74
|
"comment-json": "^4.1.1",
|
|
75
|
-
"cspell-glob": "^5.
|
|
76
|
-
"cspell-lib": "^5.
|
|
75
|
+
"cspell-glob": "^5.11.1",
|
|
76
|
+
"cspell-lib": "^5.11.1",
|
|
77
|
+
"fast-json-stable-stringify": "^2.1.0",
|
|
78
|
+
"file-entry-cache": "^6.0.1",
|
|
77
79
|
"fs-extra": "^10.0.0",
|
|
78
80
|
"get-stdin": "^8.0.0",
|
|
79
|
-
"glob": "^7.
|
|
80
|
-
"
|
|
81
|
+
"glob": "^7.2.0",
|
|
82
|
+
"imurmurhash": "^0.1.4",
|
|
83
|
+
"strip-ansi": "^6.0.1",
|
|
81
84
|
"vscode-uri": "^3.0.2"
|
|
82
85
|
},
|
|
83
86
|
"engines": {
|
|
84
87
|
"node": ">=12.13.0"
|
|
85
88
|
},
|
|
86
89
|
"devDependencies": {
|
|
87
|
-
"@cspell/cspell-types": "^5.
|
|
88
|
-
"@types/
|
|
90
|
+
"@cspell/cspell-types": "^5.11.1",
|
|
91
|
+
"@types/file-entry-cache": "^5.0.2",
|
|
92
|
+
"@types/fs-extra": "^9.0.13",
|
|
89
93
|
"@types/glob": "^7.1.4",
|
|
94
|
+
"@types/imurmurhash": "^0.1.1",
|
|
90
95
|
"@types/micromatch": "^4.0.2",
|
|
91
96
|
"@types/minimatch": "^3.0.5",
|
|
92
|
-
"jest": "^27.2.
|
|
97
|
+
"jest": "^27.2.3",
|
|
93
98
|
"micromatch": "^4.0.4",
|
|
94
99
|
"minimatch": "^3.0.4",
|
|
95
100
|
"rimraf": "^3.0.2"
|
|
96
101
|
},
|
|
97
|
-
"gitHead": "
|
|
102
|
+
"gitHead": "ef2cd2332a126afba25f288d5a3d726db7b6ca90"
|
|
98
103
|
}
|