cspell-lib 5.19.2 → 5.19.5

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.
Files changed (38) hide show
  1. package/dist/Models/PatternRegExp.d.ts +5 -0
  2. package/dist/Models/PatternRegExp.js +13 -0
  3. package/dist/Models/TextDocument.d.ts +9 -0
  4. package/dist/Models/TextDocument.js +36 -3
  5. package/dist/Settings/CSpellSettingsServer.d.ts +1 -1
  6. package/dist/Settings/CSpellSettingsServer.js +10 -10
  7. package/dist/Settings/DefaultSettings.d.ts +3 -1
  8. package/dist/Settings/DefaultSettings.js +44 -20
  9. package/dist/Settings/DictionarySettings.d.ts +5 -3
  10. package/dist/Settings/DictionarySettings.js +23 -19
  11. package/dist/Settings/LanguageSettings.d.ts +2 -2
  12. package/dist/Settings/LanguageSettings.js +37 -27
  13. package/dist/Settings/index.d.ts +1 -1
  14. package/dist/Settings/index.js +2 -1
  15. package/dist/SpellingDictionary/Dictionaries.js +2 -2
  16. package/dist/SpellingDictionary/DictionaryLoader.d.ts +2 -2
  17. package/dist/SpellingDictionary/DictionaryLoader.js +34 -30
  18. package/dist/SpellingDictionary/SpellingDictionaryCollection.js +1 -1
  19. package/dist/SpellingDictionary/SpellingDictionaryFromTrie.js +1 -1
  20. package/dist/index.d.ts +1 -1
  21. package/dist/index.js +2 -1
  22. package/dist/suggestions.js +4 -1
  23. package/dist/textValidation/determineTextDocumentSettings.js +3 -3
  24. package/dist/textValidation/docValidator.d.ts +5 -0
  25. package/dist/textValidation/docValidator.js +61 -16
  26. package/dist/textValidation/validator.js +5 -2
  27. package/dist/trace.js +2 -1
  28. package/dist/util/Memorizer.d.ts +8 -0
  29. package/dist/util/Memorizer.js +59 -1
  30. package/dist/util/debugPerf.d.ts +9 -0
  31. package/dist/util/debugPerf.js +22 -0
  32. package/dist/util/simpleCache.d.ts +4 -2
  33. package/dist/util/simpleCache.js +18 -15
  34. package/dist/util/timer.d.ts +11 -0
  35. package/dist/util/timer.js +32 -3
  36. package/dist/util/util.d.ts +7 -0
  37. package/dist/util/util.js +18 -1
  38. package/package.json +11 -11
@@ -59,49 +59,50 @@ function __log(msg) {
59
59
  debugMode && debugLog.push(msg);
60
60
  }
61
61
  const dictionaryCache = new Map();
