cspell-lib 8.2.3 → 8.2.4
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/esm/Settings/Controller/configLoader/configSearch.d.ts +1 -0
- package/dist/esm/Settings/Controller/configLoader/configSearch.js +12 -3
- package/dist/esm/Settings/DictionarySettings.js +2 -2
- package/dist/esm/SpellingDictionary/DictionaryController/DictionaryLoader.d.ts +3 -1
- package/dist/esm/SpellingDictionary/DictionaryController/DictionaryLoader.js +10 -3
- package/dist/esm/textValidation/docValidator.d.ts +15 -0
- package/dist/esm/textValidation/docValidator.js +34 -0
- package/dist/esm/trace.js +2 -5
- package/dist/esm/util/AutoResolve.d.ts +15 -0
- package/dist/esm/util/AutoResolve.js +53 -0
- package/dist/esm/util/TextRange.d.ts +4 -0
- package/dist/esm/util/simpleCache.d.ts +1 -0
- package/dist/esm/util/simpleCache.js +10 -1
- package/package.json +15 -15
|
@@ -74,17 +74,26 @@ export class ConfigSearch {
|
|
|
74
74
|
const parentInfo = await parentInfoP;
|
|
75
75
|
const name = urlBasename(dir).slice(0, -1);
|
|
76
76
|
const found = parentInfo.get(name);
|
|
77
|
-
if (!found?.isDirectory())
|
|
77
|
+
if (!found?.isDirectory() && !found?.isSymbolicLink())
|
|
78
78
|
return false;
|
|
79
79
|
}
|
|
80
80
|
const dirUrlHref = dir.href;
|
|
81
|
-
const dirInfo = await dirInfoCache.get(dirUrlHref, async () =>
|
|
81
|
+
const dirInfo = await dirInfoCache.get(dirUrlHref, async () => await this.readDir(dir));
|
|
82
82
|
const name = urlBasename(filename);
|
|
83
83
|
const found = dirInfo.get(name);
|
|
84
|
-
return
|
|
84
|
+
return found?.isFile() || found?.isSymbolicLink() || false;
|
|
85
85
|
};
|
|
86
86
|
return hasFile;
|
|
87
87
|
}
|
|
88
|
+
async readDir(dir) {
|
|
89
|
+
try {
|
|
90
|
+
const dirInfo = await this.fs.readDirectory(dir);
|
|
91
|
+
return new Map(dirInfo.map((ent) => [ent.name, ent]));
|
|
92
|
+
}
|
|
93
|
+
catch (e) {
|
|
94
|
+
return new Map();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
88
97
|
createHasFileStatCheck() {
|
|
89
98
|
const hasFile = async (filename) => {
|
|
90
99
|
const stat = await this.fs.stat(filename).catch(() => undefined);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { mapDictionaryInformationToWeightMap } from 'cspell-trie-lib';
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import { isDictionaryDefinitionInlineInternal } from '../Models/CSpellSettingsInternalDef.js';
|
|
4
|
-
import {
|
|
4
|
+
import { createAutoResolveWeakWeakCache } from '../util/AutoResolve.js';
|
|
5
5
|
import { resolveRelativeTo } from '../util/resolveFile.js';
|
|
6
6
|
import { toFilePathOrHref } from '../util/url.js';
|
|
7
7
|
import { clean } from '../util/util.js';
|
|
@@ -40,7 +40,7 @@ function fixDicPath(defPath, defFile) {
|
|
|
40
40
|
export function mapDictDefsToInternal(defs, pathToSettingsFile) {
|
|
41
41
|
return defs?.map((def) => mapDictDefToInternal(def, pathToSettingsFile));
|
|
42
42
|
}
|
|
43
|
-
const internalDefs =
|
|
43
|
+
const internalDefs = createAutoResolveWeakWeakCache();
|
|
44
44
|
export function mapDictDefToInternal(def, pathToSettingsFile) {
|
|
45
45
|
return internalDefs.get(def, (def) => _mapDictDefToInternal(def, pathToSettingsFile));
|
|
46
46
|
}
|
|
@@ -8,7 +8,9 @@ export declare class DictionaryLoader {
|
|
|
8
8
|
private inlineDictionaryCache;
|
|
9
9
|
private dictionaryCacheByDef;
|
|
10
10
|
private reader;
|
|
11
|
-
|
|
11
|
+
/** The keepAliveCache is to hold onto the most recently loaded dictionaries. */
|
|
12
|
+
private keepAliveCache;
|
|
13
|
+
constructor(fs: VFileSystem, keepAliveSize?: number);
|
|
12
14
|
loadDictionary(def: DictionaryDefinitionInternal): Promise<SpellingDictionary>;
|
|
13
15
|
/**
|
|
14
16
|
* Check to see if any of the cached dictionaries have changed. If one has changed, reload it.
|
|
@@ -3,8 +3,9 @@ import { StrongWeakMap } from '@cspell/strong-weak-map';
|
|
|
3
3
|
import { createFailedToLoadDictionary, createInlineSpellingDictionary, createSpellingDictionary, createSpellingDictionaryFromTrieFile, } from 'cspell-dictionary';
|
|
4
4
|
import { compareStats, toFileURL, urlBasename } from 'cspell-io';
|
|
5
5
|
import { isDictionaryDefinitionInlineInternal } from '../../Models/CSpellSettingsInternalDef.js';
|
|
6
|
-
import { AutoResolveWeakCache } from '../../util/AutoResolve.js';
|
|
6
|
+
import { AutoResolveWeakCache, AutoResolveWeakWeakCache } from '../../util/AutoResolve.js';
|
|
7
7
|
import { toError } from '../../util/errors.js';
|
|
8
|
+
import { SimpleCache } from '../../util/simpleCache.js';
|
|
8
9
|
import { SpellingDictionaryLoadError } from '../SpellingDictionaryError.js';
|
|
9
10
|
const MAX_AGE = 10000;
|
|
10
11
|
const loaders = {
|
|
@@ -23,11 +24,14 @@ export class DictionaryLoader {
|
|
|
23
24
|
fs;
|
|
24
25
|
dictionaryCache = new StrongWeakMap();
|
|
25
26
|
inlineDictionaryCache = new AutoResolveWeakCache();
|
|
26
|
-
dictionaryCacheByDef = new
|
|
27
|
+
dictionaryCacheByDef = new AutoResolveWeakWeakCache();
|
|
27
28
|
reader;
|
|
28
|
-
|
|
29
|
+
/** The keepAliveCache is to hold onto the most recently loaded dictionaries. */
|
|
30
|
+
keepAliveCache;
|
|
31
|
+
constructor(fs, keepAliveSize = 10) {
|
|
29
32
|
this.fs = fs;
|
|
30
33
|
this.reader = toReader(fs);
|
|
34
|
+
this.keepAliveCache = new SimpleCache(keepAliveSize);
|
|
31
35
|
}
|
|
32
36
|
loadDictionary(def) {
|
|
33
37
|
if (isDictionaryDefinitionInlineInternal(def)) {
|
|
@@ -39,6 +43,7 @@ export class DictionaryLoader {
|
|
|
39
43
|
}
|
|
40
44
|
const loadedEntry = this.loadEntry(def.path, def);
|
|
41
45
|
this.setCacheEntry(key, loadedEntry, def);
|
|
46
|
+
this.keepAliveCache.set(def, loadedEntry);
|
|
42
47
|
return loadedEntry.pending.then(([dictionary]) => dictionary);
|
|
43
48
|
}
|
|
44
49
|
/**
|
|
@@ -52,6 +57,7 @@ export class DictionaryLoader {
|
|
|
52
57
|
getCacheEntry(def) {
|
|
53
58
|
const defEntry = this.dictionaryCacheByDef.get(def);
|
|
54
59
|
if (defEntry) {
|
|
60
|
+
this.keepAliveCache.get(def);
|
|
55
61
|
return defEntry;
|
|
56
62
|
}
|
|
57
63
|
const key = this.calcKey(def);
|
|
@@ -59,6 +65,7 @@ export class DictionaryLoader {
|
|
|
59
65
|
if (entry) {
|
|
60
66
|
// replace old entry so it can be released.
|
|
61
67
|
entry.options = def;
|
|
68
|
+
this.keepAliveCache.set(def, entry);
|
|
62
69
|
}
|
|
63
70
|
return { key, entry };
|
|
64
71
|
}
|
|
@@ -72,6 +72,21 @@ export declare class DocumentValidator {
|
|
|
72
72
|
checkDocumentDirectives(forceCheck?: boolean): ValidationIssue[];
|
|
73
73
|
get document(): TextDocument;
|
|
74
74
|
updateDocumentText(text: string): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Get the calculated ranges of text that should be included in the spell checking.
|
|
77
|
+
* @returns MatchRanges of text to include.
|
|
78
|
+
*/
|
|
79
|
+
getCheckedTextRanges(): MatchRange[];
|
|
80
|
+
traceWord(word: string): {
|
|
81
|
+
word: string;
|
|
82
|
+
found: boolean;
|
|
83
|
+
foundWord: string | undefined;
|
|
84
|
+
forbidden: boolean;
|
|
85
|
+
noSuggest: boolean;
|
|
86
|
+
dictName: string;
|
|
87
|
+
dictSource: string;
|
|
88
|
+
errors: Error[] | undefined;
|
|
89
|
+
}[];
|
|
75
90
|
private defaultParser;
|
|
76
91
|
private _checkParsedText;
|
|
77
92
|
private addPossibleError;
|
|
@@ -11,6 +11,7 @@ import { calcSuggestionAdjustedToToMatchCase } from '../suggestions.js';
|
|
|
11
11
|
import { catchPromiseError, toError } from '../util/errors.js';
|
|
12
12
|
import { AutoCache } from '../util/simpleCache.js';
|
|
13
13
|
import { uriToFilePath } from '../util/Uri.js';
|
|
14
|
+
import { toFilePathOrHref } from '../util/url.js';
|
|
14
15
|
import { defaultMaxDuplicateProblems, defaultMaxNumberOfProblems } from './defaultConstants.js';
|
|
15
16
|
import { determineTextDocumentSettings } from './determineTextDocumentSettings.js';
|
|
16
17
|
import { textValidatorFactory } from './lineValidatorFactory.js';
|
|
@@ -237,6 +238,36 @@ export class DocumentValidator {
|
|
|
237
238
|
updateTextDocument(this._document, [{ text }]);
|
|
238
239
|
await this._updatePrep();
|
|
239
240
|
}
|
|
241
|
+
/**
|
|
242
|
+
* Get the calculated ranges of text that should be included in the spell checking.
|
|
243
|
+
* @returns MatchRanges of text to include.
|
|
244
|
+
*/
|
|
245
|
+
getCheckedTextRanges() {
|
|
246
|
+
assert(this._preparations, ERROR_NOT_PREPARED);
|
|
247
|
+
return this._preparations.includeRanges;
|
|
248
|
+
}
|
|
249
|
+
traceWord(word) {
|
|
250
|
+
assert(this._preparations, ERROR_NOT_PREPARED);
|
|
251
|
+
const dictCollection = this._preparations.dictionary;
|
|
252
|
+
const config = this._preparations.config;
|
|
253
|
+
const opts = {
|
|
254
|
+
ignoreCase: true,
|
|
255
|
+
allowCompoundWords: config.allowCompoundWords || false,
|
|
256
|
+
};
|
|
257
|
+
const trace = dictCollection.dictionaries
|
|
258
|
+
.map((dict) => ({ dict, findResult: dict.find(word, opts) }))
|
|
259
|
+
.map(({ dict, findResult }) => ({
|
|
260
|
+
word,
|
|
261
|
+
found: !!findResult?.found,
|
|
262
|
+
foundWord: findResult?.found || undefined,
|
|
263
|
+
forbidden: findResult?.forbidden || false,
|
|
264
|
+
noSuggest: findResult?.noSuggest || false,
|
|
265
|
+
dictName: dict.name,
|
|
266
|
+
dictSource: toFilePathOrHref(dict.source),
|
|
267
|
+
errors: normalizeErrors(dict.getErrors?.()),
|
|
268
|
+
}));
|
|
269
|
+
return trace;
|
|
270
|
+
}
|
|
240
271
|
defaultParser() {
|
|
241
272
|
return pipeSync(this.document.getLines(), opMap((line) => {
|
|
242
273
|
const { text, offset } = line;
|
|
@@ -378,4 +409,7 @@ function recordPerfTime(timings, name) {
|
|
|
378
409
|
function timePromise(timings, name, p) {
|
|
379
410
|
return p.finally(recordPerfTime(timings, name));
|
|
380
411
|
}
|
|
412
|
+
function normalizeErrors(errors) {
|
|
413
|
+
return errors?.length ? errors : undefined;
|
|
414
|
+
}
|
|
381
415
|
//# sourceMappingURL=docValidator.js.map
|
package/dist/esm/trace.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { fileURLToPath } from 'node:url';
|
|
2
1
|
import { genSequence } from 'gensequence';
|
|
3
2
|
import { toInternalSettings } from './Settings/CSpellSettingsServer.js';
|
|
4
3
|
import { finalizeSettings, mergeSettings } from './Settings/index.js';
|
|
5
4
|
import { calcSettingsForLanguageId } from './Settings/LanguageSettings.js';
|
|
6
5
|
import { getDictionaryInternal, refreshDictionaryCache } from './SpellingDictionary/index.js';
|
|
6
|
+
import { toFilePathOrHref } from './util/url.js';
|
|
7
7
|
import * as util from './util/util.js';
|
|
8
8
|
export async function traceWords(words, settings, options) {
|
|
9
9
|
const results = await util.asyncIterableToArray(traceWordsAsync(words, settings, options));
|
|
@@ -64,9 +64,6 @@ export async function* traceWordsAsync(words, settings, options) {
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
function dictSourceToFilename(source) {
|
|
67
|
-
|
|
68
|
-
return fileURLToPath(source);
|
|
69
|
-
}
|
|
70
|
-
return source;
|
|
67
|
+
return toFilePathOrHref(source);
|
|
71
68
|
}
|
|
72
69
|
//# sourceMappingURL=trace.js.map
|
|
@@ -46,5 +46,20 @@ export declare class AutoResolveWeakCache<K extends object, V> implements IWeakM
|
|
|
46
46
|
stats(): AutoResolveCacheStats;
|
|
47
47
|
}
|
|
48
48
|
export declare function createAutoResolveWeakCache<K extends object, V>(): AutoResolveWeakCache<K, V>;
|
|
49
|
+
export declare class AutoResolveWeakWeakCache<K extends object, V extends object> implements IWeakMap<K, V> {
|
|
50
|
+
private _map;
|
|
51
|
+
private _stats;
|
|
52
|
+
get(k: K): V | undefined;
|
|
53
|
+
get(k: K, resolve: (k: K) => V): V;
|
|
54
|
+
get(k: K, resolve?: (k: K) => V): V | undefined;
|
|
55
|
+
get map(): WeakMap<K, WeakRef<V>>;
|
|
56
|
+
has(k: K): boolean;
|
|
57
|
+
set(k: K, v: V): this;
|
|
58
|
+
clear(): void;
|
|
59
|
+
delete(k: K): boolean;
|
|
60
|
+
dispose(): void;
|
|
61
|
+
stats(): AutoResolveCacheStats;
|
|
62
|
+
}
|
|
63
|
+
export declare function createAutoResolveWeakWeakCache<K extends object, V extends object>(): AutoResolveWeakWeakCache<K, V>;
|
|
49
64
|
export {};
|
|
50
65
|
//# sourceMappingURL=AutoResolve.d.ts.map
|
|
@@ -116,4 +116,57 @@ export class AutoResolveWeakCache {
|
|
|
116
116
|
export function createAutoResolveWeakCache() {
|
|
117
117
|
return new AutoResolveWeakCache();
|
|
118
118
|
}
|
|
119
|
+
export class AutoResolveWeakWeakCache {
|
|
120
|
+
_map = new WeakMap();
|
|
121
|
+
_stats = new CacheStatsTracker();
|
|
122
|
+
get(k, resolve) {
|
|
123
|
+
const map = this._map;
|
|
124
|
+
const found = map.get(k);
|
|
125
|
+
const foundValue = found?.deref();
|
|
126
|
+
if (found !== undefined && foundValue) {
|
|
127
|
+
++this._stats.hits;
|
|
128
|
+
return foundValue;
|
|
129
|
+
}
|
|
130
|
+
++this._stats.misses;
|
|
131
|
+
if (!resolve) {
|
|
132
|
+
if (found) {
|
|
133
|
+
map.delete(k);
|
|
134
|
+
}
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
++this._stats.resolved;
|
|
138
|
+
const value = resolve(k);
|
|
139
|
+
map.set(k, new WeakRef(value));
|
|
140
|
+
return value;
|
|
141
|
+
}
|
|
142
|
+
get map() {
|
|
143
|
+
return this._map;
|
|
144
|
+
}
|
|
145
|
+
has(k) {
|
|
146
|
+
return !!this._map.get(k)?.deref();
|
|
147
|
+
}
|
|
148
|
+
set(k, v) {
|
|
149
|
+
++this._stats.sets;
|
|
150
|
+
this._map.set(k, new WeakRef(v));
|
|
151
|
+
return this;
|
|
152
|
+
}
|
|
153
|
+
clear() {
|
|
154
|
+
this._stats.clear();
|
|
155
|
+
this._map = new WeakMap();
|
|
156
|
+
}
|
|
157
|
+
delete(k) {
|
|
158
|
+
++this._stats.deletes;
|
|
159
|
+
return this._map.delete(k);
|
|
160
|
+
}
|
|
161
|
+
dispose() {
|
|
162
|
+
++this._stats.disposals;
|
|
163
|
+
this.clear();
|
|
164
|
+
}
|
|
165
|
+
stats() {
|
|
166
|
+
return this._stats.stats();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
export function createAutoResolveWeakWeakCache() {
|
|
170
|
+
return new AutoResolveWeakWeakCache();
|
|
171
|
+
}
|
|
119
172
|
//# sourceMappingURL=AutoResolve.js.map
|
|
@@ -103,6 +103,13 @@ export class SimpleCache {
|
|
|
103
103
|
set(key, value) {
|
|
104
104
|
this._set(key, { v: value });
|
|
105
105
|
}
|
|
106
|
+
delete(key) {
|
|
107
|
+
let deleted = false;
|
|
108
|
+
for (const c of this.caches()) {
|
|
109
|
+
deleted = c.delete(key) || deleted;
|
|
110
|
+
}
|
|
111
|
+
return deleted;
|
|
112
|
+
}
|
|
106
113
|
_set(key, entry) {
|
|
107
114
|
if (this.L0.has(key)) {
|
|
108
115
|
this.L0.set(key, entry);
|
|
@@ -117,9 +124,11 @@ export class SimpleCache {
|
|
|
117
124
|
return [this.L0, this.L1, this.L2];
|
|
118
125
|
}
|
|
119
126
|
rotate() {
|
|
127
|
+
const L2 = this.L2;
|
|
120
128
|
this.L2 = this.L1;
|
|
121
129
|
this.L1 = this.L0;
|
|
122
|
-
this.L0 =
|
|
130
|
+
this.L0 = L2;
|
|
131
|
+
this.L0.clear();
|
|
123
132
|
}
|
|
124
133
|
}
|
|
125
134
|
export class AutoCache extends SimpleCache {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cspell-lib",
|
|
3
|
-
"version": "8.2.
|
|
3
|
+
"version": "8.2.4",
|
|
4
4
|
"description": "A library of useful functions used across various cspell tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -57,21 +57,21 @@
|
|
|
57
57
|
},
|
|
58
58
|
"homepage": "https://github.com/streetsidesoftware/cspell#readme",
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@cspell/cspell-bundled-dicts": "8.2.
|
|
61
|
-
"@cspell/cspell-pipe": "8.2.
|
|
62
|
-
"@cspell/cspell-resolver": "8.2.
|
|
63
|
-
"@cspell/cspell-types": "8.2.
|
|
64
|
-
"@cspell/dynamic-import": "8.2.
|
|
65
|
-
"@cspell/strong-weak-map": "8.2.
|
|
60
|
+
"@cspell/cspell-bundled-dicts": "8.2.4",
|
|
61
|
+
"@cspell/cspell-pipe": "8.2.4",
|
|
62
|
+
"@cspell/cspell-resolver": "8.2.4",
|
|
63
|
+
"@cspell/cspell-types": "8.2.4",
|
|
64
|
+
"@cspell/dynamic-import": "8.2.4",
|
|
65
|
+
"@cspell/strong-weak-map": "8.2.4",
|
|
66
66
|
"clear-module": "^4.1.2",
|
|
67
67
|
"comment-json": "^4.2.3",
|
|
68
68
|
"configstore": "^6.0.0",
|
|
69
|
-
"cspell-config-lib": "8.2.
|
|
70
|
-
"cspell-dictionary": "8.2.
|
|
71
|
-
"cspell-glob": "8.2.
|
|
72
|
-
"cspell-grammar": "8.2.
|
|
73
|
-
"cspell-io": "8.2.
|
|
74
|
-
"cspell-trie-lib": "8.2.
|
|
69
|
+
"cspell-config-lib": "8.2.4",
|
|
70
|
+
"cspell-dictionary": "8.2.4",
|
|
71
|
+
"cspell-glob": "8.2.4",
|
|
72
|
+
"cspell-grammar": "8.2.4",
|
|
73
|
+
"cspell-io": "8.2.4",
|
|
74
|
+
"cspell-trie-lib": "8.2.4",
|
|
75
75
|
"fast-equals": "^5.0.1",
|
|
76
76
|
"gensequence": "^6.0.0",
|
|
77
77
|
"import-fresh": "^3.3.0",
|
|
@@ -90,10 +90,10 @@
|
|
|
90
90
|
"@cspell/dict-fr-fr": "^2.2.2",
|
|
91
91
|
"@cspell/dict-html": "^4.0.5",
|
|
92
92
|
"@cspell/dict-nl-nl": "^2.3.0",
|
|
93
|
-
"@cspell/dict-python": "^4.1.
|
|
93
|
+
"@cspell/dict-python": "^4.1.11",
|
|
94
94
|
"@types/configstore": "^6.0.2",
|
|
95
95
|
"cspell-dict-nl-nl": "^1.1.2",
|
|
96
96
|
"lorem-ipsum": "^2.0.8"
|
|
97
97
|
},
|
|
98
|
-
"gitHead": "
|
|
98
|
+
"gitHead": "d3c5ff685b3aa2bf984f557d81380f2c994547e0"
|
|
99
99
|
}
|