This repository has been archived by the owner on May 1, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 303
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(lint): improve linting performance
* chore: ignore WebStorm config files * chore: upgrade internal tslint dependencies - update tslint-eslint-rules - run tslint with --type-check flag * fix(interfaces): remove unnecessary semicolons * fix: remove unnecessary semicolons * chore: use stylish formatter for tslint * fix: fix tslint errors * chore: update mock-fs (allows using Node v7+) * feat(lint): upgrade to TSLint v5 * feat(lint): add ENV_TYPE_CHECK_ON_LINT and default to true * test(lint): cleanup a little * refactor(lint): improve linting logic * fix(lint): make CLI argument the same as the env var * feat(lint): add support for enabling type check during lint * test(lint): more cleanup * fix(lint): set project dir to context {rootDir} * chore: update tslint * chore(lint): add typeCheck() fn * chore: fix tslint errors * feat: implement and run type check if enabled * refactor(lint): rename generateFormattedErrorMsg() to generateErrorMessageForFiles() * fix(lint): filter duplicate file names * docs(lint): update note * chore(lint): add some TODOs * feat(lint): set default value for --typeCheck to false * docs(lint): document --typeCheck flag * fix(lint): don't create a new instance of BuildError when throwing after linting failed * fix(lint): set --typeCheckOnLint to null as default instead of false * test(lint): fix typeCheckOnLint flag tests * test(lint): add tests for generateErrorMessageForFiles(), getFileNames() and removeDuplicateFileNames() * chore(lint): remove some TODOs * fix(lint): properly pass CLI arguments to linter * feat(lint): properly disable type check during builds * fix(lint): allow null TSLint config file * chore: revert string change * chore: fix npm warning * chore: upgrade tslint-eslint-rules * perf(lint): only create the linter and TS program once per linting instance instead of once per file * chore: fix tslint errors * chore(lint): only fetch lint result after all files have been linted - rename processLintResults() to processLintResult() - update jsdocs * test(lint): test all lint fns * chore: fix tslint errors * refactor(lint): use Set to filter unique file names
- Loading branch information
1 parent
27ac148
commit 106d82c
Showing
9 changed files
with
271 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
import { Configuration, Linter } from 'tslint'; | ||
import { DiagnosticCategory } from 'typescript'; | ||
import * as ts from 'typescript'; | ||
import { isObject } from 'util'; | ||
import { | ||
createLinter, | ||
createProgram, | ||
getFileNames, | ||
getLintResult, | ||
getTsLintConfig, | ||
lint, | ||
typeCheck | ||
} from './lint-factory'; | ||
|
||
|
||
describe('lint factory', () => { | ||
describe('createProgram()', () => { | ||
it('should create a TS Program', () => { | ||
const context: any = {rootDir: ''}; | ||
const program: any = createProgram(context, ''); | ||
const fns = [ | ||
'getSourceFiles', | ||
'getTypeChecker' | ||
]; | ||
|
||
expect(isObject(program)).toBeTruthy(); | ||
for (const fn of fns) { | ||
expect(typeof program[fn]).toEqual('function'); | ||
} | ||
}); | ||
}); | ||
|
||
describe('getTsLintConfig()', () => { | ||
it('should fetch the TSLint configuration from file path', () => { | ||
const tsConfigFilePath = 'tsconfig.json'; | ||
const mockConfig = {rulesDirectory: ['node_modules/@ionic']}; | ||
spyOn(Configuration, Configuration.loadConfigurationFromPath.name).and.returnValue(mockConfig); | ||
|
||
const config = getTsLintConfig(tsConfigFilePath); | ||
|
||
expect(isObject(config)).toBeTruthy(); | ||
expect(Configuration.loadConfigurationFromPath).toHaveBeenLastCalledWith(tsConfigFilePath); | ||
expect(config).toEqual(mockConfig); | ||
}); | ||
|
||
it('should extend configuration with {linterOptions} if provided', () => { | ||
const tsConfigFilePath = 'tsconfig.json'; | ||
const mockConfig = {rulesDirectory: ['node_modules/@ionic']}; | ||
spyOn(Configuration, Configuration.loadConfigurationFromPath.name).and.returnValue(mockConfig); | ||
const config = getTsLintConfig(tsConfigFilePath, { | ||
typeCheck: true | ||
}); | ||
|
||
expect(config.linterOptions).toEqual({ | ||
typeCheck: true | ||
}); | ||
}); | ||
}); | ||
|
||
describe('createLinter()', () => { | ||
it('should create a Linter', () => { | ||
const context: any = {rootDir: ''}; | ||
const program = createProgram(context, ''); | ||
const linter = createLinter(context, program); | ||
|
||
expect(linter instanceof Linter).toBeTruthy(); | ||
}); | ||
}); | ||
|
||
describe('getFileNames()', () => { | ||
it('should get the file names referenced in the tsconfig.json', () => { | ||
const context: any = {rootDir: ''}; | ||
const program = createProgram(context, ''); | ||
const mockFiles = ['test.ts']; | ||
spyOn(Linter, 'getFileNames').and.returnValue(mockFiles); | ||
const files = getFileNames(context, program); | ||
|
||
expect(Array.isArray(files)).toBeTruthy(); | ||
expect(files).toEqual(mockFiles); | ||
}); | ||
}); | ||
|
||
describe('typeCheck()', () => { | ||
it('should not be called if {typeCheck} is false', done => { | ||
const context: any = {rootDir: ''}; | ||
const program = createProgram(context, ''); | ||
|
||
spyOn(ts, ts.getPreEmitDiagnostics.name).and.returnValue([]); | ||
|
||
typeCheck(context, program, {typeCheck: false}) | ||
.then((result) => { | ||
expect(ts.getPreEmitDiagnostics).toHaveBeenCalledTimes(0); | ||
expect(result).toEqual([]); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should type check if {typeCheck} is true', done => { | ||
const context: any = {rootDir: ''}; | ||
const program = createProgram(context, ''); | ||
|
||
const diagnostics: any = [{ | ||
file: {}, | ||
start: 2, | ||
length: 10, | ||
messageText: 'Oops', | ||
category: DiagnosticCategory.Warning, | ||
code: 120 | ||
}]; | ||
|
||
spyOn(ts, ts.getPreEmitDiagnostics.name).and.returnValue(diagnostics); | ||
|
||
typeCheck(context, program, {typeCheck: true}) | ||
.then((result) => { | ||
expect(ts.getPreEmitDiagnostics).toHaveBeenCalledWith(program); | ||
expect(result).toEqual(diagnostics); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('lint()', () => { | ||
it('should lint a file', () => { | ||
const context: any = {rootDir: ''}; | ||
const program = createProgram(context, ''); | ||
const linter = createLinter(context, program); | ||
spyOn(linter, 'lint').and.returnValue(undefined); | ||
const config = {}; | ||
const filePath = 'test.ts'; | ||
const fileContents = 'const test = true;'; | ||
|
||
lint(linter, config, filePath, fileContents); | ||
|
||
expect(linter.lint).toHaveBeenCalledWith(filePath, fileContents, config); | ||
}); | ||
}); | ||
describe('getLintResult()', () => { | ||
it('should get the lint results after linting a file', () => { | ||
const context: any = {rootDir: ''}; | ||
const program = createProgram(context, ''); | ||
const linter = createLinter(context, program); | ||
spyOn(linter, 'lint').and.returnValue(undefined); | ||
const mockResult: any = {}; | ||
spyOn(linter, 'getResult').and.returnValue(mockResult); | ||
const config = { | ||
jsRules: new Map(), | ||
rules: new Map() | ||
}; | ||
const filePath = 'test.ts'; | ||
const fileContents = 'const test = true;'; | ||
|
||
lint(linter, config, filePath, fileContents); | ||
|
||
const result = getLintResult(linter); | ||
expect(isObject(result)).toBeTruthy(); | ||
expect(result).toEqual(mockResult); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.