cspell-lib 6.1.2 → 6.1.3

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 (45) hide show
  1. package/dist/LanguageIds.js +1 -2
  2. package/dist/Models/TextDocument.js +3 -3
  3. package/dist/Settings/CSpellSettingsServer.js +45 -10
  4. package/dist/Settings/DictionarySettings.js +1 -1
  5. package/dist/Settings/LanguageSettings.js +1 -2
  6. package/dist/Settings/configLoader.js +15 -19
  7. package/dist/Settings/link.js +5 -6
  8. package/dist/Settings/pnpLoader.js +1 -2
  9. package/dist/SpellingDictionary/DictionaryLoader.js +2 -2
  10. package/dist/SpellingDictionary/SpellingDictionary.d.ts +2 -2
  11. package/dist/SpellingDictionary/SpellingDictionaryCollection.js +1 -1
  12. package/dist/SpellingDictionary/SpellingDictionaryFromTrie.js +3 -4
  13. package/dist/SpellingDictionary/SpellingDictionaryMethods.d.ts +2 -2
  14. package/dist/SpellingDictionary/SpellingDictionaryMethods.js +4 -4
  15. package/dist/SpellingDictionary/createSpellingDictionary.js +1 -1
  16. package/dist/spellCheckFile.js +3 -3
  17. package/dist/suggestions.js +9 -13
  18. package/dist/textValidation/ValidationTypes.d.ts +41 -0
  19. package/dist/textValidation/ValidationTypes.js +3 -0
  20. package/dist/textValidation/determineTextDocumentSettings.js +2 -3
  21. package/dist/textValidation/docValidator.d.ts +11 -7
  22. package/dist/textValidation/docValidator.js +56 -43
  23. package/dist/textValidation/index.d.ts +2 -2
  24. package/dist/textValidation/isWordValid.d.ts +12 -0
  25. package/dist/textValidation/isWordValid.js +19 -0
  26. package/dist/textValidation/lineValidatorFactory.d.ts +5 -0
  27. package/dist/textValidation/lineValidatorFactory.js +145 -0
  28. package/dist/textValidation/parsedText.d.ts +11 -17
  29. package/dist/textValidation/parsedText.js +74 -10
  30. package/dist/textValidation/textValidator.d.ts +5 -42
  31. package/dist/textValidation/textValidator.js +8 -114
  32. package/dist/textValidation/validator.d.ts +5 -1
  33. package/dist/textValidation/validator.js +6 -4
  34. package/dist/trace.js +15 -19
  35. package/dist/util/Memorizer.d.ts +8 -1
  36. package/dist/util/Memorizer.js +10 -6
  37. package/dist/util/PairingHeap.js +1 -2
  38. package/dist/util/TextMap.d.ts +15 -0
  39. package/dist/util/TextMap.js +62 -0
  40. package/dist/util/memorizerWeak.js +2 -4
  41. package/dist/util/search.js +2 -2
  42. package/dist/util/text.js +1 -1
  43. package/dist/util/timer.js +1 -1
  44. package/dist/util/wordSplitter.js +2 -4
  45. package/package.json +13 -13
@@ -1,10 +1,11 @@
1
- import type { CSpellUserSettings } from '@cspell/cspell-types';
2
- import { CSpellSettingsInternal } from '../Models/CSpellSettingsInternalDef';
1
+ import type { CSpellUserSettings, MappedText, ParsedText } from '@cspell/cspell-types';
2
+ import { CSpellSettingsInternal, CSpellSettingsInternalFinalized } from '../Models/CSpellSettingsInternalDef';
3
3
  import { TextDocument } from '../Models/TextDocument';
4
4
  import { SpellingDictionaryCollection } from '../SpellingDictionary';
5
5
  import { MatchRange } from '../util/TextRange';
6
- import { ParsedText, SimpleRange } from './parsedText';
7
- import { LineValidator, ValidationOptions, type LineSegment } from './textValidator';
6
+ import { SimpleRange } from './parsedText';
7
+ import type { TextValidator } from './ValidationTypes';
8
+ import { ValidationOptions } from './ValidationTypes';
8
9
  import { ValidateTextOptions, ValidationIssue } from './validator';