62
- function loadDictionary(uri, options) {
63
- const key = calcKey(uri, options);
62
+ const dictionaryCacheByDef = new Map();
63
+ function getCacheEntry(def) {
64
+ const defEntry = dictionaryCacheByDef.get(def);
65
+ if (defEntry) {
66
+ return defEntry;
67
+ }
68
+ const key = calcKey(def);
64
69
  const entry = dictionaryCache.get(key);
70
+ if (entry) {
71
+ // replace old entry so it can be released.
72
+ entry.options = def;
73
+ }
74
+ return { key, entry };
75
+ }
76
+ function setCacheEntry(key, entry, def) {
77
+ dictionaryCache.set(key, entry);
78
+ dictionaryCacheByDef.set(def, { key, entry });
79
+ }
80
+ function loadDictionary(def) {
81
+ const { key, entry } = getCacheEntry(def);
65
82
  if (entry) {
66
83
  return entry.pending.then(([dictionary]) => dictionary);
67
84
  }
68
- const loadedEntry = loadEntry(uri, options);
69
- dictionaryCache.set(key, loadedEntry);
85
+ const loadedEntry = loadEntry(def.path, def);
86
+ setCacheEntry(key, loadedEntry, def);
70
87
  return loadedEntry.pending.then(([dictionary]) => dictionary);
71
88
  }
72
89
  exports.loadDictionary = loadDictionary;
73
- function loadDictionarySync(uri, options) {
74
- const key = calcKey(uri, options);
75
- const entry = dictionaryCache.get(key);
90
+ function loadDictionarySync(def) {
91
+ const { key, entry } = getCacheEntry(def);
76
92
  if ((entry === null || entry === void 0 ? void 0 : entry.dictionary) && entry.loadingState === LoadingState.Loaded) {
77
- // if (entry.options.name === 'temp') {
78
- // __log(
79
- // `Cache Found ${entry.options.name}; ts: ${entry.sig.toFixed(2)}; file: ${path.relative(
80
- // process.cwd(),
81
- // entry.uri
82
- // )}`
83
- // );
84
- // }
85
93
  return entry.dictionary;
86
94
  }
87
- // if (options.name === 'temp') {
88
- // __log(
89
- // `Cache Miss ${options.name}; ts: ${entry?.sig.toFixed(2) || Date.now()}; file: ${path.relative(
90
- // process.cwd(),
91
- // uri
92
- // )}`
93
- // );
94
- // }
95
- const loadedEntry = loadEntrySync(uri, options);
96
- dictionaryCache.set(key, loadedEntry);
95
+ const loadedEntry = loadEntrySync(def.path, def);
96
+ setCacheEntry(key, loadedEntry, def);
97
97
  return loadedEntry.dictionary;
98
98
  }
99
99
  exports.loadDictionarySync = loadDictionarySync;
100
100
  const importantOptionKeys = ['name', 'noSuggest', 'useCompounds', 'type'];
101
- function calcKey(uri, options) {
102
- const loaderType = determineType(uri, options);
103
- const optValues = importantOptionKeys.map((k) => { var _a; return ((_a = options[k]) === null || _a === void 0 ? void 0 : _a.toString()) || ''; });
104
- const parts = [uri, loaderType].concat(optValues);
101
+ function calcKey(def) {
102
+ const path = def.path;
103
+ const loaderType = determineType(path, def);
104
+ const optValues = importantOptionKeys.map((k) => { var _a; return ((_a = def[k]) === null || _a === void 0 ? void 0 : _a.toString()) || ''; });
105
+ const parts = [path, loaderType].concat(optValues);
105
106
  return parts.join('|');
106
107
  }
107
108
  /**
@@ -136,7 +137,10 @@ async function refreshEntry(entry, maxAge, now) {
136
137
  // }
137
138
  if (sigMatches && hasChanged) {
138
139
  entry.loadingState = LoadingState.Loading;
139
- dictionaryCache.set(calcKey(entry.uri, entry.options), loadEntry(entry.uri, entry.options));
140
+ const key = calcKey(entry.options);
141
+ const newEntry = loadEntry(entry.uri, entry.options);
142
+ dictionaryCache.set(key, newEntry);
143
+ dictionaryCacheByDef.set(entry.options, { key, entry: newEntry });
140
144
  }
141
145
  }
142
146
  }
@@ -54,7 +54,7 @@ class SpellingDictionaryCollection {
54
54
  return this._suggest(word, suggestOptions);
55
55
  }
56
56
  _suggest(word, suggestOptions) {
57
- const { numSuggestions = (0, Settings_1.getDefaultSettings)().numSuggestions || SpellingDictionaryMethods_1.defaultNumSuggestions, numChanges, ignoreCase, includeTies, timeout, } = suggestOptions;
57
+ const { numSuggestions = (0, Settings_1.getDefaultSettings)(false).numSuggestions || SpellingDictionaryMethods_1.defaultNumSuggestions, numChanges, ignoreCase, includeTies, timeout, } = suggestOptions;
58
58
  const prefixNoCase = cspell_trie_lib_1.CASE_INSENSITIVE_PREFIX;
59
59
  const filter = (word, _cost) => {
60
60
  return ((ignoreCase || word[0] !== prefixNoCase) &&
@@ -97,7 +97,7 @@ class SpellingDictionaryFromTrie {
97
97
  return this._suggest(word, suggestOptions);
98
98
  }
99
99
  _suggest(word, suggestOptions) {
100
- const { numSuggestions = (0, Settings_1.getDefaultSettings)().numSuggestions || SpellingDictionaryMethods_1.defaultNumSuggestions, numChanges, includeTies, ignoreCase, timeout, } = suggestOptions;
100
+ const { numSuggestions = (0, Settings_1.getDefaultSettings)(false).numSuggestions || SpellingDictionaryMethods_1.defaultNumSuggestions, numChanges, includeTies, ignoreCase, timeout, } = suggestOptions;
101
101
  function filter(_word) {
102
102
  return true;
103
103
  }
package/dist/index.d.ts CHANGED
@@ -7,7 +7,7 @@ export * from '@cspell/cspell-types';
7
7
  export * from 'cspell-io';
8
8
  export { ExcludeFilesGlobMap, ExclusionFunction } from './exclusionHelper';
9
9
  export { getLanguagesForExt } from './LanguageIds';
10
- export { createTextDocument } from './Models/TextDocument';
10
+ export { createTextDocument, updateTextDocument } from './Models/TextDocument';
11
11
  export type { CreateTextDocumentParams, TextDocument, TextDocumentLine } from './Models/TextDocument';
12
12
  export * from './Settings';
13
13
  export { defaultFileName as defaultSettingsFilename } from './Settings';
package/dist/index.js CHANGED
@@ -26,7 +26,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
26
26
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.getDictionary = exports.clearCachedFiles = exports.ExclusionHelper = exports.Link = exports.Text = exports.validateText = exports.IncludeExcludeFlag = exports.checkText = exports.resolveFile = exports.setLogger = exports.getLogger = exports.traceWordsAsync = exports.traceWords = exports.DocumentValidator = exports.suggestionsForWords = exports.suggestionsForWord = exports.SuggestionError = exports.SpellingDictionaryLoadError = exports.SpellingDictionaryCollection = exports.refreshDictionaryCache = exports.isSpellingDictionaryLoadError = exports.createSpellingDictionary = exports.CompoundWordsMethod = exports.spellCheckFile = exports.spellCheckDocument = exports.isBinaryFile = exports.fileToDocument = exports.determineFinalDocumentSettings = exports.constructSettingsForText = exports.combineTextAndLanguageSettings = exports.defaultSettingsFilename = exports.createTextDocument = exports.getLanguagesForExt = void 0;
29
+ exports.getDictionary = exports.clearCachedFiles = exports.ExclusionHelper = exports.Link = exports.Text = exports.validateText = exports.IncludeExcludeFlag = exports.checkText = exports.resolveFile = exports.setLogger = exports.getLogger = exports.traceWordsAsync = exports.traceWords = exports.DocumentValidator = exports.suggestionsForWords = exports.suggestionsForWord = exports.SuggestionError = exports.SpellingDictionaryLoadError = exports.SpellingDictionaryCollection = exports.refreshDictionaryCache = exports.isSpellingDictionaryLoadError = exports.createSpellingDictionary = exports.CompoundWordsMethod = exports.spellCheckFile = exports.spellCheckDocument = exports.isBinaryFile = exports.fileToDocument = exports.determineFinalDocumentSettings = exports.constructSettingsForText = exports.combineTextAndLanguageSettings = exports.defaultSettingsFilename = exports.updateTextDocument = exports.createTextDocument = exports.getLanguagesForExt = void 0;
30
30
  const ExclusionHelper = __importStar(require("./exclusionHelper"));
31
31
  exports.ExclusionHelper = ExclusionHelper;
32
32
  const Settings_1 = require("./Settings");
@@ -42,6 +42,7 @@ var LanguageIds_1 = require("./LanguageIds");
42
42
  Object.defineProperty(exports, "getLanguagesForExt", { enumerable: true, get: function () { return LanguageIds_1.getLanguagesForExt; } });
43
43
  var TextDocument_1 = require("./Models/TextDocument");
44
44
  Object.defineProperty(exports, "createTextDocument", { enumerable: true, get: function () { return TextDocument_1.createTextDocument; } });
45
+ Object.defineProperty(exports, "updateTextDocument", { enumerable: true, get: function () { return TextDocument_1.updateTextDocument; } });
45
46
  __exportStar(require("./Settings"), exports);
46
47
  var Settings_2 = require("./Settings");
47
48
  Object.defineProperty(exports, "defaultSettingsFilename", { enumerable: true, get: function () { return Settings_2.defaultFileName; } });
@@ -35,6 +35,7 @@ async function* suggestionsForWords(words, options, settings = {}) {
35
35
  }
36
36
  exports.suggestionsForWords = suggestionsForWords;
37
37
  async function suggestionsForWord(word, options, settings = {}) {
38
+ var _a;
38
39
  const { languageId, locale: language, strict = true, numChanges = 4, numSuggestions = 8, includeTies = true, includeDefaultConfig = true, dictionaries, } = options || {};
39
40
  const ignoreCase = !strict;
40
41
  async function determineDictionaries(config) {
@@ -56,7 +57,9 @@ async function suggestionsForWord(word, options, settings = {}) {
56
57
  };
57
58
  }
58
59
  await (0, SpellingDictionary_1.refreshDictionaryCache)();
59
- const config = includeDefaultConfig ? (0, Settings_1.mergeSettings)((0, Settings_1.getDefaultSettings)(), (0, Settings_1.getGlobalSettings)(), settings) : settings;
60
+ const config = includeDefaultConfig
61
+ ? (0, Settings_1.mergeSettings)((0, Settings_1.getDefaultSettings)((_a = settings.loadDefaultConfiguration) !== null && _a !== void 0 ? _a : true), (0, Settings_1.getGlobalSettings)(), settings)
62
+ : settings;
60
63
  const { dictionaryCollection, allDictionaryCollection } = await determineDictionaries(config);
61
64
  const opts = { ignoreCase, numChanges, numSuggestions, includeTies };
62
65
  const suggestionsByDictionary = dictionaryCollection.dictionaries.map((dict) => dict.suggest(word, opts).map((r) => ({ ...r, dictName: dict.name })));
@@ -41,11 +41,11 @@ const TextDocumentSettings_1 = require("../Settings/TextDocumentSettings");
41
41
  * @param settings - The near final settings. Should already be the combination of all configuration files.
42
42
  */
43
43
  function determineTextDocumentSettings(doc, settings) {
44
- var _a;
44
+ var _a, _b;
45
45
  const filename = doc.uri.fsPath;
46
- const settingsWithDefaults = (0, Settings_1.mergeSettings)((0, Settings_1.getDefaultSettings)(), (0, Settings_1.getGlobalSettings)(), settings);
46
+ const settingsWithDefaults = (0, Settings_1.mergeSettings)((0, Settings_1.getDefaultSettings)((_a = settings.loadDefaultConfiguration) !== null && _a !== void 0 ? _a : true), (0, Settings_1.getGlobalSettings)(), settings);
47
47
  const fileSettings = (0, Settings_1.calcOverrideSettings)(settingsWithDefaults, filename);
48
- const languageIds = ((_a = fileSettings === null || fileSettings === void 0 ? void 0 : fileSettings.languageId) === null || _a === void 0 ? void 0 : _a.length)
48
+ const languageIds = ((_b = fileSettings === null || fileSettings === void 0 ? void 0 : fileSettings.languageId) === null || _b === void 0 ? void 0 : _b.length)
49
49
  ? fileSettings.languageId
50
50
  : doc.languageId
51
51
  ? doc.languageId
@@ -26,6 +26,7 @@ export declare class DocumentValidator {
26
26
  private _prepared;
27
27
  private _preparations;
28
28
  private _preparationTime;
29
+ private _suggestions;
29
30
  /**
30
31
  * @param doc - Document to validate
31
32
  * @param config - configuration to use (not finalized).
@@ -35,15 +36,19 @@ export declare class DocumentValidator {
35
36
  prepareSync(): void;
36
37
  prepare(): Promise<void>;
37
38
  private _prepareAsync;
39
+ private _updatePrep;
38
40
  /**
39
41
  * The amount of time in ms to prepare for validation.
40
42
  */
41
43
  get prepTime(): number;
42
44
  checkText(range: SimpleRange, _text: string, _scope: string[]): ValidationIssue[];
43
45
  get document(): TextDocument;
46
+ updateDocumentText(text: string): void;
44
47
  private addPossibleError;
45
48
  private catchError;
46
49
  private errorCatcherWrapper;
50
+ private suggest;
51
+ private genSuggestions;
47
52
  }
48
53
  export declare type Offset = number;
49
54
  export declare type SimpleRange = readonly [Offset, Offset];
@@ -6,10 +6,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.DocumentValidator = void 0;
7
7
  const cspell_pipe_1 = require("@cspell/cspell-pipe");
8
8
  const assert_1 = __importDefault(require("assert"));
9
+ const TextDocument_1 = require("../Models/TextDocument");
9
10
  const Settings_1 = require("../Settings");
10
11
  const configLoader_1 = require("../Settings/configLoader");
11
12
  const SpellingDictionary_1 = require("../SpellingDictionary");
12
13
  const errors_1 = require("../util/errors");
14
+ const Memorizer_1 = require("../util/Memorizer");
15
+ const simpleCache_1 = require("../util/simpleCache");
13
16
  const timer_1 = require("../util/timer");
14
17
  const util_1 = require("../util/util");
15
18
  const determineTextDocumentSettings_1 = require("./determineTextDocumentSettings");
@@ -26,6 +29,7 @@ class DocumentValidator {
26
29
  this._ready = false;
27
30
  this.errors = [];
28
31
  this._preparationTime = -1;
32
+ this._suggestions = new simpleCache_1.AutoCache((text) => this.genSuggestions(text), 1000);
29
33
  this._document = doc;
30
34
  // console.error(`DocumentValidator: ${doc.uri}`);
31
35
  }
@@ -50,7 +54,7 @@ class DocumentValidator {
50
54
  ? this.errorCatcherWrapper(() => searchForDocumentConfigSync(this._document, settings, settings))
51
55
  : undefined;
52
56
  this.addPossibleError((_a = localConfig === null || localConfig === void 0 ? void 0 : localConfig.__importRef) === null || _a === void 0 ? void 0 : _a.error);
53
- const config = localConfig ? (0, Settings_1.mergeSettings)(settings, localConfig) : settings;
57
+ const config = (0, Settings_1.mergeSettings)(settings, localConfig);
54
58
  const docSettings = (0, determineTextDocumentSettings_1.determineTextDocumentSettings)(this._document, config);
55
59
  const dict = (0, SpellingDictionary_1.getDictionaryInternalSync)(docSettings);
56
60
  const shouldCheck = (_b = docSettings.enabled) !== null && _b !== void 0 ? _b : true;
@@ -60,6 +64,7 @@ class DocumentValidator {
60
64
  const segmenter = (0, textValidator_1.mapLineSegmentAgainstRangesFactory)(includeRanges);
61
65
  const lineValidator = (0, textValidator_1.lineValidatorFactory)(dict, validateOptions);
62
66
  this._preparations = {
67
+ config,
63
68
  dictionary: dict,
64
69
  docSettings,
65
70
  shouldCheck,
@@ -70,6 +75,7 @@ class DocumentValidator {
70
75
  };
71
76
  this._ready = true;
72
77
  this._preparationTime = timer.elapsed();
78
+ // console.error(`prepareSync ${this._preparationTime.toFixed(2)}ms`);
73
79
  }
74
80
  async prepare() {
75
81
  if (this._ready)
@@ -90,9 +96,9 @@ class DocumentValidator {
90
96
  : useSearchForConfig
91
97
  ? this.catchError(searchForDocumentConfig(this._document, settings, settings))
92
98
  : undefined;
93
- const localConfig = await pLocalConfig;
99
+ const localConfig = (await pLocalConfig) || {};
94
100
  this.addPossibleError((_a = localConfig === null || localConfig === void 0 ? void 0 : localConfig.__importRef) === null || _a === void 0 ? void 0 : _a.error);
95
- const config = localConfig ? (0, Settings_1.mergeSettings)(settings, localConfig) : settings;
101
+ const config = (0, Settings_1.mergeSettings)(settings, localConfig);
96
102
  const docSettings = (0, determineTextDocumentSettings_1.determineTextDocumentSettings)(this._document, config);
97
103
  const dict = await (0, SpellingDictionary_1.getDictionaryInternal)(docSettings);
98
104
  const shouldCheck = (_b = docSettings.enabled) !== null && _b !== void 0 ? _b : true;
@@ -102,6 +108,7 @@ class DocumentValidator {
102
108
  const segmenter = (0, textValidator_1.mapLineSegmentAgainstRangesFactory)(includeRanges);
103
109
  const lineValidator = (0, textValidator_1.lineValidatorFactory)(dict, validateOptions);
104
110
  this._preparations = {
111
+ config,
105
112
  dictionary: dict,
106
113
  docSettings,
107
114
  shouldCheck,
@@ -113,6 +120,31 @@ class DocumentValidator {
113
120
  this._ready = true;
114
121
  this._preparationTime = timer.elapsed();
115
122
  }
123
+ _updatePrep() {
124
+ var _a;
125
+ (0, assert_1.default)(this._preparations);
126
+ const timer = (0, timer_1.createTimer)();
127
+ const { config } = this._preparations;
128
+ const docSettings = (0, determineTextDocumentSettings_1.determineTextDocumentSettings)(this._document, config);
129
+ const dict = (0, SpellingDictionary_1.getDictionaryInternalSync)(docSettings);
130
+ const shouldCheck = (_a = docSettings.enabled) !== null && _a !== void 0 ? _a : true;
131
+ const finalSettings = (0, Settings_1.finalizeSettings)(docSettings);
132
+ const validateOptions = (0, validator_1.settingsToValidateOptions)(finalSettings);
133
+ const includeRanges = (0, textValidator_1.calcTextInclusionRanges)(this._document.text, validateOptions);
134
+ const segmenter = (0, textValidator_1.mapLineSegmentAgainstRangesFactory)(includeRanges);
135
+ const lineValidator = (0, textValidator_1.lineValidatorFactory)(dict, validateOptions);
136
+ this._preparations = {
137
+ config,
138
+ dictionary: dict,
139
+ docSettings,
140
+ shouldCheck,
141
+ validateOptions,
142
+ includeRanges,
143
+ segmenter,
144
+ lineValidator,
145
+ };
146
+ this._preparationTime = timer.elapsed();
147
+ }
116
148
  /**
117
149
  * The amount of time in ms to prepare for validation.
118
150
  */
@@ -120,7 +152,6 @@ class DocumentValidator {
120
152
  return this._preparationTime;
121
153
  }
122
154
  checkText(range, _text, _scope) {
123
- var _a;
124
155
  (0, assert_1.default)(this._ready);
125
156
  (0, assert_1.default)(this._preparations);
126
157
  const { segmenter, lineValidator } = this._preparations;
@@ -143,25 +174,21 @@ class DocumentValidator {
143
174
  if (!this.options.generateSuggestions) {
144
175
  return issues;
145
176
  }
146
- const settings = this._preparations.docSettings;
147
- const dict = this._preparations.dictionary;
148
- const sugOptions = (0, util_1.clean)({
149
- compoundMethod: 0,
150
- numSuggestions: this.options.numSuggestions,
151
- includeTies: false,
152
- ignoreCase: !((_a = settings.caseSensitive) !== null && _a !== void 0 ? _a : false),
153
- timeout: settings.suggestionsTimeout,
154
- numChanges: settings.suggestionNumChanges,
155
- });
156
177
  const withSugs = issues.map((t) => {
157
- const suggestions = dict.suggest(t.text, sugOptions).map((r) => r.word);
158
- return { ...t, suggestions };
178
+ // lazy suggestion calculation.
179
+ const text = t.text;
180
+ const suggestions = (0, Memorizer_1.callOnce)(() => this.suggest(text));
181
+ return Object.defineProperty({ ...t }, 'suggestions', { enumerable: true, get: suggestions });
159
182
  });
160
183
  return withSugs;
161
184
  }
162
185
  get document() {
163
186
  return this._document;
164
187
  }
188
+ updateDocumentText(text) {
189
+ (0, TextDocument_1.updateTextDocument)(this._document, [{ text }]);
190
+ this._updatePrep();
191
+ }
165
192
  addPossibleError(error) {
166
193
  if (!error)
167
194
  return;
@@ -182,6 +209,24 @@ class DocumentValidator {
182
209
  }
183
210
  return undefined;
184
211
  }
212
+ suggest(text) {
213
+ return this._suggestions.get(text);
214
+ }
215
+ genSuggestions(text) {
216
+ var _a;
217
+ (0, assert_1.default)(this._preparations);
218
+ const settings = this._preparations.docSettings;
219
+ const dict = this._preparations.dictionary;
220
+ const sugOptions = (0, util_1.clean)({
221
+ compoundMethod: 0,
222
+ numSuggestions: this.options.numSuggestions,
223
+ includeTies: false,
224
+ ignoreCase: !((_a = settings.caseSensitive) !== null && _a !== void 0 ? _a : false),
225
+ timeout: settings.suggestionsTimeout,
226
+ numChanges: settings.suggestionNumChanges,
227
+ });
228
+ return dict.suggest(text, sugOptions).map((r) => r.word);
229
+ }
185
230
  }
186
231
  exports.DocumentValidator = DocumentValidator;
187
232
  async function searchForDocumentConfig(document, defaultConfig, pnpSettings) {
@@ -26,6 +26,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.checkText = exports.IncludeExcludeFlag = exports.settingsToValidateOptions = exports.validateText = exports.diagSource = void 0;
27
27
  const Settings = __importStar(require("../Settings"));
28
28
  const SpellingDictionary_1 = require("../SpellingDictionary");
29
+ const Memorizer_1 = require("../util/Memorizer");
29
30
  const util_1 = require("../util/util");
30
31
  const textValidator_1 = require("./textValidator");
31
32
  exports.diagSource = 'cSpell Checker';
@@ -46,8 +47,10 @@ async function validateText(text, settings, options = {}) {
46
47
  numChanges: settings.suggestionNumChanges,
47
48
  });
48
49
  const withSugs = issues.map((t) => {
49
- const suggestions = dict.suggest(t.text, sugOptions).map((r) => r.word);
50
- return { ...t, suggestions };
50
+ const text = t.text;
51
+ // lazy suggestion calculation.
52
+ const suggestions = (0, Memorizer_1.callOnce)(() => dict.suggest(text, sugOptions).map((r) => r.word));
53
+ return Object.defineProperty({ ...t }, 'suggestions', { enumerable: true, get: suggestions });
51
54
  });
52
55
  return withSugs;
53
56
  }
package/dist/trace.js CHANGED
@@ -26,6 +26,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.traceWordsAsync = exports.traceWords = void 0;
27
27
  const gensequence_1 = require("gensequence");
28
28
  const Settings_1 = require("./Settings");
29
+ const CSpellSettingsServer_1 = require("./Settings/CSpellSettingsServer");
29
30
  const LanguageSettings_1 = require("./Settings/LanguageSettings");
30
31
  const SpellingDictionary_1 = require("./SpellingDictionary");
31
32
  const util = __importStar(require("./util/util"));
@@ -50,7 +51,7 @@ async function* traceWordsAsync(words, settings, options) {
50
51
  const dictionaries = (settings.dictionaries || [])
51
52
  .concat((settings.dictionaryDefinitions || []).map((d) => d.name))
52
53
  .filter(util.uniqueFn);
53
- const dictSettings = { ...settings, dictionaries };
54
+ const dictSettings = (0, CSpellSettingsServer_1.toInternalSettings)({ ...settings, dictionaries });
54
55
  const dictBase = await (0, SpellingDictionary_1.getDictionaryInternal)(settings);
55
56
  const dicts = await (0, SpellingDictionary_1.getDictionaryInternal)(dictSettings);
56
57
  const activeDictionaries = dictBase.dictionaries.map((d) => d.name);
@@ -41,10 +41,18 @@ export declare function memorizerKeyBy<F extends (...args: any[]) => any, Args e
41
41
  * @param fn - function to memorize
42
42
  * @returns a new function.
43
43
  */
44
+ export declare function memorizeLastCall<T>(fn: (...p: []) => T): (...p: []) => T;
44
45
  export declare function memorizeLastCall<T, K0>(fn: (...p: [K0]) => T): (...p: [K0]) => T;
45
46
  export declare function memorizeLastCall<T, K0, K1>(fn: (...p: [K0, K1]) => T): (...p: [K0, K1]) => T;
46
47
  export declare function memorizeLastCall<T, K0, K1, K2>(fn: (...p: [K0, K1, K2]) => T): (...p: [K0, K1, K2]) => T;
47
48
  export declare function memorizeLastCall<T, K0, K1, K2, K3>(fn: (...p: [K0, K1, K2, K3]) => T): (...p: [K0, K1, K2, K3]) => T;
48
49
  export declare function memorizeLastCall<T, K>(fn: (...p: [...K[]]) => T): (...p: [...K[]]) => T;
50
+ /**
51
+ * calls a function exactly once and always returns the same value.
52
+ * @param fn - function to call
53
+ * @returns a new function
54
+ */
55
+ export declare function callOnce<T>(fn: () => T): () => T;
56
+ export declare function memorizerAll<K extends any[], T>(fn: (...p: K) => T): (...p: K) => T;
49
57
  export {};
50
58
  //# sourceMappingURL=Memorizer.d.ts.map
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.memorizeLastCall = exports.memorizerKeyBy = exports.memorizer = void 0;
3
+ exports.memorizerAll = exports.callOnce = exports.memorizeLastCall = exports.memorizerKeyBy = exports.memorizer = void 0;
4
4
  const util_1 = require("./util");
5
5
  /* eslint-disable @typescript-eslint/no-explicit-any */
6
6
  const defaultSize = 50000;
@@ -73,4 +73,62 @@ function memorizeLastCall(fn) {
73
73
  };
74
74
  }
75
75
  exports.memorizeLastCall = memorizeLastCall;
76
+ /**
77
+ * calls a function exactly once and always returns the same value.
78
+ * @param fn - function to call
79
+ * @returns a new function
80
+ */
81
+ function callOnce(fn) {
82
+ let last;
83
+ return () => {
84
+ if (last) {
85
+ return last.value;
86
+ }
87
+ last = {
88
+ value: fn(),
89
+ };
90
+ return last.value;
91
+ };
92
+ }
93
+ exports.callOnce = callOnce;
94
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
95
+ function memorizerAll(fn) {
96
+ const r = {};
97
+ function find(p) {
98
+ var _a;
99
+ let n = r;
100
+ for (const k of p) {
101
+ if (!n)
102
+ break;
103
+ n = (_a = n.c) === null || _a === void 0 ? void 0 : _a.get(k);
104
+ }
105
+ return n;
106
+ }
107
+ function set(p, v) {
108
+ var _a;
109
+ let n = r;
110
+ for (const k of p) {
111
+ const c = (_a = n.c) === null || _a === void 0 ? void 0 : _a.get(k);
112
+ if (c) {
113
+ n = c;
114
+ continue;
115
+ }
116
+ const r = {};
117
+ n.c = n.c || new Map();
118
+ n.c.set(k, r);
119
+ n = r;
120
+ }
121
+ n.v = v;
122
+ }
123
+ return (...p) => {
124
+ const f = find(p);
125
+ if (f && 'v' in f) {
126
+ return f.v;
127
+ }
128
+ const v = fn(...p);
129
+ set(p, v);
130
+ return v;
131
+ };
132
+ }
133
+ exports.memorizerAll = memorizerAll;
76
134
  //# sourceMappingURL=Memorizer.js.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Measure and log result.
3
+ * @param fn - function to measure.
4
+ * @param message - message to log
5
+ * @param callback - called when the function has finished.
6
+ * @returns a function
7
+ */
8
+ export declare function perfFn<P extends any[], R>(fn: (...args: P) => R, message: string, callback?: (m: string, elapsedMs: number) => void): (...args: P) => R;
9
+ //# sourceMappingURL=debugPerf.d.ts.map
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.perfFn = void 0;
4
+ const timer_1 = require("./timer");
5
+ /**
6
+ * Measure and log result.
7
+ * @param fn - function to measure.
8
+ * @param message - message to log
9
+ * @param callback - called when the function has finished.
10
+ * @returns a function
11
+ */
12
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
+ function perfFn(fn, message, callback = (message, time) => console.error(`${message}: ${time.toFixed(2)}ms`)) {
14
+ return (...args) => {
15
+ const timer = (0, timer_1.createTimer)();
16
+ const r = fn(...args);
17
+ callback(message, timer.elapsed());
18
+ return r;
19
+ };
20
+ }
21
+ exports.perfFn = perfFn;
22
+ //# sourceMappingURL=debugPerf.js.map
@@ -7,7 +7,8 @@ export declare class SimpleWeakCache<K extends object, T> {
7
7
  constructor(size: number);
8
8
  has(key: K): boolean;
9
9
  get(key: K): T | undefined;
10
- set(key: K, value: T): this | undefined;
10
+ set(key: K, value: T): void;
11
+ private _set;
11
12
  private caches;
12
13
  private rotate;
13
14
  }
@@ -32,7 +33,8 @@ export declare class SimpleCache<K, T> {
32
33
  constructor(size: number);
33
34
  has(key: K): boolean;
34
35
  get(key: K): T | undefined;
35
- set(key: K, value: T): this | undefined;
36
+ set(key: K, value: T): void;
37
+ private _set;
36
38
  private caches;
37
39
  private rotate;
38
40
  }
@@ -18,27 +18,29 @@ class SimpleWeakCache {
18
18
  }
19
19
  get(key) {
20
20
  for (const c of this.caches()) {
21
- if (c.has(key)) {
22
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
23
- const v = c.get(key);
21
+ const entry = c.get(key);
22
+ if (entry) {
24
23
  if (c !== this.L0) {
25
- this.set(key, v);
24
+ this._set(key, entry);
26
25
  }
27
- return v;
26
+ return entry.v;
28
27
  }
29
28
  }
30
29
  return undefined;
31
30
  }
32
31
  set(key, value) {
32
+ this._set(key, { v: value });
33
+ }
34
+ _set(key, entry) {
33
35
  if (this.L0.has(key)) {
34
- this.L0.set(key, value);
36
+ this.L0.set(key, entry);
35
37
  return this;
36
38
  }
37
39
  if (this.sizeL0 >= this.size) {
38
40
  this.rotate();
39
41
  }
40
42
  this.sizeL0 += 1;
41
- this.L0.set(key, value);
43
+ this.L0.set(key, entry);
42
44
  }
43
45
  caches() {
44
46
  return [this.L0, this.L1, this.L2];
@@ -90,32 +92,33 @@ class SimpleCache {
90
92
  }
91
93
  get(key) {
92
94
  for (const c of this.caches()) {
93
- if (c.has(key)) {
94
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
95
- const v = c.get(key);
95
+ const entry = c.get(key);
96
+ if (entry) {
96
97
  if (c !== this.L0) {
97
- this.set(key, v);
98
+ this._set(key, entry);
98
99
  }
99
- return v;
100
+ return entry.v;
100
101
  }
101
102
  }
102
103
  return undefined;
103
104
  }
104
105
  set(key, value) {
106
+ this._set(key, { v: value });
107
+ }
108
+ _set(key, entry) {
105
109
  if (this.L0.has(key)) {
106
- this.L0.set(key, value);
110
+ this.L0.set(key, entry);
107
111
  return this;
108
112
  }
109
113
  if (this.L0.size >= this.size) {
110
114
  this.rotate();
111
115
  }
112
- this.L0.set(key, value);
116
+ this.L0.set(key, entry);
113
117
  }
114
118
  caches() {
115
119
  return [this.L0, this.L1, this.L2];
116
120
  }
117
121
  rotate() {
118
- this.L2.clear();
119
122
  this.L2 = this.L1;
120
123
  this.L1 = this.L0;
121
124
  this.L0 = new Map();
@@ -6,10 +6,21 @@ export interface Timer {
6
6
  * timer was created / started.
7
7
  */
8
8
  elapsed(): number;
9
+ /**
10
+ * Calculate the amount of time in ms since the
11
+ * end of the last lap.
12
+ */
13
+ lap(): number;
9
14
  }
10
15
  export declare function createTimer(hrTimeFn?: HRTimeFn): Timer;
11
16
  export declare type HRTimeFn = (time?: HRTime) => HRTime;
12
17
  export declare type HRTime = [number, number];
13
18
  export declare function toMilliseconds(t: HRTime): number;
14
19
  export declare function polyHrTime(time?: HRTime): HRTime;
20
+ export interface LapRecorder {
21
+ times: [name: string, lapTime: number, totalTime: number][];
22
+ lap(name: string): void;
23
+ report(): string[];
24
+ }
25
+ export declare function createLapRecorder(): LapRecorder;
15
26
  //# sourceMappingURL=timer.d.ts.map