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.
- package/dist/LanguageIds.js +1 -2
- package/dist/Models/TextDocument.js +3 -3
- package/dist/Settings/CSpellSettingsServer.js +45 -10
- package/dist/Settings/DictionarySettings.js +1 -1
- package/dist/Settings/LanguageSettings.js +1 -2
- package/dist/Settings/configLoader.js +15 -19
- package/dist/Settings/link.js +5 -6
- package/dist/Settings/pnpLoader.js +1 -2
- package/dist/SpellingDictionary/DictionaryLoader.js +2 -2
- package/dist/SpellingDictionary/SpellingDictionary.d.ts +2 -2
- package/dist/SpellingDictionary/SpellingDictionaryCollection.js +1 -1
- package/dist/SpellingDictionary/SpellingDictionaryFromTrie.js +3 -4
- package/dist/SpellingDictionary/SpellingDictionaryMethods.d.ts +2 -2
- package/dist/SpellingDictionary/SpellingDictionaryMethods.js +4 -4
- package/dist/SpellingDictionary/createSpellingDictionary.js +1 -1
- package/dist/spellCheckFile.js +3 -3
- package/dist/suggestions.js +9 -13
- package/dist/textValidation/ValidationTypes.d.ts +41 -0
- package/dist/textValidation/ValidationTypes.js +3 -0
- package/dist/textValidation/determineTextDocumentSettings.js +2 -3
- package/dist/textValidation/docValidator.d.ts +11 -7
- package/dist/textValidation/docValidator.js +56 -43
- package/dist/textValidation/index.d.ts +2 -2
- package/dist/textValidation/isWordValid.d.ts +12 -0
- package/dist/textValidation/isWordValid.js +19 -0
- package/dist/textValidation/lineValidatorFactory.d.ts +5 -0
- package/dist/textValidation/lineValidatorFactory.js +145 -0
- package/dist/textValidation/parsedText.d.ts +11 -17
- package/dist/textValidation/parsedText.js +74 -10
- package/dist/textValidation/textValidator.d.ts +5 -42
- package/dist/textValidation/textValidator.js +8 -114
- package/dist/textValidation/validator.d.ts +5 -1
- package/dist/textValidation/validator.js +6 -4
- package/dist/trace.js +15 -19
- package/dist/util/Memorizer.d.ts +8 -1
- package/dist/util/Memorizer.js +10 -6
- package/dist/util/PairingHeap.js +1 -2
- package/dist/util/TextMap.d.ts +15 -0
- package/dist/util/TextMap.js +62 -0
- package/dist/util/memorizerWeak.js +2 -4
- package/dist/util/search.js +2 -2
- package/dist/util/text.js +1 -1
- package/dist/util/timer.js +1 -1
- package/dist/util/wordSplitter.js +2 -4
- 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 {
|
|
7
|
-
import {
|
|
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
|
|
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
|
-
|
|
82
|
-
segmenter: (
|
|
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(
|
|
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(
|
|
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) && (
|
|
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,
|
|
69
|
-
const
|
|
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
|
-
|
|
80
|
+
textValidator,
|
|
79
81
|
localConfig,
|
|
80
|
-
localConfigFilepath:
|
|
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(
|
|
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(
|
|
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) && (
|
|
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,
|
|
117
|
-
const
|
|
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
|
-
|
|
128
|
+
textValidator,
|
|
127
129
|
localConfig,
|
|
128
|
-
localConfigFilepath:
|
|
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 =
|
|
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,
|
|
145
|
-
const
|
|
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
|
-
|
|
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 {
|
|
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
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
|
216
|
-
const
|
|
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: !(
|
|
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 './
|
|
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
|
|
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
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
5
|
-
|
|
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(
|
|
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(
|
|
15
|
-
|
|
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 -
|
|
19
|
-
const range = mapRangeBackToOriginalPos([off, off + (
|
|
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:
|
|
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
|