Skip to content

Commit

Permalink
feat: Add ability to check only workspace files. (streetsidesoftware#…
Browse files Browse the repository at this point in the history
…1146)

* Create test.py
* feat: Add ability to check only workspace files.
* dev: wire up `fileIsIncluded`
* Update AppState.test.ts.snap
  • Loading branch information
Jason3S authored Aug 11, 2021
1 parent dbe3996 commit 85a4586
Show file tree
Hide file tree
Showing 21 changed files with 219 additions and 61 deletions.
3 changes: 3 additions & 0 deletions fixtures/workspaces/config-in-package/out/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
console.log('Hello World!');

// specialcode
5 changes: 5 additions & 0 deletions fixtures/workspaces/config-in-package/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 11 additions & 4 deletions fixtures/workspaces/config-in-package/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,17 @@
"scripts": {
"test": "echo test"
},
"author": "",
"license": "MIT",
"cspell": {
"version": "0.2",
"words": []
},
"author": "",
"license": "MIT"
"ignorePaths": [
"out"
],
"dictionaryDefinitions": [],
"dictionaries": [],
"words": [],
"ignoreWords": [],
"import": []
}
}
6 changes: 6 additions & 0 deletions fixtures/workspaces/single/py/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
foo: str = "A Parrot"

print(foo.lower())
print(foo.islower())
print(foo.isupper())
print(foo.isprintable())
7 changes: 7 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2152,6 +2152,13 @@
},
"scope": "resource",
"type": "array"
},
"cSpell.spellCheckOnlyWorkspaceFiles": {
"default": true,
"markdownDescription": "Only spell check files that are in the currently open workspace.\nThis same effect can be achieved using the `files` setting.\n\n```\n\"cSpell.files\": [\"**\", \"**​/.*​/**\"]\n```",
"scope": "window",
"title": "Spell Check Only Workspace Files",
"type": "boolean"
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions packages/_server/spell-checker-config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1780,6 +1780,13 @@
"scope": "application",
"type": "number"
},
"spellCheckOnlyWorkspaceFiles": {
"default": true,
"markdownDescription": "Only spell check files that are in the currently open workspace.\nThis same effect can be achieved using the `files` setting.\n\n```\n\"cSpell.files\": [\"**\", \"**​/.*​/**\"]\n```",
"scope": "window",
"title": "Spell Check Only Workspace Files",
"type": "boolean"
},
"usePnP": {
"description": "Packages managers like Yarn 2 use a `.pnp.cjs` file to assist in loading packages stored in the repository.\n\nWhen true, the spell checker will search up the directory structure for the existence of a PnP file and load it.",
"scope": "resource",
Expand Down
11 changes: 5 additions & 6 deletions packages/_server/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,9 @@ export interface GetConfigurationForDocumentRequest extends TextDocumentInfo {
workspaceConfig?: WorkspaceConfigForDocument;
}

export interface GetConfigurationForDocumentResult {
languageEnabled: boolean | undefined;
fileEnabled: boolean | undefined;
export interface GetConfigurationForDocumentResult extends IsSpellCheckEnabledResult {
settings: config.CSpellUserSettings | undefined;
docSettings: config.CSpellUserSettings | undefined;
excludedBy: ExcludeRef[] | undefined;
configFiles: UriString[];
configTargets: ConfigTarget[];
}
Expand All @@ -128,12 +125,14 @@ export interface ExcludeRef {
glob: string;
id: string | undefined;
name: string | undefined;
filename: string | undefined;
configUri: string | undefined;
}

export interface IsSpellCheckEnabledResult {
languageEnabled: boolean | undefined;
fileEnabled: boolean | undefined;
fileEnabled: boolean;
fileIsIncluded: boolean;
fileIsExcluded: boolean;
excludedBy: ExcludeRef[] | undefined;
}

Expand Down
14 changes: 14 additions & 0 deletions packages/_server/src/config/cspellConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,20 @@ export interface SpellCheckerSettings {
*/
customDictionaries?: CustomDictionaries;

/**
* @title Spell Check Only Workspace Files
* @scope window
* @markdownDescription
* Only spell check files that are in the currently open workspace.
* This same effect can be achieved using the `files` setting.
*
* ```
* "cSpell.files": ["**", "**​/.*​/**"]
* ```
* @default true
*/
spellCheckOnlyWorkspaceFiles?: boolean;

/**
* Show Regular Expression Explorer
* @scope application
Expand Down
5 changes: 3 additions & 2 deletions packages/_server/src/config/documentSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ export class DocumentSettings {
const { ignorePaths = [], files = [] } = fileSettings;

const globRoot = Uri.parse(globRootFolder.uri).fsPath;
if (!files.length) {
if (!files.length && cSpellConfigSettings.spellCheckOnlyWorkspaceFiles !== false) {
// Add file globs that will match the entire workspace.
files.push({ glob: '**', root: globRoot });
files.push({ glob: '**/.*/**', root: globRoot });
Expand Down Expand Up @@ -561,7 +561,8 @@ export function calcIncludeExclude(settings: ExtSettings, uri: Uri): { include:
}

export function isIncluded(settings: ExtSettings, uri: Uri): boolean {
return settings.includeGlobMatcher.match(uri.fsPath);
const files = settings.settings.files;
return !files?.length || settings.includeGlobMatcher.match(uri.fsPath);
}

export function isExcluded(settings: ExtSettings, uri: Uri): boolean {
Expand Down
64 changes: 38 additions & 26 deletions packages/_server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import * as Validator from './validator';
import { ReplaySubject, Subscription, timer } from 'rxjs';
import { filter, tap, debounce, debounceTime, mergeMap, take } from 'rxjs/operators';
import { onCodeActionHandler } from './codeActions';
import { Glob } from 'cspell-lib';
import { CSpellSettingsWithSourceTrace, Glob } from 'cspell-lib';

import * as CSpell from 'cspell-lib';
import { CSpellUserSettings } from './config/cspellConfig';
Expand All @@ -35,7 +35,7 @@ import {
stringifyPatterns,
} from './config/documentSettings';
import { log, logError, logger, logInfo, LogLevel, setWorkspaceBase, setWorkspaceFolders } from 'common-utils/log.js';
import { toUri } from 'common-utils/uriHelper.js';
import { toUri, toFileUri } from 'common-utils/uriHelper.js';
import { PatternMatcher, MatchResult, RegExpMatches } from './PatternMatcher';
import { DictionaryWatcher } from './config/dictionaryWatcher';
import { ConfigWatcher } from './config/configWatcher';
Expand Down Expand Up @@ -196,42 +196,27 @@ export function run(): void {
disposables.push(dictionaryWatcher.listen(onDictionaryChange));
disposables.push(configWatcher.listen(onConfigFileChange));

async function handleIsSpellCheckEnabled(params: TextDocumentInfo): Promise<Api.IsSpellCheckEnabledResult> {
const { uri, languageId } = params;
const fileEnabled = uri ? !(await isUriExcluded(uri)) : undefined;
const settings = await getActiveUriSettings(uri);
const languageEnabled = languageId && uri ? await isLanguageEnabled({ uri, languageId }, settings) : undefined;
const excludedBy = !fileEnabled && uri ? await getExcludedBy(uri) : undefined;

return {
languageEnabled,
fileEnabled,
excludedBy,
};
function handleIsSpellCheckEnabled(params: TextDocumentInfo): Promise<Api.IsSpellCheckEnabledResult> {
return calcIncludeExcludeInfo(params);
}

async function handleGetConfigurationForDocument(
params: Api.GetConfigurationForDocumentRequest
): Promise<Api.GetConfigurationForDocumentResult> {
const { uri, languageId, workspaceConfig } = params;
const { uri, workspaceConfig } = params;
const doc = uri && documents.get(uri);
const docSettings = stringifyPatterns((doc && (await getSettingsToUseForDocument(doc))) || undefined);
const settings = stringifyPatterns(await getActiveUriSettings(uri));
const languageEnabled = languageId && doc ? await isLanguageEnabled(doc, settings) : undefined;
const configFiles = uri ? (await documentSettings.findCSpellConfigurationFilesForUri(uri)).map((uri) => uri.toString()) : [];

const configTargets = workspaceConfig ? calculateConfigTargets(settings, workspaceConfig) : [];
const ieInfo = await calcIncludeExcludeInfo(params);

const fileEnabled = uri ? !(await isUriExcluded(uri)) : undefined;
const excludedBy = !fileEnabled && uri ? await getExcludedBy(uri) : undefined;
return {
languageEnabled,
fileEnabled,
settings,
docSettings,
excludedBy,
configFiles,
configTargets,
docSettings,
settings,
...ieInfo,
};
}

Expand All @@ -240,10 +225,16 @@ export function run(): void {
if (typeof g === 'string') return g;
return g.glob;
}

function extractGlobSourceUri(settings: CSpellSettingsWithSourceTrace): string | undefined {
const filename = settings.__importRef?.filename || settings.source?.filename;
return filename ?? toFileUri(filename)?.toString();
}

const ex = await documentSettings.calcExcludedBy(uri);
return ex.map((ex) => ({
glob: globToString(ex.glob),
filename: ex.settings.__importRef?.filename || ex.settings.source?.filename,
configUri: extractGlobSourceUri(ex.settings),
id: ex.settings.id,
name: ex.settings.name,
}));
Expand Down Expand Up @@ -371,11 +362,32 @@ export function run(): void {
return enabledLanguageIds.indexOf(textDocument.languageId) >= 0;
}

async function calcIncludeExcludeInfo(params: TextDocumentInfo): Promise<Api.IsSpellCheckEnabledResult> {
const { uri, languageId } = params;
const settings = await getActiveUriSettings(uri);
const languageEnabled = languageId && uri ? await isLanguageEnabled({ uri, languageId }, settings) : undefined;

const { include: fileIsIncluded = true, exclude: fileIsExcluded = false } = uri ? await calcFileIncludeExclude(uri) : {};
const fileEnabled = fileIsIncluded && !fileIsExcluded;
const excludedBy = fileIsExcluded && uri ? await getExcludedBy(uri) : undefined;
return {
excludedBy,
fileEnabled,
fileIsExcluded,
fileIsIncluded,
languageEnabled,
};
}

async function isUriExcluded(uri: string) {
const ie = await documentSettings.calcIncludeExclude(toUri(uri));
const ie = await calcFileIncludeExclude(uri);
return !ie.include || ie.exclude;
}

function calcFileIncludeExclude(uri: string) {
return documentSettings.calcIncludeExclude(toUri(uri));
}

async function getBaseSettings(doc: TextDocument) {
const settings = await getActiveSettings(doc);
return { ...CSpell.mergeSettings(defaultSettings, settings), enabledLanguageIds: settings.enabledLanguageIds };
Expand Down
1 change: 1 addition & 0 deletions packages/_settingsViewer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"lint": "eslint 'src/**/*.ts'",
"start:dev": "webpack server --config webpack.dev.js",
"webpack": "webpack --config webpack.prod.js",
"watch": "yarn webpack --watch",
"test": "jest src"
},
"keywords": [],
Expand Down
25 changes: 19 additions & 6 deletions packages/_settingsViewer/src/api/settings/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export type FileUri = string;
export type ConfigTarget = keyof SettingByConfigTarget<void>;
export type ConfigSource = ConfigTarget | 'default';

export type Inherited<T> = T;
export type Extends<T> = T;

export interface SettingByConfigTarget<T> {
user: T;
Expand All @@ -43,17 +43,30 @@ export interface DictionaryEntry {

export interface Config {
inherited: { [key in keyof Config]?: ConfigSource };
locales: Inherited<LocaleList>;
languageIdsEnabled: Inherited<FileTypeList>;
locales: Extends<LocaleList>;
languageIdsEnabled: Extends<FileTypeList>;
}

export interface FileConfig extends TextDocument {
languageEnabled: boolean | undefined;
fileEnabled: boolean | undefined;
export interface FileConfig extends TextDocument, IsSpellCheckEnabledResult {
dictionaries: DictionaryEntry[];
configFiles: ConfigFile[];
}

export interface ExcludeRef {
glob: string;
id?: string | undefined;
name?: string | undefined;
configUri?: string | undefined;
}

export interface IsSpellCheckEnabledResult {
languageEnabled?: boolean | undefined;
fileEnabled: boolean;
fileIsIncluded: boolean;
fileIsExcluded: boolean;
excludedBy?: ExcludeRef[] | undefined;
}

export interface ConfigFile {
uri: FileUri;
name: string;
Expand Down
33 changes: 33 additions & 0 deletions packages/_settingsViewer/src/test/samples/sampleSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ const _sampleSettings: Settings = {
languageId: 'typescript',
languageEnabled: true,
fileEnabled: true,
fileIsIncluded: true,
fileIsExcluded: false,
excludedBy: undefined,
dictionaries: dictionaries.filter((e) => e.languageIds.includes('typescript')),
configFiles: _configFiles,
},
Expand All @@ -108,6 +111,9 @@ const _sampleSettingsSingleFolder: Settings = {
languageId: 'typescript',
languageEnabled: true,
fileEnabled: true,
fileIsIncluded: true,
fileIsExcluded: false,
excludedBy: undefined,
dictionaries: dictionaries.filter((e) => e.languageIds.includes('typescript')),
configFiles: _configFiles,
},
Expand All @@ -117,7 +123,34 @@ const _sampleSettingsSingleFolder: Settings = {
activeFileUri: 'file:///Users/cspell/projects/vscode-cspell-dict-extensions/extensions/dutch/src/extension.ts',
};

const _sampleSettingsExcluded: Settings = {
dictionaries,
knownLanguageIds,
configs: {
user: { locales: ['en'], languageIdsEnabled: languageIdsUser, inherited: {} },
workspace: { locales: ['en'], languageIdsEnabled: languageIdsWorkspace, inherited: { locales: 'user' } },
folder: { locales: ['en'], languageIdsEnabled: languageIdsWorkspace, inherited: { locales: 'user', languageIdsEnabled: 'workspace' } },
file: {
uri: 'file:///Users/cspell/projects/vscode-cspell-dict-extensions/package-lock.json',
fileName: 'package-lock.json',
isUntitled: false,
languageId: 'typescript',
languageEnabled: true,
fileEnabled: false,
fileIsIncluded: true,
fileIsExcluded: true,
excludedBy: [{ glob: 'package-lock.json', id: 'VSCode-Config' }],
dictionaries: dictionaries.filter((e) => e.languageIds.includes('typescript')),
configFiles: _configFiles,
},
},
workspace: sampleWorkspace,
activeFolderUri: 'file:///Users/cspell/projects/vscode-cspell-dict-extensions',
activeFileUri: 'file:///Users/cspell/projects/vscode-cspell-dict-extensions/package-lock.json',
};

export const sampleSettings = Object.freeze(_sampleSettings);
export const sampleSettingsSingleFolder = Object.freeze(_sampleSettingsSingleFolder);
export const sampleSettingsExcluded = Object.freeze(_sampleSettingsExcluded);

// cspell:ignore ripgrep
11 changes: 11 additions & 0 deletions packages/_settingsViewer/src/test/samples/sampleWorkspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ const textDocuments: TextDocument[] = [
isUntitled: false,
languageId: 'rust',
},
{
uri: 'file:///Users/cspell/projects/vscode-cspell-dict-extensions/package-lock.json',
fileName: 'package-lock.json',
isUntitled: false,
languageId: 'json',
},
];

const _sampleWorkspace: Workspace = {
Expand All @@ -35,6 +41,11 @@ const _sampleWorkspace: Workspace = {
name: 'dutch',
uri: 'file:///Users/cspell/projects/vscode-cspell-dict-extensions/extensions/dutch',
},
{
index: 1,
name: 'vscode-cspell-dict-extensions',
uri: 'file:///Users/cspell/projects/vscode-cspell-dict-extensions',
},
],
name: 'ripgrep',
textDocuments,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,5 +132,6 @@ exports[`Validate AppState workspaceFolderNames 1`] = `
Array [
"ripgrep",
"dutch",
"vscode-cspell-dict-extensions",
]
`;
Loading

0 comments on commit 85a4586

Please sign in to comment.