9
10
  export interface DocumentValidatorOptions extends ValidateTextOptions {
10
11
  /**
@@ -51,10 +52,12 @@ export declare class DocumentValidator {
51
52
  checkDocument(forceCheck?: boolean): ValidationIssue[];
52
53
  get document(): TextDocument;
53
54
  updateDocumentText(text: string): void;
54
- private checkDocumentLines;
55
+ private defaultParser;
56
+ private _checkParsedText;
55
57
  private addPossibleError;
56
58
  private catchError;
57
59
  private errorCatcherWrapper;
60
+ private _parse;
58
61
  private suggest;
59
62
  private genSuggestions;
60
63
  getFinalizedDocSettings(): CSpellSettingsInternal;
@@ -77,9 +80,10 @@ interface Preparations {
77
80
  dictionary: SpellingDictionaryCollection;
78
81
  /** configuration after applying in-doc settings */
79
82
  docSettings: CSpellSettingsInternal;
83
+ finalSettings: CSpellSettingsInternalFinalized;
80
84
  includeRanges: MatchRange[];
81
- lineValidator: LineValidator;
82
- segmenter: (lineSegment: LineSegment) => LineSegment[];
85
+ textValidator: TextValidator;
86
+ segmenter: (texts: MappedText) => Iterable<MappedText>;
83
87
  shouldCheck: boolean;
84
88
  validateOptions: ValidationOptions;
85
89
  localConfig: CSpellUserSettings | undefined;
@@ -17,6 +17,8 @@ const simpleCache_1 = require("../util/simpleCache");
17
17
  const timer_1 = require("../util/timer");
18
18
  const util_1 = require("../util/util");
19
19
  const determineTextDocumentSettings_1 = require("./determineTextDocumentSettings");
20
+ const lineValidatorFactory_1 = require("./lineValidatorFactory");
21
+ const parsedText_1 = require("./parsedText");
20
22
  const textValidator_1 = require("./textValidator");
21
23
  const validator_1 = require("./validator");
22
24
  const ERROR_NOT_PREPARED = 'Validator Must be prepared before calling this function.';
@@ -39,7 +41,6 @@ class DocumentValidator {
39
41
  return this._ready;
40
42
  }
41
43
  prepareSync() {
42
- var _a, _b, _c;
43
44
  // @todo
44
45
  // Determine doc settings.
45
46
  // Calc include ranges
@@ -55,29 +56,30 @@ class DocumentValidator {
55
56
  : useSearchForConfig
56
57
  ? this.errorCatcherWrapper(() => searchForDocumentConfigSync(this._document, settings, settings))
57
58
  : undefined;
58
- this.addPossibleError((_a = localConfig === null || localConfig === void 0 ? void 0 : localConfig.__importRef) === null || _a === void 0 ? void 0 : _a.error);
59
+ this.addPossibleError(localConfig?.__importRef?.error);
59
60
  const config = (0, Settings_1.mergeSettings)(settings, localConfig);
60
61
  const docSettings = (0, determineTextDocumentSettings_1.determineTextDocumentSettings)(this._document, config);
61
62
  const dict = (0, SpellingDictionary_1.getDictionaryInternalSync)(docSettings);
62
- const matcher = new cspell_glob_1.GlobMatcher((localConfig === null || localConfig === void 0 ? void 0 : localConfig.ignorePaths) || [], { root: process.cwd(), dot: true });
63
+ const matcher = new cspell_glob_1.GlobMatcher(localConfig?.ignorePaths || [], { root: process.cwd(), dot: true });
63
64
  const uri = this._document.uri;
64
- const shouldCheck = !matcher.match(uri.fsPath) && ((_b = docSettings.enabled) !== null && _b !== void 0 ? _b : true);
65
+ const shouldCheck = !matcher.match(uri.fsPath) && (docSettings.enabled ?? true);
65
66
  const finalSettings = (0, Settings_1.finalizeSettings)(docSettings);
66
67
  const validateOptions = (0, validator_1.settingsToValidateOptions)(finalSettings);
67
68
  const includeRanges = (0, textValidator_1.calcTextInclusionRanges)(this._document.text, validateOptions);
68
- const segmenter = (0, textValidator_1.mapLineSegmentAgainstRangesFactory)(includeRanges);
69
- const lineValidator = (0, textValidator_1.lineValidatorFactory)(dict, validateOptions);
69
+ const segmenter = (0, parsedText_1.createMappedTextSegmenter)(includeRanges);
70
+ const textValidator = (0, lineValidatorFactory_1.textValidatorFactory)(dict, validateOptions);
70
71
  this._preparations = {
71
72
  config,
72
73
  dictionary: dict,
73
74
  docSettings,
75
+ finalSettings,
74
76
  shouldCheck,
75
77
  validateOptions,
76
78
  includeRanges,
77
79
  segmenter,
78
- lineValidator,
80
+ textValidator,
79
81
  localConfig,
80
- localConfigFilepath: (_c = localConfig === null || localConfig === void 0 ? void 0 : localConfig.__importRef) === null || _c === void 0 ? void 0 : _c.filename,
82
+ localConfigFilepath: localConfig?.__importRef?.filename,
81
83
  };
82
84
  this._ready = true;
83
85
  this._preparationTime = timer.elapsed();
@@ -92,7 +94,6 @@ class DocumentValidator {
92
94
  return this._prepared;
93
95
  }
94
96
  async _prepareAsync() {
95
- var _a, _b, _c;
96
97
  (0, assert_1.default)(!this._ready);
97
98
  const timer = (0, timer_1.createTimer)();
98
99
  const { options, settings } = this;
@@ -103,46 +104,46 @@ class DocumentValidator {
103
104
  ? this.catchError(searchForDocumentConfig(this._document, settings, settings))
104
105
  : undefined;
105
106
  const localConfig = (await pLocalConfig) || {};
106
- this.addPossibleError((_a = localConfig === null || localConfig === void 0 ? void 0 : localConfig.__importRef) === null || _a === void 0 ? void 0 : _a.error);
107
+ this.addPossibleError(localConfig?.__importRef?.error);
107
108
  const config = (0, Settings_1.mergeSettings)(settings, localConfig);
108
109
  const docSettings = (0, determineTextDocumentSettings_1.determineTextDocumentSettings)(this._document, config);
109
110
  const dict = await (0, SpellingDictionary_1.getDictionaryInternal)(docSettings);
110
- const matcher = new cspell_glob_1.GlobMatcher((localConfig === null || localConfig === void 0 ? void 0 : localConfig.ignorePaths) || [], { root: process.cwd(), dot: true });
111
+ const matcher = new cspell_glob_1.GlobMatcher(localConfig?.ignorePaths || [], { root: process.cwd(), dot: true });
111
112
  const uri = this._document.uri;
112
- const shouldCheck = !matcher.match(uri.fsPath) && ((_b = docSettings.enabled) !== null && _b !== void 0 ? _b : true);
113
+ const shouldCheck = !matcher.match(uri.fsPath) && (docSettings.enabled ?? true);
113
114
  const finalSettings = (0, Settings_1.finalizeSettings)(docSettings);
114
115
  const validateOptions = (0, validator_1.settingsToValidateOptions)(finalSettings);
115
116
  const includeRanges = (0, textValidator_1.calcTextInclusionRanges)(this._document.text, validateOptions);
116
- const segmenter = (0, textValidator_1.mapLineSegmentAgainstRangesFactory)(includeRanges);
117
- const lineValidator = (0, textValidator_1.lineValidatorFactory)(dict, validateOptions);
117
+ const segmenter = (0, parsedText_1.createMappedTextSegmenter)(includeRanges);
118
+ const textValidator = (0, lineValidatorFactory_1.textValidatorFactory)(dict, validateOptions);
118
119
  this._preparations = {
119
120
  config,
120
121
  dictionary: dict,
121
122
  docSettings,
123
+ finalSettings,
122
124
  shouldCheck,
123
125
  validateOptions,
124
126
  includeRanges,
125
127
  segmenter,
126
- lineValidator,
128
+ textValidator,
127
129
  localConfig,
128
- localConfigFilepath: (_c = localConfig === null || localConfig === void 0 ? void 0 : localConfig.__importRef) === null || _c === void 0 ? void 0 : _c.filename,
130
+ localConfigFilepath: localConfig?.__importRef?.filename,
129
131
  };
130
132
  this._ready = true;
131
133
  this._preparationTime = timer.elapsed();
132
134
  }
133
135
  _updatePrep() {
134
- var _a;
135
136
  (0, assert_1.default)(this._preparations, ERROR_NOT_PREPARED);
136
137
  const timer = (0, timer_1.createTimer)();
137
138
  const prep = this._preparations;
138
139
  const docSettings = (0, determineTextDocumentSettings_1.determineTextDocumentSettings)(this._document, prep.config);
139
140
  const dict = (0, SpellingDictionary_1.getDictionaryInternalSync)(docSettings);
140
- const shouldCheck = (_a = docSettings.enabled) !== null && _a !== void 0 ? _a : true;
141
+ const shouldCheck = docSettings.enabled ?? true;
141
142
  const finalSettings = (0, Settings_1.finalizeSettings)(docSettings);
142
143
  const validateOptions = (0, validator_1.settingsToValidateOptions)(finalSettings);
143
144
  const includeRanges = (0, textValidator_1.calcTextInclusionRanges)(this._document.text, validateOptions);
144
- const segmenter = (0, textValidator_1.mapLineSegmentAgainstRangesFactory)(includeRanges);
145
- const lineValidator = (0, textValidator_1.lineValidatorFactory)(dict, validateOptions);
145
+ const segmenter = (0, parsedText_1.createMappedTextSegmenter)(includeRanges);
146
+ const textValidator = (0, lineValidatorFactory_1.textValidatorFactory)(dict, validateOptions);
146
147
  this._preparations = {
147
148
  ...prep,
148
149
  dictionary: dict,
@@ -151,7 +152,7 @@ class DocumentValidator {
151
152
  validateOptions,
152
153
  includeRanges,
153
154
  segmenter,
154
- lineValidator,
155
+ textValidator,
155
156
  };
156
157
  this._preparationTime = timer.elapsed();
157
158
  }
@@ -163,27 +164,28 @@ class DocumentValidator {
163
164
  }
164
165
  checkText(range, _text, scope) {
165
166
  const text = this._document.text.slice(range[0], range[1]);
166
- return this.check({ text, range, scope });
167
+ return this.check({ text, range, scope: scope.join(' ') });
167
168
  }
168
169
  check(parsedText) {
169
170
  (0, assert_1.default)(this._ready);
170
171
  (0, assert_1.default)(this._preparations, ERROR_NOT_PREPARED);
171
- const { range, text } = parsedText;
172
- const { segmenter, lineValidator } = this._preparations;
172
+ const { segmenter, textValidator } = this._preparations;
173
173
  // Determine settings for text range
174
174
  // Slice text based upon include ranges
175
175
  // Check text against dictionaries.
176
- const offset = range[0];
177
- const line = this._document.lineAt(offset);
178
- const lineSeg = {
179
- line,
180
- segment: {
181
- text,
182
- offset,
183
- },
184
- };
185
- const aIssues = (0, cspell_pipe_1.pipeSync)(segmenter(lineSeg), (0, cspell_pipe_1.opConcatMap)(lineValidator));
186
- const issues = [...aIssues];
176
+ const document = this._document;
177
+ let line = undefined;
178
+ function mapToIssue(issue) {
179
+ const { range, text, isFlagged, isFound } = issue;
180
+ const offset = range[0];
181
+ const length = range[1] - range[0];
182
+ (0, assert_1.default)(!line || line.offset <= offset);
183
+ if (!line || line.offset + line.text.length <= offset) {
184
+ line = document.lineAt(offset);
185
+ }
186
+ return { text, offset, line, length, isFlagged, isFound };
187
+ }
188
+ const issues = [...(0, cspell_pipe_1.pipeSync)(segmenter(parsedText), (0, cspell_pipe_1.opConcatMap)(textValidator), (0, cspell_pipe_1.opMap)(mapToIssue))];
187
189
  if (!this.options.generateSuggestions) {
188
190
  return issues;
189
191
  }
@@ -198,7 +200,7 @@ class DocumentValidator {
198
200
  checkDocument(forceCheck = false) {
199
201
  (0, assert_1.default)(this._ready);
200
202
  (0, assert_1.default)(this._preparations, ERROR_NOT_PREPARED);
201
- return forceCheck || this.shouldCheckDocument() ? [...this.checkDocumentLines()] : [];
203
+ return forceCheck || this.shouldCheckDocument() ? [...this._checkParsedText(this._parse())] : [];
202
204
  }
203
205
  get document() {
204
206
  return this._document;
@@ -207,15 +209,20 @@ class DocumentValidator {
207
209
  (0, TextDocument_1.updateTextDocument)(this._document, [{ text }]);
208
210
  this._updatePrep();
209
211
  }
210
- *checkDocumentLines() {
212
+ defaultParser() {
213
+ return (0, cspell_pipe_1.pipeSync)(this.document.getLines(), (0, cspell_pipe_1.opMap)((line) => {
214
+ const { text, offset } = line;
215
+ const range = [offset, offset + text.length];
216
+ return { text, range };
217
+ }));
218
+ }
219
+ *_checkParsedText(parsedTexts) {
211
220
  (0, assert_1.default)(this._preparations, ERROR_NOT_PREPARED);
212
221
  const { maxNumberOfProblems = textValidator_1.defaultMaxNumberOfProblems, maxDuplicateProblems = textValidator_1.defaultMaxDuplicateProblems } = this._preparations.validateOptions;
213
222
  let numProblems = 0;
214
223
  const mapOfProblems = new Map();
215
- for (const line of this.document.getLines()) {
216
- const { text, offset } = line;
217
- const range = [offset, offset + text.length];
218
- for (const issue of this.check({ text, range })) {
224
+ for (const pText of parsedTexts) {
225
+ for (const issue of this.check(pText)) {
219
226
  const { text } = issue;
220
227
  const n = (mapOfProblems.get(text) || 0) + 1;
221
228
  mapOfProblems.set(text, n);
@@ -247,11 +254,17 @@ class DocumentValidator {
247
254
  }
248
255
  return undefined;
249
256
  }
257
+ _parse() {
258
+ (0, assert_1.default)(this._preparations, ERROR_NOT_PREPARED);
259
+ const parser = this._preparations.finalSettings.parser;
260
+ if (typeof parser !== 'object')
261
+ return this.defaultParser();
262
+ return parser.parse(this.document.text, this.document.uri.path).parsedTexts;
263
+ }
250
264
  suggest(text) {
251
265
  return this._suggestions.get(text);
252
266
  }
253
267
  genSuggestions(text) {
254
- var _a;
255
268
  (0, assert_1.default)(this._preparations, ERROR_NOT_PREPARED);
256
269
  const settings = this._preparations.docSettings;
257
270
  const dict = this._preparations.dictionary;
@@ -259,7 +272,7 @@ class DocumentValidator {
259
272
  compoundMethod: 0,
260
273
  numSuggestions: this.options.numSuggestions,
261
274
  includeTies: false,
262
- ignoreCase: !((_a = settings.caseSensitive) !== null && _a !== void 0 ? _a : false),
275
+ ignoreCase: !(settings.caseSensitive ?? false),
263
276
  timeout: settings.suggestionsTimeout,
264
277
  numChanges: settings.suggestionNumChanges,
265
278
  });
@@ -1,8 +1,8 @@
1
1
  export { calcTextInclusionRanges } from './textValidator';
2
- export type { CheckOptions, IncludeExcludeOptions, ValidationOptions, ValidationResult } from './textValidator';
2
+ export type { CheckOptions, IncludeExcludeOptions, ValidationOptions, ValidationResult } from './ValidationTypes';
3
3
  export { checkText, IncludeExcludeFlag, validateText } from './validator';
4
4
  export type { CheckTextInfo, TextInfoItem, ValidateTextOptions, ValidationIssue } from './validator';
5
5
  export { DocumentValidator } from './docValidator';
6
6
  export type { DocumentValidatorOptions } from './docValidator';
7
- export type { Offset, SimpleRange, ParsedText } from './parsedText';
7
+ export type { Offset, SimpleRange } from './parsedText';
8
8
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,12 @@
1
+ import { SpellingDictionary } from '../SpellingDictionary/SpellingDictionary';
2
+ import { TextOffsetRO } from './ValidationTypes';
3
+ export interface IsWordValidOptions {
4
+ ignoreCase: boolean;
5
+ useCompounds: boolean | undefined;
6
+ }
7
+ export declare function hasWordCheck(dict: SpellingDictionary, word: string, options: IsWordValidOptions): boolean;
8
+ export declare function isWordValidWithEscapeRetry(dict: SpellingDictionary, wo: TextOffsetRO, line: TextOffsetRO, options: IsWordValidOptions): boolean;
9
+ export declare const __testing__: {
10
+ hasWordCheck: typeof hasWordCheck;
11
+ };
12
+ //# sourceMappingURL=isWordValid.d.ts.map
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.__testing__ = exports.isWordValidWithEscapeRetry = exports.hasWordCheck = void 0;
4
+ function hasWordCheck(dict, word, options) {
5
+ word = word.replace(/\\/g, '');
6
+ return dict.has(word, options);
7
+ }
8
+ exports.hasWordCheck = hasWordCheck;
9
+ function isWordValidWithEscapeRetry(dict, wo, line, options) {
10
+ const firstTry = hasWordCheck(dict, wo.text, options);
11
+ return (firstTry ||
12
+ // Drop the first letter if it is preceded by a '\'.
13
+ (line.text[wo.offset - line.offset - 1] === '\\' && hasWordCheck(dict, wo.text.slice(1), options)));
14
+ }
15
+ exports.isWordValidWithEscapeRetry = isWordValidWithEscapeRetry;
16
+ exports.__testing__ = {
17
+ hasWordCheck,
18
+ };
19
+ //# sourceMappingURL=isWordValid.js.map
@@ -0,0 +1,5 @@
1
+ import { SpellingDictionary } from '../SpellingDictionary/SpellingDictionary';
2
+ import type { LineValidator, TextValidator, ValidationOptions } from './ValidationTypes';
3
+ export declare function lineValidatorFactory(dict: SpellingDictionary, options: ValidationOptions): LineValidator;
4
+ export declare function textValidatorFactory(dict: SpellingDictionary, options: ValidationOptions): TextValidator;
5
+ //# sourceMappingURL=lineValidatorFactory.d.ts.map
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.textValidatorFactory = exports.lineValidatorFactory = void 0;
27
+ const cspell_pipe_1 = require("@cspell/cspell-pipe");
28
+ const gensequence_1 = require("gensequence");
29
+ const RxPat = __importStar(require("../Settings/RegExpPatterns"));
30
+ const Text = __importStar(require("../util/text"));
31
+ const util_1 = require("../util/util");
32
+ const wordSplitter_1 = require("../util/wordSplitter");
33
+ const textValidator_1 = require("./textValidator");
34
+ const isWordValid_1 = require("./isWordValid");
35
+ const parsedText_1 = require("./parsedText");
36
+ function lineValidatorFactory(dict, options) {
37
+ const { minWordLength = textValidator_1.defaultMinWordLength, flagWords = [], allowCompoundWords = false, ignoreCase = true, } = options;
38
+ const hasWordOptions = {
39
+ ignoreCase,
40
+ useCompounds: allowCompoundWords || undefined, // let the dictionaries decide on useCompounds if allow is false
41
+ };
42
+ const dictCol = dict;
43
+ const setOfFlagWords = new Set(flagWords);
44
+ const setOfKnownSuccessfulWords = new Set();
45
+ const rememberFilter = (fn) => (v) => {
46
+ const keep = fn(v);
47
+ if (!keep) {
48
+ setOfKnownSuccessfulWords.add(v.text);
49
+ }
50
+ return keep;
51
+ };
52
+ const filterAlreadyChecked = (wo) => {
53
+ return !setOfKnownSuccessfulWords.has(wo.text);
54
+ };
55
+ function testForFlaggedWord(wo) {
56
+ const text = wo.text;
57
+ return setOfFlagWords.has(text) || setOfFlagWords.has(text.toLowerCase()) || dictCol.isForbidden(text);
58
+ }
59
+ function isWordIgnored(word) {
60
+ return dict.isNoSuggestWord(word, options);
61
+ }
62
+ function isWordFlagged(word) {
63
+ const isIgnored = isWordIgnored(word.text);
64
+ const isFlagged = !isIgnored && testForFlaggedWord(word);
65
+ return isFlagged;
66
+ }
67
+ function checkFlagWords(word) {
68
+ word.isFlagged = isWordFlagged(word);
69
+ return word;
70
+ }
71
+ function checkWord(word, options) {
72
+ const isIgnored = isWordIgnored(word.text);
73
+ const { isFlagged = !isIgnored && testForFlaggedWord(word) } = word;
74
+ const isFound = isFlagged
75
+ ? undefined
76
+ : isIgnored || (0, isWordValid_1.isWordValidWithEscapeRetry)(dictCol, word, word.line, options);
77
+ return (0, util_1.clean)({ ...word, isFlagged, isFound });
78
+ }
79
+ const fn = (lineSegment) => {
80
+ function splitterIsValid(word) {
81
+ return (setOfKnownSuccessfulWords.has(word.text) ||
82
+ (!testForFlaggedWord(word) &&
83
+ (0, isWordValid_1.isWordValidWithEscapeRetry)(dictCol, word, lineSegment.line, hasWordOptions)));
84
+ }
85
+ function checkFullWord(vr) {
86
+ if (vr.isFlagged) {
87
+ return [vr];
88
+ }
89
+ const codeWordResults = (0, cspell_pipe_1.toArray)((0, cspell_pipe_1.pipeSync)(Text.extractWordsFromCodeTextOffset(vr), (0, cspell_pipe_1.opFilter)(filterAlreadyChecked), (0, cspell_pipe_1.opMap)((t) => ({ ...t, line: vr.line })), (0, cspell_pipe_1.opMap)(checkFlagWords), (0, cspell_pipe_1.opFilter)(rememberFilter((wo) => wo.text.length >= minWordLength || !!wo.isFlagged)), (0, cspell_pipe_1.opMap)((wo) => (wo.isFlagged ? wo : checkWord(wo, hasWordOptions))), (0, cspell_pipe_1.opFilter)(rememberFilter((wo) => wo.isFlagged || !wo.isFound)), (0, cspell_pipe_1.opFilter)(rememberFilter((wo) => !RxPat.regExRepeatedChar.test(wo.text))),
90
+ // get back the original text.
91
+ (0, cspell_pipe_1.opMap)((wo) => ({
92
+ ...wo,
93
+ text: Text.extractText(lineSegment.segment, wo.offset, wo.offset + wo.text.length),
94
+ }))));
95
+ if (!codeWordResults.length || isWordIgnored(vr.text) || checkWord(vr, hasWordOptions).isFound) {
96
+ rememberFilter((_) => false)(vr);
97
+ return [];
98
+ }
99
+ return codeWordResults;
100
+ }
101
+ function checkPossibleWords(possibleWord) {
102
+ if (isWordFlagged(possibleWord)) {
103
+ const vr = {
104
+ ...possibleWord,
105
+ line: lineSegment.line,
106
+ isFlagged: true,
107
+ };
108
+ return [vr];
109
+ }
110
+ const mismatches = (0, cspell_pipe_1.toArray)((0, cspell_pipe_1.pipeSync)(Text.extractWordsFromTextOffset(possibleWord), (0, cspell_pipe_1.opFilter)(filterAlreadyChecked), (0, cspell_pipe_1.opMap)((wo) => ({ ...wo, line: lineSegment.line })), (0, cspell_pipe_1.opMap)(checkFlagWords), (0, cspell_pipe_1.opFilter)(rememberFilter((wo) => wo.text.length >= minWordLength || !!wo.isFlagged)), (0, cspell_pipe_1.opConcatMap)(checkFullWord)));
111
+ if (mismatches.length) {
112
+ // Try the more expensive word splitter
113
+ const splitResult = (0, wordSplitter_1.split)(lineSegment.segment, possibleWord.offset, splitterIsValid);
114
+ const nonMatching = splitResult.words.filter((w) => !w.isFound);
115
+ if (nonMatching.length < mismatches.length) {
116
+ return nonMatching.map((w) => ({ ...w, line: lineSegment.line })).map(checkFlagWords);
117
+ }
118
+ }
119
+ return mismatches;
120
+ }
121
+ const checkedPossibleWords = (0, gensequence_1.genSequence)((0, cspell_pipe_1.pipeSync)(Text.extractPossibleWordsFromTextOffset(lineSegment.segment), (0, cspell_pipe_1.opFilter)(filterAlreadyChecked), (0, cspell_pipe_1.opConcatMap)(checkPossibleWords)));
122
+ return checkedPossibleWords;
123
+ };
124
+ return fn;
125
+ }
126
+ exports.lineValidatorFactory = lineValidatorFactory;
127
+ function textValidatorFactory(dict, options) {
128
+ const lineValidator = lineValidatorFactory(dict, options);
129
+ function validator(pText) {
130
+ const { text, range: srcRange, map } = pText;
131
+ const srcOffset = srcRange[0];
132
+ const segment = { text, offset: 0 };
133
+ const lineSegment = { line: segment, segment };
134
+ function mapBackToOriginSimple(vr) {
135
+ const { text, offset, isFlagged, isFound } = vr;
136
+ const r = (0, parsedText_1.mapRangeBackToOriginalPos)([offset, offset + text.length], map);
137
+ const range = [r[0] + srcOffset, r[1] + srcOffset];
138
+ return { text, range, isFlagged, isFound };
139
+ }
140
+ return [...lineValidator(lineSegment)].map(mapBackToOriginSimple);
141
+ }
142
+ return validator;
143
+ }
144
+ exports.textValidatorFactory = textValidatorFactory;
145
+ //# sourceMappingURL=lineValidatorFactory.js.map
@@ -1,21 +1,15 @@
1
+ import { MappedText } from '@cspell/cspell-types';
1
2
  import { ValidationIssue } from './validator';
3
+ import * as TextRange from '../util/TextRange';
2
4
  export declare type Offset = number;
3
5
  export declare type SimpleRange = readonly [Offset, Offset];
4
- export interface ParsedText {
5
- /**
6
- * Transformed text
7
- */
8
- text: string;
9
- /**
10
- * Offset pair of the original text
11
- */
12
- range: SimpleRange;
13
- /**
14
- * Relative map to the original text.
15
- */
16
- map?: number[];
17
- scope?: string[];
18
- }
19
- export declare function mapIssueBackToOriginalPos(parsedText: ParsedText, issue: ValidationIssue): ValidationIssue;
20
- export declare function mapRangeBackToOriginalPos(offRange: SimpleRange, map: number[]): SimpleRange;
6
+ export declare function mapIssueBackToOriginalPos(mappedText: MappedText, issue: ValidationIssue): ValidationIssue;
7
+ export declare function mapRangeBackToOriginalPos(offRange: SimpleRange, map: number[] | undefined): SimpleRange;
8
+ export declare function mapRangeToLocal(rangeOrig: SimpleRange, map: number[] | undefined): SimpleRange;
9
+ /**
10
+ * Factory to create a segmentation function that will segment MappedText against a set of includeRanges.
11
+ * The function produced is optimized for forward scanning. It will perform poorly for randomly ordered offsets.
12
+ * @param includeRanges Allowed ranges for words.
13
+ */
14
+ export declare function createMappedTextSegmenter(includeRanges: TextRange.MatchRange[]): (text: MappedText) => Iterable<MappedText>;
21
15
  //# sourceMappingURL=parsedText.d.ts.map
@@ -1,25 +1,25 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.mapRangeBackToOriginalPos = exports.mapIssueBackToOriginalPos = void 0;
4
- function mapIssueBackToOriginalPos(parsedText, issue) {
5
- if (!parsedText.map || parsedText.map.length === 0)
3
+ exports.createMappedTextSegmenter = exports.mapRangeToLocal = exports.mapRangeBackToOriginalPos = exports.mapIssueBackToOriginalPos = void 0;
4
+ const TextMap_1 = require("../util/TextMap");
5
+ function mapIssueBackToOriginalPos(mappedText, issue) {
6
+ if (!mappedText.map || mappedText.map.length === 0)
6
7
  return issue;
7
- const textOff = mapTextOffsetBackToOriginalPos(parsedText, issue);
8
+ const textOff = mapTextOffsetBackToOriginalPos(mappedText, issue);
8
9
  return {
9
10
  ...issue,
10
11
  ...textOff,
11
12
  };
12
13
  }
13
14
  exports.mapIssueBackToOriginalPos = mapIssueBackToOriginalPos;
14
- function mapTextOffsetBackToOriginalPos(parsedText, textOff) {
15
- var _a;
16
- if (!parsedText.map || !parsedText.map.length)
15
+ function mapTextOffsetBackToOriginalPos(mappedText, textOff) {
16
+ if (!mappedText.map || !mappedText.map.length)
17
17
  return textOff;
18
- const off = textOff.offset - parsedText.range[0];
19
- const range = mapRangeBackToOriginalPos([off, off + ((_a = textOff.length) !== null && _a !== void 0 ? _a : textOff.text.length)], parsedText.map);
18
+ const off = textOff.offset - mappedText.range[0];
19
+ const range = mapRangeBackToOriginalPos([off, off + (textOff.length ?? textOff.text.length)], mappedText.map);
20
20
  return {
21
21
  text: textOff.text,
22
- offset: parsedText.range[0] + range[0],
22
+ offset: mappedText.range[0] + range[0],
23
23
  length: range[1] - range[0],
24
24
  };
25
25
  }
@@ -43,4 +43,68 @@ function mapRangeBackToOriginalPos(offRange, map) {
43
43
  return [iA, iB];
44
44
  }
45
45
  exports.mapRangeBackToOriginalPos = mapRangeBackToOriginalPos;
46
+ function mapRangeToLocal(rangeOrig, map) {
47
+ if (!map || !map.length)
48
+ return rangeOrig;
49
+ const [start, end] = rangeOrig;
50
+ let i = 0, j = 0, p = 0;
51
+ while (p < map.length && map[p] < start) {
52
+ i = map[p];
53
+ j = map[p + 1];
54
+ p += 2;
55
+ }
56
+ const jA = start - i + j;
57
+ while (p < map.length && map[p] < end) {
58
+ i = map[p];
59
+ j = map[p + 1];
60
+ p += 2;
61
+ }
62
+ const jB = end - i + j;
63
+ return [jA, jB];
64
+ }
65
+ exports.mapRangeToLocal = mapRangeToLocal;
66
+ /**
67
+ * Factory to create a segmentation function that will segment MappedText against a set of includeRanges.
68
+ * The function produced is optimized for forward scanning. It will perform poorly for randomly ordered offsets.
69
+ * @param includeRanges Allowed ranges for words.
70
+ */
71
+ function createMappedTextSegmenter(includeRanges) {
72
+ let rangePos = 0;
73
+ function* segmenter(pText) {
74
+ if (!includeRanges.length) {
75
+ return;
76
+ }
77
+ const range = pText.range;
78
+ const textEndPos = range[1];
79
+ let textStartPos = range[0];
80
+ while (rangePos && (rangePos >= includeRanges.length || includeRanges[rangePos].startPos > textStartPos)) {
81
+ rangePos -= 1;
82
+ }
83
+ const cur = includeRanges[rangePos];
84
+ if (textEndPos <= cur.endPos && textStartPos >= cur.startPos) {
85
+ yield pText;
86
+ return;
87
+ }
88
+ while (textStartPos < textEndPos) {
89
+ while (includeRanges[rangePos] && includeRanges[rangePos].endPos <= textStartPos) {
90
+ rangePos += 1;
91
+ }
92
+ if (!includeRanges[rangePos]) {
93
+ break;
94
+ }
95
+ const { startPos, endPos } = includeRanges[rangePos];
96
+ if (textEndPos < startPos) {
97
+ break;
98
+ }
99
+ const a = Math.max(textStartPos, startPos);
100
+ const b = Math.min(textEndPos, endPos);
101
+ if (a !== b) {
102
+ yield (0, TextMap_1.extractTextMapRangeOrigin)(pText, [a, b]);
103
+ }
104
+ textStartPos = b;
105
+ }
106
+ }
107
+ return segmenter;
108
+ }
109
+ exports.createMappedTextSegmenter = createMappedTextSegmenter;
46
110
  //# sourceMappingURL=parsedText.js.map