Skip to content

Commit

Permalink
dev: Refactor cache files (#1986)
Browse files Browse the repository at this point in the history
- Remove any circular import references.
- Move interfaces next to the supporting code.
  • Loading branch information
Jason3S committed Nov 13, 2021
1 parent fa1aa11 commit c37f6e2
Show file tree
Hide file tree
Showing 12 changed files with 83 additions and 69 deletions.
7 changes: 3 additions & 4 deletions packages/cspell/src/application.ts
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
@@ -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
@@ -1 +1,2 @@
export { runLint } from './lint';
export { LintRequest } from './LintRequest';
8 changes: 4 additions & 4 deletions packages/cspell/src/lint/lint.test.ts
@@ -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
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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';

0 comments on commit c37f6e2

Please sign in to comment.