Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Use exactOptionalPropertyTypes #2493

Merged
merged 2 commits into from Feb 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 23 additions & 8 deletions packages/cspell-lib/api/api.d.ts
@@ -1,5 +1,5 @@
/// <reference types="node" />
import { Glob, CSpellSettingsWithSourceTrace, ReplaceMap, DictionaryInformation, DictionaryDefinitionPreferred, DictionaryDefinitionAugmented, DictionaryDefinitionCustom, TextOffset, TextDocumentOffset, PnPSettings, ImportFileRef, CSpellUserSettings, LocaleId, CSpellSettings } from '@cspell/cspell-types';
import { Glob, CSpellSettingsWithSourceTrace, ReplaceMap, DictionaryInformation, DictionaryDefinitionPreferred, DictionaryDefinitionAugmented, DictionaryDefinitionCustom, TextOffset, TextDocumentOffset, PnPSettings as PnPSettings$1, ImportFileRef, CSpellUserSettings, LocaleId, CSpellSettings } from '@cspell/cspell-types';
export * from '@cspell/cspell-types';
import { CompoundWordsMethod, SuggestionResult, SuggestionCollector, WeightMap } from 'cspell-trie-lib';
export { CompoundWordsMethod, SuggestionCollector, SuggestionResult } from 'cspell-trie-lib';
Expand Down Expand Up @@ -208,6 +208,19 @@ declare class SpellingDictionaryCollection implements SpellingDictionary {
private _isNoSuggestWord;
}

/**
* The keys of an object where the values cannot be undefined.
*/
declare type OptionalKeys<T> = Exclude<{
[P in keyof T]: T[P] extends Exclude<T[P], undefined> ? never : P;
}[keyof T], undefined>;
/**
* Allow undefined in optional fields
*/
declare type OptionalOrUndefined<T> = {
[P in keyof T]: P extends OptionalKeys<T> ? T[P] | undefined : T[P];
};

