Skip to content
This repository has been archived by the owner on May 1, 2020. It is now read-only.

TSLint: add ability to exclude files and folders #1204

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
9 changes: 9 additions & 0 deletions config/tslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports = {

tsLintConfig: './tslint.json',

exclude: [
'**/node_modules/**/*'
]

}
33 changes: 24 additions & 9 deletions src/lint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { join } from 'path';
import { lintFiles } from './lint/lint-utils';
import { createProgram, getFileNames } from './lint/lint-factory';
import { Logger } from './logger/logger';
import { getUserConfigFile } from './util/config';
import { getUserConfigFile, fillConfigDefaults } from './util/config';
import { ENV_BAIL_ON_LINT_ERROR, ENV_TYPE_CHECK_ON_LINT } from './util/constants';
import { getBooleanPropertyValue } from './util/helpers';
import { getTsConfigPath } from './transpile';
Expand All @@ -15,17 +15,19 @@ import { runWorker } from './worker-client';
export interface LintWorkerConfig {
tsConfig: string;
tsLintConfig: string | null;
configFile?: string | null;
filePaths?: string[];
typeCheck?: boolean;
exclude?: string[];
}


const taskInfo: TaskInfo = {
fullArg: '--tslint',
shortArg: '-i',
envVar: 'ionic_tslint',
packageConfig: 'IONIC_TSLINT',
defaultConfigFile: '../tslint'
envVar: 'IONIC_TSLINT',
packageConfig: 'ionic_tslint',
defaultConfigFile: 'tslint.config'
};


Expand All @@ -44,11 +46,15 @@ export function lint(context: BuildContext, tsLintConfig?: string | null, typeCh
}

export function lintWorker(context: BuildContext, {tsConfig, tsLintConfig, typeCheck}: LintWorkerConfig) {
const configFile: string = getUserConfigFile(context, taskInfo, null);
const { tsLintCofig: tsLintDefaultConfig, exclude } = fillConfigDefaults(configFile, taskInfo.defaultConfigFile);
tsLintConfig = tsLintConfig || tsLintDefaultConfig;
return getLintConfig(context, tsLintConfig)
.then(tsLintConfig => lintApp(context, {
tsConfig,
tsLintConfig,
typeCheck
typeCheck,
exclude
}));
}

Expand All @@ -58,7 +64,7 @@ export function lintUpdate(changedFiles: ChangedFile[], context: BuildContext, t
return runWorker('lint', 'lintUpdateWorker', context, {
typeCheck,
tsConfig: getTsConfigPath(context),
tsLintConfig: getUserConfigFile(context, taskInfo, null),
tsLintConfig: getTsLintConfig(context, null),
filePaths: changedTypescriptFiles.map(changedTypescriptFile => changedTypescriptFile.filePath)
});
}
Expand All @@ -72,16 +78,16 @@ export function lintUpdateWorker(context: BuildContext, {tsConfig, tsLintConfig,
}


function lintApp(context: BuildContext, {tsConfig, tsLintConfig, typeCheck}: LintWorkerConfig) {
function lintApp(context: BuildContext, {tsConfig, tsLintConfig, typeCheck, exclude}: LintWorkerConfig) {
const program = createProgram(context, tsConfig);
const files = getFileNames(context, program);
const files = getFileNames(context, program, exclude);
return lintFiles(context, program, tsLintConfig, files, {typeCheck});
}


function getLintConfig(context: BuildContext, tsLintConfig: string | null): Promise<string> {
return new Promise((resolve, reject) => {
tsLintConfig = getUserConfigFile(context, taskInfo, tsLintConfig);
tsLintConfig = getTsLintConfig(context);
if (!tsLintConfig) {
tsLintConfig = join(context.rootDir, 'tslint.json');
}
Expand All @@ -100,3 +106,12 @@ function getLintConfig(context: BuildContext, tsLintConfig: string | null): Prom
});
});
}

function getTsLintConfig(context: BuildContext, configFile?: string): string {
configFile = getUserConfigFile(context, taskInfo, configFile);
let { tsLintConfig } = fillConfigDefaults(configFile, taskInfo.defaultConfigFile);
if (tsLintConfig) {
tsLintConfig = join(context.rootDir, tsLintConfig);
}
return tsLintConfig;
}
22 changes: 22 additions & 0 deletions src/lint/lint-factory.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Configuration, Linter } from 'tslint';
import { DiagnosticCategory } from 'typescript';
import * as ts from 'typescript';
import * as glob from 'glob';
import { isObject } from 'util';
import {
createLinter,
Expand Down Expand Up @@ -78,6 +79,27 @@ describe('lint factory', () => {
expect(Array.isArray(files)).toBeTruthy();
expect(files).toEqual(mockFiles);
});

it('should exclude the files matching the ignore pattern', () => {
const context: any = {rootDir: ''};
const program = createProgram(context, '');
const mockFiles = ['test.ts', 'node_modules/folder/file.ts'];

spyOn(Linter, 'getFileNames').and.returnValue(mockFiles);
const globSyncSpy = spyOn(glob, 'sync').and.callFake((file: string, options: any) => {
return file === mockFiles[0] ? [mockFiles[0]] : [];
});

const files = getFileNames(context, program, ['**/node_modules/**/*']);

expect(Array.isArray(files)).toBeTruthy();
expect(files).toEqual(mockFiles.slice(0, 1));
expect(globSyncSpy).toHaveBeenCalledTimes(2);
globSyncSpy.calls.allArgs().map((args, index) => {
expect(args[0]).toBe(mockFiles[index]);
expect(args[1]).toEqual({ignore: ['**/node_modules/**/*'], nodir: true});
});
});
});

describe('typeCheck()', () => {
Expand Down
13 changes: 11 additions & 2 deletions src/lint/lint-factory.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Configuration, Linter, LintResult } from 'tslint';
import { Program, getPreEmitDiagnostics, Diagnostic } from 'typescript';
import * as glob from 'glob';
import { BuildContext } from '../util/interfaces';
import { isObject } from 'util';

Expand Down Expand Up @@ -64,10 +65,18 @@ export function createProgram(context: BuildContext, tsConfig: string): Program
* Get all files that are sourced in TS config
* @param {BuildContext} context
* @param {Program} program
* @param {Array<string>} excludePatterns
* @return {Array<string>}
*/
export function getFileNames(context: BuildContext, program: Program): string[] {
return Linter.getFileNames(program);
export function getFileNames(context: BuildContext, program: Program, excludePatterns?: string[]): string[] {
let files: string[] = Linter.getFileNames(program);
if (excludePatterns) {
const globOptions = { ignore: excludePatterns, nodir: true };
files = files
.map((file: string) => glob.sync(file, globOptions))
.reduce((a: string[], b: string[]) => a.concat(b), []);
}
return files;
}


Expand Down