Skip to content

Commit

Permalink
Removed CSpellApplicaton class
Browse files Browse the repository at this point in the history
CSpellApplication class was a false construct just to hold the
configuration.

Made the configuration its own class and moved the method into nested
functions.
  • Loading branch information
Jason Dent committed Apr 2, 2017
1 parent 2c7271a commit 2e88beb
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 44 deletions.
5 changes: 2 additions & 3 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import * as path from 'path';
import * as program from 'commander';
const npmPackage = require(path.join(__dirname, '..', 'package.json'));
import { CSpellApplication, CSpellApplicationOptions, AppError } from './application';
import { CSpellApplicationOptions, AppError } from './application';
import * as App from './application';
import * as chalk from 'chalk';

Expand Down Expand Up @@ -63,8 +63,7 @@ program
debug: options.debug ? debugEmitter : nullEmitter,
};
showHelp = false;
const app = new CSpellApplication(files, options, emitters);
app.run().then(
App.lint(files, options, emitters).then(
result => {
console.error('CSpell: Files checked: %d, Issues found: %d in %d files', result.files, result.issues, result.filesWithIssues.size);
process.exit(result.issues ? 1 : 0);
Expand Down
12 changes: 6 additions & 6 deletions src/application.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ describe('Validate the Application', function() {
const files = ['samples/text.txt'];
const options = {};
const logger = new Logger();
const app = new App.CSpellApplication(files, options, logger);
return app.run()
const lint = App.lint(files, options, logger);
return lint
.then(result => {
expect(logger.errorCount).to.be.equal(0);
expect(logger.infoCount).to.be.greaterThan(0);
Expand All @@ -23,8 +23,8 @@ describe('Validate the Application', function() {
const files = ['samples/text.txt'];
const options = { verbose: true };
const logger = new Logger();
const app = new App.CSpellApplication(files, options, logger);
return app.run()
const lint = App.lint(files, options, logger);
return lint
.then(result => {
expect(logger.errorCount).to.be.equal(0);
expect(logger.infoCount).to.be.greaterThan(0);
Expand All @@ -37,8 +37,8 @@ describe('Validate the Application', function() {
const files = ['samples/text.txt'];
const options = { wordsOnly: true, unique: true };
const logger = new Logger();
const app = new App.CSpellApplication(files, options, logger);
return app.run()
const lint = App.lint(files, options, logger);
return lint
.then(result => {
expect(logger.errorCount).to.be.equal(0);
expect(logger.infoCount).to.be.greaterThan(0);
Expand Down
83 changes: 48 additions & 35 deletions src/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,39 +57,52 @@ export interface Emitters {
error: ErrorEmitter;
}

export class CSpellApplication {

export class CSpellApplicationConfiguration {
readonly info: (message?: any, ...args: any[]) => void;
readonly debug: (message?: any, ...args: any[]) => void;
readonly logIssue: (issue: Issue) => void;
readonly uniqueFilter: (issue: Issue) => boolean;
private configGlob = '{cspell.json,.cspell.json}';
private configGlobOptions: minimatch.IOptions = { nocase: true };
private excludes: GlobSrcInfo[];

readonly configGlob: string = '{cspell.json,.cspell.json}';
readonly configGlobOptions: minimatch.IOptions = { nocase: true };
readonly excludes: GlobSrcInfo[];

constructor(
readonly files: string[],
readonly options: CSpellApplicationOptions,
readonly emitters: Emitters
) {
this.info = emitters.info;
this.debug = emitters.debug;
this.info = emitters.info || this.info;
this.debug = emitters.debug || this.debug;
this.configGlob = options.config || this.configGlob;
this.configGlobOptions = options.config ? {} : this.configGlobOptions;
this.excludes = calcExcludeGlobInfo(options.exclude);
this.logIssue = emitters.issue;
this.logIssue = emitters.issue || this.logIssue;
this.uniqueFilter = options.unique
? util.uniqueFilterFnGenerator((issue: Issue) => issue.text)
: () => true;
}
}

export function lint(
files: string[],
options: CSpellApplicationOptions,
emitters: Emitters
) {
const cfg = new CSpellApplicationConfiguration(files, options, emitters);
return runLint(cfg);
}

function runLint(cfg: CSpellApplicationConfiguration) {
return run();

run(): Promise<RunResult> {
function run(): Promise<RunResult> {

this.header();
header();

const configRx = globRx(this.configGlob, this.configGlobOptions)
const configRx = globRx(cfg.configGlob, cfg.configGlobOptions)
.map(util.unique)
.do(configFiles => this.info(`Config Files Found:\n ${configFiles.join('\n ')}\n`))
.do(configFiles => cfg.info(`Config Files Found:\n ${configFiles.join('\n ')}\n`))
.map(filenames => ({filename: filenames.join(' || '), config: cspell.readSettingsFiles(filenames)}))
.share()
;
Expand All @@ -104,12 +117,12 @@ export class CSpellApplication {
.map(({filename, config}) => extractGlobExcludesFromConfig(filename, config))
.flatMap(a => a)
.toArray()
.map(a => a.concat(this.excludes))
.map(a => a.concat(cfg.excludes))
.toPromise();



const filesRx: Rx.Observable<FileInfo> = this.filterFiles(findFiles(this.files), exclusionGlobs)
const filesRx: Rx.Observable<FileInfo> = filterFiles(findFiles(cfg.files), exclusionGlobs)
.flatMap(filename => {
return fsp.readFile(filename).then(
text => ({text: text.toString(), filename}),
Expand All @@ -135,15 +148,15 @@ export class CSpellApplication {
.map(({configInfo, filename, text}) => {
const ext = path.extname(filename);
const languageIds = cspell.getLanguagesForExt(ext);
this.debug(`Filename: ${filename}, Extension: ${ext}, LanguageIds: ${languageIds.toString()}`);
cfg.debug(`Filename: ${filename}, Extension: ${ext}, LanguageIds: ${languageIds.toString()}`);
const settings = cspell.mergeSettings(cspell.getDefaultSettings(), configInfo.config);
const config = cspell.constructSettingsForText(settings, text, languageIds);
return {configInfo: {...configInfo, config}, filename, text};
})
.filter(info => info.configInfo.config.enabled !== false)
.do(() => status.files += 1)
.flatMap(({configInfo, filename, text}) => {
this.debug(commentJson.stringify(configInfo, undefined, 2));
cfg.debug(commentJson.stringify(configInfo, undefined, 2));
return cspell.validateText(text, configInfo.config)
.then(wordOffsets => {
return {
Expand All @@ -154,10 +167,10 @@ export class CSpellApplication {
})
.do(info => {
const {filename, issues} = info;
this.info(`Checking: ${filename} ... Issues: ${issues.length}`);
cfg.info(`Checking: ${filename} ... Issues: ${issues.length}`);
issues
.filter(this.uniqueFilter)
.forEach((issue) => this.logIssue(issue));
.filter(cfg.uniqueFilter)
.forEach((issue) => cfg.logIssue(issue));
})
.filter(info => !!info.issues.length)
.do(issue => status.filesWithIssues.add(issue.filename))
Expand All @@ -166,51 +179,51 @@ export class CSpellApplication {
return r;
}

protected header() {
this.info(`
function header() {
cfg.info(`
cspell;
Date: ${(new Date()).toUTCString()}
Options:
verbose: ${yesNo(!!this.options.verbose)}
config: ${this.configGlob}
exclude: ${this.excludes.map(a => a.glob).join('\n ')}
files: ${this.files}
wordsOnly: ${yesNo(!!this.options.wordsOnly)}
unique: ${yesNo(!!this.options.unique)}
verbose: ${yesNo(!!cfg.options.verbose)}
config: ${cfg.configGlob}
exclude: ${cfg.excludes.map(a => a.glob).join('\n ')}
files: ${cfg.files}
wordsOnly: ${yesNo(!!cfg.options.wordsOnly)}
unique: ${yesNo(!!cfg.options.unique)}
`);
}


protected isExcluded(filename: string, globs: GlobSrcInfo[]) {
function isExcluded(filename: string, globs: GlobSrcInfo[]) {
const cwd = process.cwd();
const relFilename = (filename.slice(0, cwd.length) === cwd) ? filename.slice(cwd.length) : filename;

for (const glob of globs) {
if (glob.regex.test(relFilename)) {
this.info(`Excluded File: ${filename}; Excluded by ${glob.glob} from ${glob.source}`);
cfg.info(`Excluded File: ${filename}; Excluded by ${glob.glob} from ${glob.source}`);
return true;
}
}
return false;
}

protected filterFiles(files: Rx.Observable<string>, excludeGlobs: Promise<GlobSrcInfo[]>): Rx.Observable<string> {
function filterFiles(files: Rx.Observable < string >, excludeGlobs: Promise<GlobSrcInfo[]>): Rx.Observable < string > {

excludeGlobs.then(excludeGlobs => {
const excludeInfo = excludeGlobs.map(g => `Glob: ${g.glob} from ${g.source}`);
this.info(`Exclusion Globs: \n ${excludeInfo.join('\n ')}\n`);
cfg.info(`Exclusion Globs: \n ${excludeInfo.join('\n ')}\n`);
});
return Rx.Observable.combineLatest(
files,
excludeGlobs,
(filename, globs) => ({filename, globs})
(filename, globs) => ({ filename, globs })
)
.filter(({filename, globs}) => !this.isExcluded(filename, globs))
.map(({filename}) => filename);
.filter(({ filename, globs }) => !isExcluded(filename, globs))
.map(({ filename }) => filename);
}

}


export function trace(_words: string[], _options: TraceOptions): Promise<void> {
return Promise.resolve();
}
Expand Down

0 comments on commit 2e88beb

Please sign in to comment.