declare const SymbolCSpellSettingsInternal: unique symbol;
interface CSpellSettingsInternal extends Omit<CSpellSettingsWithSourceTrace, 'dictionaryDefinitions'> {
[SymbolCSpellSettingsInternal]: true;
Expand Down Expand Up @@ -361,6 +374,7 @@ declare type LoaderResult = URI | undefined;

declare type CSpellSettingsWST$1 = CSpellSettingsWithSourceTrace;
declare type CSpellSettingsI$1 = CSpellSettingsInternal;
declare type PnPSettings = OptionalOrUndefined<PnPSettings$1>;
declare const sectionCSpell = "cSpell";
declare const defaultFileName = "cspell.json";
declare const defaultConfigFilenames: readonly string[];
Expand Down Expand Up @@ -395,18 +409,19 @@ interface ImportFileRefWithError$1 extends ImportFileRef {
declare function extractImportErrors(settings: CSpellSettingsWST$1): ImportFileRefWithError$1[];

declare type CSpellSettingsWST = CSpellSettingsWithSourceTrace;
declare type CSpellSettingsWSTO = OptionalOrUndefined<CSpellSettingsWithSourceTrace>;
declare type CSpellSettingsI = CSpellSettingsInternal;
declare const currentSettingsFileVersion = "0.2";
declare const ENV_CSPELL_GLOB_ROOT = "CSPELL_GLOB_ROOT";
declare function mergeSettings(left: CSpellSettingsWST | CSpellSettingsI, ...settings: (CSpellSettingsWST | CSpellSettingsI)[]): CSpellSettingsI;
declare function mergeInDocSettings(left: CSpellSettingsWST, right: CSpellSettingsWST): CSpellSettingsWST;
declare function calcOverrideSettings(settings: CSpellSettingsWST, filename: string): CSpellSettingsI;
declare function mergeSettings(left: CSpellSettingsWSTO | CSpellSettingsI, ...settings: (CSpellSettingsWSTO | CSpellSettingsI)[]): CSpellSettingsI;
declare function mergeInDocSettings(left: CSpellSettingsWSTO, right: CSpellSettingsWSTO): CSpellSettingsWST;
declare function calcOverrideSettings(settings: CSpellSettingsWSTO, filename: string): CSpellSettingsI;
/**
*
* @param settings - settings to finalize
* @returns settings where all globs and file paths have been resolved.
*/
declare function finalizeSettings(settings: CSpellSettingsWST | CSpellSettingsI): CSpellSettingsI;
declare function finalizeSettings(settings: CSpellSettingsWSTO | CSpellSettingsI): CSpellSettingsI;
/**
* @param filename - filename
* @param globs - globs
Expand All @@ -419,20 +434,20 @@ declare function checkFilenameMatchesGlob(filename: string, globs: Glob | Glob[]
* Return a list of Setting Sources used to create this Setting.
* @param settings the settings to search
*/
declare function getSources(settings: CSpellSettingsWST): CSpellSettingsWST[];
declare function getSources(settings: CSpellSettingsWSTO): CSpellSettingsWSTO[];
interface ImportFileRefWithError extends ImportFileRef {
error: Error;
}
interface ConfigurationDependencies {
configFiles: string[];
dictionaryFiles: string[];
}
declare function extractDependencies(settings: CSpellSettingsWST | CSpellSettingsI): ConfigurationDependencies;
declare function extractDependencies(settings: CSpellSettingsWSTO | CSpellSettingsI): ConfigurationDependencies;

declare function getDefaultSettings(): CSpellSettingsInternal;

declare class ImportError extends Error {
readonly cause?: Error;
readonly cause: Error | undefined;
constructor(msg: string, cause?: Error | unknown);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/cspell-lib/cspell.config.json
Expand Up @@ -17,6 +17,6 @@
],
"allowCompoundWords": false,
"dictionaryDefinitions": [],
"ignoreWords": [],
"ignoreWords": ["CSpellSettingsWSTO"],
"import": ["../../cspell.json"]
}
15 changes: 11 additions & 4 deletions packages/cspell-lib/src/Models/CSpellSettingsInternalDef.ts
Expand Up @@ -5,6 +5,8 @@ import {
DictionaryDefinitionPreferred,
} from '@cspell/cspell-types';
import { WeightMap } from 'cspell-trie-lib';
import { OptionalOrUndefined } from '../util/types';
import { clean } from '../util/util';

export const SymbolCSpellSettingsInternal = Symbol('CSpellSettingsInternal');

Expand All @@ -31,15 +33,20 @@ export interface DictionaryDefinitionInternalWithSource extends DictionaryDefini
readonly __source: string;
}

