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

dev: Refactor cache files #1986

Merged
merged 1 commit into from
Nov 13, 2021
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions packages/cspell/src/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,17 @@ import type { CSpellReporter, RunResult } from '@cspell/cspell-types';
import * as cspell from 'cspell-lib';
import { CheckTextInfo, TraceResult, traceWords } from 'cspell-lib';
import * as path from 'path';
import { LinterConfiguration } from './LinterConfiguration';
import { calcFinalConfigInfo, readConfig, readFile } from './fileHelper';
import { runLint } from './lint';
import { LintRequest, runLint } from './lint';
import { BaseOptions, LinterOptions, TraceOptions } from './options';
import * as util from './util/util';
export type { TraceResult } from 'cspell-lib';
export { IncludeExcludeFlag } from 'cspell-lib';
export type { TraceResult } from 'cspell-lib';

export type AppError = NodeJS.ErrnoException;

export function lint(files: string[], options: LinterOptions, emitters: CSpellReporter): Promise<RunResult> {
const cfg = new LinterConfiguration(files, options, emitters);
const cfg = new LintRequest(files, options, emitters);
return runLint(cfg);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import type { CSpellReporter, Issue } from '@cspell/cspell-types';
import * as path from 'path';
import { LinterOptions } from './options';
import { calcExcludeGlobInfo, GlobSrcInfo } from './util/glob';
import * as util from './util/util';
import { LinterOptions } from '../options';
import { calcExcludeGlobInfo, GlobSrcInfo } from '../util/glob';
import * as util from '../util/util';

const defaultContextRange = 20;

export class LinterConfiguration {
export class LintRequest {
readonly uniqueFilter: (issue: Issue) => boolean;
readonly locale: string;

Expand Down
1 change: 1 addition & 0 deletions packages/cspell/src/lint/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { runLint } from './lint';
export { LintRequest } from './LintRequest';
8 changes: 4 additions & 4 deletions packages/cspell/src/lint/lint.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as path from 'path';
import { LinterConfiguration } from '../LinterConfiguration';
import { LintRequest } from './LintRequest';
import { InMemoryReporter } from '../util/InMemoryReporter';
import { runLint } from './lint';

Expand All @@ -14,9 +14,9 @@ describe('Linter Validation Tests', () => {
test('globs on the command line override globs in the config.', async () => {
const options = { root: latexSamples };
const reporter = new InMemoryReporter();
const rWithoutFiles = await runLint(new LinterConfiguration([], options, reporter));
const rWithoutFiles = await runLint(new LintRequest([], options, reporter));
expect(rWithoutFiles.files).toBe(4);
const rWithFiles = await runLint(new LinterConfiguration(['**/ebook.tex'], options, reporter));
const rWithFiles = await runLint(new LintRequest(['**/ebook.tex'], options, reporter));
expect(rWithFiles.files).toBe(1);
});

Expand All @@ -37,7 +37,7 @@ describe('Linter Validation Tests', () => {
${['**/ebook.tex']} | ${{ root: samples, config: j(samples, 'linked/cspell-import.json') }} | ${oc({ errors: 0, files: 1 })} | ${oc({ errorCount: 0, issues: [] })}
`('runLint $files $options', async ({ files, options, expectedRunResult, expectedReport }) => {
const reporter = new InMemoryReporter();
const runResult = await runLint(new LinterConfiguration(files, options, reporter));
const runResult = await runLint(new LintRequest(files, options, reporter));
expect(runResult).toEqual(expectedRunResult);
expect(runResult).toEqual(reporter.runResult);
expect(report(reporter)).toEqual(expectedReport);
Expand Down
9 changes: 5 additions & 4 deletions packages/cspell/src/lint/lint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ import * as path from 'path';
import { format } from 'util';
import { URI } from 'vscode-uri';
import { ConfigInfo, fileInfoToDocument, FileResult, findFiles, readConfig, readFileInfo } from '../fileHelper';
import { LinterConfiguration } from '../LinterConfiguration';
import { createCache, CSpellLintResultCache } from '../util/cache';
import type { CSpellLintResultCache } from '../util/cache';
import { createCache } from '../util/cache';
import { toError } from '../util/errors';
import type { GlobOptions } from '../util/glob';
import { buildGlobMatcher, extractGlobsFromMatcher, extractPatterns, normalizeGlobsToRoot } from '../util/glob';
import { loadReporters, mergeReporters } from '../util/reporters';
import { getTimeMeasurer } from '../util/timer';
import * as util from '../util/util';
import { LintRequest } from './LintRequest';

export async function runLint(cfg: LinterConfiguration): Promise<RunResult> {
export async function runLint(cfg: LintRequest): Promise<RunResult> {
let { reporter } = cfg;
cspell.setLogger(getLoggerFromReporter(reporter));
const configErrors = new Set<string>();
Expand Down Expand Up @@ -98,7 +99,7 @@ export async function runLint(cfg: LinterConfiguration): Promise<RunResult> {

async function processFiles(files: string[], configInfo: ConfigInfo, fileCount: number): Promise<RunResult> {
const status: RunResult = runResult();
const cache = createCache(cfg);
const cache = createCache({ ...cfg.options, root: cfg.root });

const emitProgress = (filename: string, fileNum: number, result: FileResult) =>
reporter.progress({
Expand Down
22 changes: 3 additions & 19 deletions packages/cspell/src/options.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export interface LinterOptions extends BaseOptions {
import type { CacheOptions } from './util/cache';

export interface LinterOptions extends BaseOptions, CacheOptions {
/**
* Display verbose information
*/
Expand Down Expand Up @@ -40,24 +42,6 @@ export interface LinterOptions extends BaseOptions {
*/
showSuggestions?: boolean;

/**
* Store the info about processed files in order to only operate on the changed ones.
*/
cache?: boolean;

// cspell:word cspellcache
/**
* Path to the cache location. Can be a file or a directory.
* If none specified .cspellcache will be used.
* The file will be created in the directory where the cspell command is executed.
*/
cacheLocation?: string;

/**
* Strategy to use for detecting changed files, default: metadata
*/
cacheStrategy?: 'metadata' | 'content';

/**
* Enable filtering out files matching globs found in `.gitignore` files.
*/
Expand Down
16 changes: 16 additions & 0 deletions packages/cspell/src/util/cache/CSpellLintResultCache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ConfigInfo, FileResult } from '../../fileHelper';

export interface CSpellLintResultCache {
/**
* Retrieve cached lint results for a given file name, if present in the cache.
*/
getCachedLintResults(filename: string, configInfo: ConfigInfo): Promise<FileResult | undefined>;
/**
* Set the cached lint results.
*/
setCachedLintResults(result: FileResult, configInfo: ConfigInfo): void;
/**
* Persists the in-memory cache to disk.
*/
reconcile(): void;
}
19 changes: 19 additions & 0 deletions packages/cspell/src/util/cache/CacheOptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export interface CacheOptions {
/**
* Store the info about processed files in order to only operate on the changed ones.
*/
cache?: boolean;

// cspell:word cspellcache
/**
* Path to the cache location. Can be a file or a directory.
* If none specified .cspellcache will be used.
* The file will be created in the directory where the cspell command is executed.
*/
cacheLocation?: string;

/**
* Strategy to use for detecting changed files, default: metadata
*/
cacheStrategy?: 'metadata' | 'content';
}
4 changes: 2 additions & 2 deletions packages/cspell/src/util/cache/DiskCache.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { FileEntryCache, FileDescriptor } from 'file-entry-cache';
import type { FileDescriptor, FileEntryCache } from 'file-entry-cache';
import { create as createFileEntryCache } from 'file-entry-cache';
import type { ConfigInfo, FileResult } from '../../fileHelper';
import { readFileInfo } from '../../fileHelper';
import { CSpellLintResultCache } from '.';
import type { CSpellLintResultCache } from './CSpellLintResultCache';
import { getConfigHash } from './getConfigHash';

type CachedFileResult = Omit<FileResult, 'fileInfo' | 'elapsedTimeMs'>;
Expand Down
2 changes: 1 addition & 1 deletion packages/cspell/src/util/cache/DummyCache.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { CSpellLintResultCache } from '.';
import type { CSpellLintResultCache } from './CSpellLintResultCache';

/**
* Dummy cache implementation that should be usd if caching option is disabled.
Expand Down
21 changes: 21 additions & 0 deletions packages/cspell/src/util/cache/createCache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import path from 'path';
import { CacheOptions } from './CacheOptions';
import { CSpellLintResultCache } from './CSpellLintResultCache';
import { DiskCache } from './DiskCache';
import { DummyCache } from './DummyCache';

// cspell:word cspellcache
export const DEFAULT_CACHE_LOCATION = '.cspellcache';

export interface CreateCacheOptions extends CacheOptions {
root: string;
}

/**
* Creates CSpellLintResultCache (disk cache if caching is enabled in config or dummy otherwise)
*/

export function createCache(options: CreateCacheOptions): CSpellLintResultCache {
const { cache, cacheLocation = DEFAULT_CACHE_LOCATION, cacheStrategy = 'metadata', root } = options;
return cache ? new DiskCache(path.resolve(root, cacheLocation), cacheStrategy === 'content') : new DummyCache();
}
35 changes: 4 additions & 31 deletions packages/cspell/src/util/cache/index.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,4 @@
import path from 'path';
import type { LinterConfiguration } from '../../LinterConfiguration';
import type { ConfigInfo, FileResult } from '../../fileHelper';
import { DummyCache } from './DummyCache';
import { DiskCache } from './DiskCache';

// cspell:word cspellcache
export const DEFAULT_CACHE_LOCATION = '.cspellcache';

export interface CSpellLintResultCache {
/**
* Retrieve cached lint results for a given file name, if present in the cache.
*/
getCachedLintResults(filename: string, configInfo: ConfigInfo): Promise<FileResult | undefined>;
/**
* Set the cached lint results.
*/
setCachedLintResults(result: FileResult, configInfo: ConfigInfo): void;
/**
* Persists the in-memory cache to disk.
*/
reconcile(): void;
}

/**
* Creates CSpellLintResultCache (disk cache if caching is enabled in config or dummy otherwise)
*/
export function createCache(cfg: LinterConfiguration): CSpellLintResultCache {
const { cache, cacheLocation = DEFAULT_CACHE_LOCATION, cacheStrategy = 'metadata' } = cfg.options;
return cache ? new DiskCache(path.resolve(cfg.root, cacheLocation), cacheStrategy === 'content') : new DummyCache();
}
export { createCache, DEFAULT_CACHE_LOCATION } from './createCache';
export type { CreateCacheOptions } from './createCache';
export type { CSpellLintResultCache } from './CSpellLintResultCache';
export type { CacheOptions } from './CacheOptions';