-
-
Notifications
You must be signed in to change notification settings - Fork 103
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Support forbidden words in dictionaries (#1516)
## Making Words Forbidden There are several ways to mark a word as forbidden: 1. In a custom word list with words beginning with `!`. ``` !forbiddenWord ``` 2. In `words` section of `cspell` configuration: ``` "words": [ "!forbiddenWord", "configstore" ], ``` 3. In `flagWords` section of `cspell` configuration: ``` "flagWords": ["forbiddenWord"] ``` ## Overriding Forbidden words Sometimes it is necessary to allow a word even if it is forbidden. ### In a comment ```js /** * Do not mark `forbiddenWord` as incorrect. * cspell:ignore forbiddenWord */ ``` ### In the `cspell` configuration ```jsonc { "ignoreWords": ["forbiddenWord"] } ```
- Loading branch information
Showing
20 changed files
with
307 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,71 @@ | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
const defaultSize = 50000; | ||
|
||
export function memorizer<A0, T>(fn: (arg: A0) => T, size?: number): (arg0: A0) => T; | ||
export function memorizer<A0, A1, T>(fn: (arg: A0, arg1: A1) => T, size?: number): (arg0: A0, arg1: A1) => T; | ||
export function memorizer<A0, A1, A2, T>( | ||
fn: (arg: A0, arg1: A1, arg2: A2) => T, | ||
size?: number | ||
): (arg0: A0, arg1: A1, arg2: A2) => T; | ||
export function memorizer<A, T>(fn: (...args: A[]) => T, size: number = defaultSize): (...args: A[]) => T { | ||
const cache = new Map<string, T>(); | ||
return (...args: A[]) => { | ||
const key = args.join('>!@['); | ||
if (!cache.has(key)) { | ||
if (cache.size >= size) { | ||
cache.clear(); | ||
} | ||
cache.set(key, fn(...args)); | ||
/** Only types that can be easily turned into strings */ | ||
type P0 = string | number | boolean | RegExp | undefined; | ||
|
||
type Primitive = P0 | P0[]; | ||
|
||
/** | ||
* Memorize the result of a function call to be returned on later calls with the same parameters. | ||
* | ||
* Note: The parameters are converted into a string: `key = args.join('>!@[')` | ||
* | ||
* For speed, it keeps two caches, L0 and L1. Each cache can contain up to `size` values. But that actual number | ||
* of cached values is between `size + 1` and `size * 2`. | ||
* | ||
* Caches are NOT sorted. Items are added to L0 until it is full. Once it is full, L1 takes over L0's values and L0 is cleared. | ||
* | ||
* If an item is not found in L0, L1 is checked before calling the `fn` and the resulting value store in L0. | ||
* | ||
* @param fn - function to be called. | ||
* @param size - size of cache | ||
*/ | ||
export function memorizer< | ||
F extends (...args: Primitive[]) => any, | ||
Args extends Parameters<F> = Parameters<F>, | ||
R extends ReturnType<F> = ReturnType<F> | ||
>(fn: F, size?: number): (...args: Args) => R { | ||
return memorizerKeyBy(fn, (...args: Args) => args.join('>!@['), size); | ||
} | ||
|
||
/** | ||
* Memorize the result of a function call to be returned on later calls with the same parameters. | ||
* | ||
* Note: `keyFn` is use to convert the function parameters into a string to look up in the cache. | ||
* | ||
* For speed, it keeps two caches, L0 and L1. Each cache can contain up to `size` values. But that actual number | ||
* of cached values is between `size + 1` and `size * 2`. | ||
* | ||
* Caches are NOT sorted. Items are added to L0 until it is full. Once it is full, L1 takes over L0's values and L0 is cleared. | ||
* | ||
* If an item is not found in L0, L1 is checked before calling the `fn` and the resulting value store in L0. | ||
* | ||
* @param fn - function to be memorized | ||
* @param keyFn - extracts a `key` value from the arguments to `fn` to be used as the key to the cache | ||
* @param size - size of the cache. | ||
* @returns A function | ||
*/ | ||
export function memorizerKeyBy< | ||
F extends (...args: any[]) => any, | ||
Args extends Parameters<F> = Parameters<F>, | ||
R extends ReturnType<F> = ReturnType<F> | ||
>(fn: F, keyFn: (...args: Args) => string, size: number = defaultSize): (...args: Args) => R { | ||
let count = 0; | ||
let cacheL0: Record<string, R> = Object.create(null); | ||
let cacheL1: Record<string, R> = Object.create(null); | ||
return (...args: Args) => { | ||
const key = keyFn(...args); | ||
if (key in cacheL0) return cacheL0[key]; | ||
|
||
const v = key in cacheL1 ? cacheL1[key] : fn(...args); | ||
if (count >= size) { | ||
cacheL1 = cacheL0; | ||
cacheL0 = Object.create(null); | ||
count = 0; | ||
} | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
return cache.get(key)!; | ||
cacheL0[key] = v; | ||
++count; | ||
return v; | ||
}; | ||
} |
Oops, something went wrong.