export function createCSpellSettingsInternal(parts: Partial<CSpellSettingsInternal> = {}): CSpellSettingsInternal {
return {
export function createCSpellSettingsInternal(
parts: OptionalOrUndefined<Partial<CSpellSettingsInternal>> = {}
): CSpellSettingsInternal {
return clean({
...parts,
[SymbolCSpellSettingsInternal]: true,
};
});
}

export function isCSpellSettingsInternal(
cs: CSpellSettingsInternal | CSpellSettingsWithSourceTrace
cs:
| CSpellSettingsInternal
| CSpellSettingsWithSourceTrace
| OptionalOrUndefined<CSpellSettingsInternal | CSpellSettingsWithSourceTrace>
): cs is CSpellSettingsInternal {
return !!(<CSpellSettingsInternal>cs)[SymbolCSpellSettingsInternal];
}
49 changes: 27 additions & 22 deletions packages/cspell-lib/src/Settings/CSpellSettingsServer.ts
Expand Up @@ -13,11 +13,13 @@ import {
CSpellSettingsInternal,
isCSpellSettingsInternal,
} from '../Models/CSpellSettingsInternalDef';
import { OptionalOrUndefined } from '../util/types';
import * as util from '../util/util';
import { calcDictionaryDefsToLoad, mapDictDefsToInternal } from './DictionarySettings';
import { resolvePatterns } from './patterns';

type CSpellSettingsWST = CSpellSettingsWithSourceTrace;
type CSpellSettingsWSTO = OptionalOrUndefined<CSpellSettingsWithSourceTrace>;
type CSpellSettingsI = CSpellSettingsInternal;

export const configSettingsFileVersion0_1 = '0.1';
Expand Down Expand Up @@ -104,8 +106,8 @@ function replaceIfNotEmpty<T>(left: Array<T> = [], right: Array<T> = []) {
}

export function mergeSettings(
left: CSpellSettingsWST | CSpellSettingsI,
...settings: (CSpellSettingsWST | CSpellSettingsI)[]
left: CSpellSettingsWSTO | CSpellSettingsI,
...settings: (CSpellSettingsWSTO | CSpellSettingsI)[]
): CSpellSettingsI {
const rawSettings = settings.reduce<CSpellSettingsI>(merge, toInternalSettings(left));
return util.clean(rawSettings);
Expand All @@ -116,7 +118,10 @@ function isEmpty(obj: Object) {
return Object.keys(obj).length === 0 && obj.constructor === Object;
}

function merge(left: CSpellSettingsWST | CSpellSettingsI, right: CSpellSettingsWST | CSpellSettingsI): CSpellSettingsI {
function merge(
left: CSpellSettingsWSTO | CSpellSettingsI,
right: CSpellSettingsWSTO | CSpellSettingsI
): CSpellSettingsI {
const _left = toInternalSettings(left);
const _right = toInternalSettings(right);
if (left === right) {
Expand Down Expand Up @@ -196,7 +201,7 @@ function versionBasedMergeList<T>(
* @param left - setting on the left side of a merge
* @param right - setting on the right side of a merge
*/
function isLeftAncestorOfRight(left: CSpellSettingsWST, right: CSpellSettingsWST): boolean {
function isLeftAncestorOfRight(left: CSpellSettingsWSTO, right: CSpellSettingsWSTO): boolean {
return hasAncestor(right, left, 0);
}

Expand All @@ -206,11 +211,11 @@ function isLeftAncestorOfRight(left: CSpellSettingsWST, right: CSpellSettingsWST
* @param left - setting on the left side of a merge
* @param right - setting on the right side of a merge
*/
function doesLeftHaveRightAncestor(left: CSpellSettingsWST, right: CSpellSettingsWST): boolean {
function doesLeftHaveRightAncestor(left: CSpellSettingsWSTO, right: CSpellSettingsWSTO): boolean {
return hasAncestor(left, right, 1);
}

function hasAncestor(s: CSpellSettingsWST, ancestor: CSpellSettingsWST, side: number): boolean {
function hasAncestor(s: CSpellSettingsWSTO, ancestor: CSpellSettingsWSTO, side: number): boolean {
const sources = s.source?.sources;
if (!sources) return false;
// calc the first or last index of the source array.
Expand All @@ -219,12 +224,12 @@ function hasAncestor(s: CSpellSettingsWST, ancestor: CSpellSettingsWST, side: nu
return src === ancestor || (src && hasAncestor(src, ancestor, side)) || false;
}

export function mergeInDocSettings(left: CSpellSettingsWST, right: CSpellSettingsWST): CSpellSettingsWST {
export function mergeInDocSettings(left: CSpellSettingsWSTO, right: CSpellSettingsWSTO): CSpellSettingsWST {
const merged = {
...mergeSettings(left, right),
includeRegExpList: mergeListUnique(left.includeRegExpList, right.includeRegExpList),
};
return merged;
return util.clean(merged);
}

/**
Expand All @@ -243,7 +248,7 @@ function takeRightOtherwiseLeft<T>(left: T[] | undefined, right: T[] | undefined
return left || right;
}

export function calcOverrideSettings(settings: CSpellSettingsWST, filename: string): CSpellSettingsI {
export function calcOverrideSettings(settings: CSpellSettingsWSTO, filename: string): CSpellSettingsI {
const _settings = toInternalSettings(settings);
const overrides = _settings.overrides || [];

Expand All @@ -258,7 +263,7 @@ export function calcOverrideSettings(settings: CSpellSettingsWST, filename: stri
* @param settings - settings to finalize
* @returns settings where all globs and file paths have been resolved.
*/
export function finalizeSettings(settings: CSpellSettingsWST | CSpellSettingsI): CSpellSettingsI {
export function finalizeSettings(settings: CSpellSettingsWSTO | CSpellSettingsI): CSpellSettingsI {
return _finalizeSettings(toInternalSettings(settings));
}

Expand All @@ -278,9 +283,9 @@ function _finalizeSettings(settings: CSpellSettingsI): CSpellSettingsI {
}

export function toInternalSettings(settings: undefined): undefined;
export function toInternalSettings(settings: CSpellSettingsI | CSpellSettingsWST): CSpellSettingsI;
export function toInternalSettings(settings?: CSpellSettingsI | CSpellSettingsWST): CSpellSettingsI | undefined;
export function toInternalSettings(settings?: CSpellSettingsI | CSpellSettingsWST): CSpellSettingsI | undefined {
export function toInternalSettings(settings: CSpellSettingsI | CSpellSettingsWSTO): CSpellSettingsI;
export function toInternalSettings(settings?: CSpellSettingsI | CSpellSettingsWSTO): CSpellSettingsI | undefined;
export function toInternalSettings(settings?: CSpellSettingsI | CSpellSettingsWSTO): CSpellSettingsI | undefined {
if (settings === undefined) return undefined;
if (isCSpellSettingsInternal(settings)) return settings;

Expand Down Expand Up @@ -310,12 +315,12 @@ export function checkFilenameMatchesGlob(filename: string, globs: Glob | Glob[])
return m.match(filename);
}

function mergeSources(left: CSpellSettingsWST, right: CSpellSettingsWST): Source {
function mergeSources(left: CSpellSettingsWSTO, right: CSpellSettingsWSTO): Source {
const { source: a = { name: 'left' } } = left;
const { source: b = { name: 'right' } } = right;
return {
name: [left.name || a.name, right.name || b.name].join('|'),
sources: [left, right],
sources: [left as CSpellSettingsWithSourceTrace, right as CSpellSettingsWithSourceTrace],
};
}

Expand All @@ -333,11 +338,11 @@ function max<T>(a: T | undefined, b: T | undefined): T | undefined {
* Return a list of Setting Sources used to create this Setting.
* @param settings the settings to search
*/
export function getSources(settings: CSpellSettingsWST): CSpellSettingsWST[] {
const visited = new Set<CSpellSettingsWST>();
const sources: CSpellSettingsWST[] = [];
export function getSources(settings: CSpellSettingsWSTO): CSpellSettingsWSTO[] {
const visited = new Set<CSpellSettingsWSTO>();
const sources: CSpellSettingsWSTO[] = [];

function _walkSourcesTree(settings: CSpellSettingsWST | undefined): void {
function _walkSourcesTree(settings: CSpellSettingsWSTO | undefined): void {
if (!settings || visited.has(settings)) return;
visited.add(settings);
if (!settings.source?.sources?.length) {
Expand All @@ -352,9 +357,9 @@ export function getSources(settings: CSpellSettingsWST): CSpellSettingsWST[] {
return sources;
}

type Imports = CSpellSettingsWST['__imports'];
type Imports = CSpellSettingsWSTO['__imports'];

function mergeImportRefs(left: CSpellSettingsWST, right: CSpellSettingsWST = {}): Imports {
function mergeImportRefs(left: CSpellSettingsWSTO, right: CSpellSettingsWSTO = {}): Imports {
const imports = new Map(left.__imports || []);
if (left.__importRef) {
imports.set(left.__importRef.filename, left.__importRef);
Expand All @@ -378,7 +383,7 @@ export interface ConfigurationDependencies {
dictionaryFiles: string[];
}

export function extractDependencies(settings: CSpellSettingsWST | CSpellSettingsI): ConfigurationDependencies {
export function extractDependencies(settings: CSpellSettingsWSTO | CSpellSettingsI): ConfigurationDependencies {
const settingsI = toInternalSettings(settings);
const configFiles = [...(mergeImportRefs(settingsI) || [])].map(([filename]) => filename);
const dictionaryFiles = calcDictionaryDefsToLoad(settingsI).map((dict) => dict.path);
Expand Down
6 changes: 5 additions & 1 deletion packages/cspell-lib/src/Settings/DefaultSettings.ts
Expand Up @@ -136,7 +136,11 @@ const getSettings = (function () {
if (!settings) {
const jsonSettings = readSettings(defaultConfigFile);
settings = mergeSettings(_defaultSettings, jsonSettings);
settings.name = jsonSettings.name;
if (jsonSettings.name !== undefined) {
settings.name = jsonSettings.name;
} else {
delete settings.name;
}
}
return settings;
};
Expand Down
30 changes: 12 additions & 18 deletions packages/cspell-lib/src/Settings/DictionarySettings.ts
Expand Up @@ -19,6 +19,7 @@ import { createDictionaryReferenceCollection } from './DictionaryReferenceCollec
import { mapDictionaryInformationToWeightMap, WeightMap } from 'cspell-trie-lib';
import { DictionaryInformation } from '@cspell/cspell-types';
import { RequireOptional, UnionFields } from '../util/types';
import { clean } from '../util/util';

export type DefMapArrayItem = [string, DictionaryDefinitionInternal];

Expand Down Expand Up @@ -116,19 +117,19 @@ type DictDef = Partial<
UnionFields<UnionFields<DictionaryDefinition, DictionaryDefinitionAugmented>, DictionaryDefinitionCustom>
>;

class _DictionaryDefinitionInternalWithSource implements RequireOptional<DictionaryDefinitionInternalWithSource> {
class _DictionaryDefinitionInternalWithSource implements DictionaryDefinitionInternalWithSource {
private _weightMap: WeightMap | undefined;
readonly name: string;
readonly path: string;
readonly addWords: boolean | undefined;
readonly description: string | undefined;
readonly dictionaryInformation: DictionaryInformation | undefined;
readonly type: DictionaryFileTypes | undefined;
readonly file: undefined;
readonly repMap: ReplaceMap | undefined;
readonly useCompounds: boolean | undefined;
readonly noSuggest: boolean | undefined;
readonly scope: CustomDictionaryScope | CustomDictionaryScope[] | undefined;
readonly addWords?: boolean;
readonly description?: string;
readonly dictionaryInformation?: DictionaryInformation;
readonly type?: DictionaryFileTypes;
readonly file?: undefined;
readonly repMap?: ReplaceMap;
readonly useCompounds?: boolean;
readonly noSuggest?: boolean;
readonly scope?: CustomDictionaryScope | CustomDictionaryScope[];
constructor(def: DictionaryDefinition, readonly __source: string) {
// this bit of assignment is to have the compiler help use if any new fields are added.
const defAll: DictDef = def;
Expand Down Expand Up @@ -164,17 +165,10 @@ class _DictionaryDefinitionInternalWithSource implements RequireOptional<Diction
useCompounds,
};

Object.assign(this, clean(ddi));
this.name = ddi.name;
this.file = ddi.file;
this.path = ddi.path;
this.addWords = ddi.addWords;
this.description = ddi.description;
this.dictionaryInformation = ddi.dictionaryInformation;
this.type = ddi.type;
this.repMap = ddi.repMap;
this.noSuggest = ddi.noSuggest;
this.scope = ddi.scope;
this.useCompounds = ddi.useCompounds;
this._weightMap = this.dictionaryInformation
? mapDictionaryInformationToWeightMap(this.dictionaryInformation)
: undefined;
Expand Down
2 changes: 1 addition & 1 deletion packages/cspell-lib/src/Settings/ImportError.ts
@@ -1,7 +1,7 @@
import { isError } from '../util/errors';

export class ImportError extends Error {
readonly cause?: Error;
readonly cause: Error | undefined;
constructor(msg: string, cause?: Error | unknown) {
super(msg);
this.cause = isError(cause) ? cause : undefined;
Expand Down
3 changes: 2 additions & 1 deletion packages/cspell-lib/src/Settings/InDocSettings.ts
@@ -1,6 +1,7 @@
import type { CSpellUserSettings } from '@cspell/cspell-types';
import { genSequence, Sequence } from 'gensequence';
import * as Text from '../util/text';
import { clean } from '../util/util';
import { mergeInDocSettings } from './CSpellSettingsServer';

// cspell:ignore gimuy
Expand Down Expand Up @@ -70,7 +71,7 @@ function parseLocale(match: string): CSpellUserSettings {

function parseIgnoreWords(match: string): CSpellUserSettings {
const wordsSetting = parseWords(match);
return { id: 'in-doc-ignore', ignoreWords: wordsSetting.words };
return clean({ id: 'in-doc-ignore', ignoreWords: wordsSetting.words });
}

function parseRegEx(match: string): string[] {
Expand Down