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): capture results of all linted files
capture results of all linted files closes #725
- Loading branch information
1 parent
e13b857
commit eb4314e
Showing
5 changed files
with
205 additions
and
60 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { createProgram as lintCreateProgram, findConfiguration, getFileNames as lintGetFileNames } from 'tslint'; | ||
import * as Linter from 'tslint'; | ||
import { Program } from 'typescript'; | ||
|
||
export function getLinter(filePath: string, fileContent: string, program: Program) { | ||
const configuration = findConfiguration(null, filePath); | ||
|
||
const linter = new Linter(filePath, fileContent, { | ||
configuration: configuration, | ||
formatter: null, | ||
formattersDirectory: null, | ||
rulesDirectory: null, | ||
}, program); | ||
|
||
return linter; | ||
} | ||
|
||
export function createProgram(configFilePath: string, sourceDir: string) { | ||
return lintCreateProgram(configFilePath, sourceDir); | ||
} | ||
|
||
export function getFileNames(program: Program) { | ||
return lintGetFileNames(program); | ||
} |
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,94 @@ | ||
import * as lintUtils from './lint-utils'; | ||
import * as lintFactory from './lint-factory'; | ||
import * as helpers from '../util/helpers'; | ||
import * as fs from 'fs'; | ||
|
||
import * as tsLintLogger from '../logger/logger-tslint'; | ||
import * as loggerDiagnostics from '../logger/logger-diagnostics'; | ||
|
||
describe('lint utils', () => { | ||
describe('lintFile', () => { | ||
it('should return lint details', () => { | ||
// arrange | ||
const mockLintResults: any = { | ||
failures: [] | ||
}; | ||
const mockLinter = { | ||
lint: () => { | ||
return mockLintResults; | ||
} | ||
}; | ||
const filePath = '/Users/dan/someFile.ts'; | ||
const fileContent = 'someContent'; | ||
const mockProgram: any = {}; | ||
spyOn(helpers, helpers.readFileAsync.name).and.returnValue(Promise.resolve(fileContent)); | ||
spyOn(lintFactory, lintFactory.getLinter.name).and.returnValue(mockLinter); | ||
spyOn(fs, 'openSync').and.returnValue(null); | ||
spyOn(fs, 'readSync').and.returnValue(null); | ||
spyOn(fs, 'closeSync').and.returnValue(null); | ||
// act | ||
|
||
const result = lintUtils.lintFile(null, mockProgram, filePath); | ||
|
||
// assert | ||
return result.then((result: lintUtils.LintResult) => { | ||
expect(result.filePath).toEqual(filePath); | ||
expect(result.failures).toEqual(mockLintResults.failures); | ||
expect(lintFactory.getLinter).toHaveBeenCalledWith(filePath, fileContent, mockProgram); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('processLintResults', () => { | ||
it('should complete when no files have an error', () => { | ||
// arrange | ||
const lintResults: any[] = [ | ||
{ | ||
failures: [], | ||
filePath: '/Users/myFileOne.ts' | ||
}, | ||
{ | ||
failures: [], | ||
filePath: '/Users/myFileTwo.ts' | ||
} | ||
]; | ||
|
||
// act | ||
lintUtils.processLintResults(null, lintResults); | ||
|
||
// assert | ||
|
||
}); | ||
|
||
it('should throw an error when one or more file has failures', () => { | ||
// arrange | ||
|
||
spyOn(loggerDiagnostics, loggerDiagnostics.printDiagnostics.name).and.returnValue(null); | ||
spyOn(tsLintLogger, tsLintLogger.runTsLintDiagnostics.name).and.returnValue(null); | ||
const lintResults: any[] = [ | ||
{ | ||
failures: [ | ||
{ } | ||
], | ||
filePath: '/Users/myFileOne.ts' | ||
}, | ||
{ | ||
failures: [ | ||
], | ||
filePath: '/Users/myFileTwo.ts' | ||
} | ||
]; | ||
const knownError = new Error('Should never get here'); | ||
|
||
// act | ||
try { | ||
lintUtils.processLintResults(null, lintResults); | ||
throw knownError; | ||
} catch (ex) { | ||
expect(loggerDiagnostics.printDiagnostics).toHaveBeenCalledTimes(1); | ||
expect(loggerDiagnostics.printDiagnostics).toHaveBeenCalledTimes(1); | ||
expect(ex).not.toEqual(knownError); | ||
} | ||
}); | ||
}); | ||
}); |
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,70 @@ | ||
import * as fs from 'fs'; | ||
import { Program } from 'typescript'; | ||
import { BuildError } from '../util/errors'; | ||
import { getLinter } from './lint-factory'; | ||
import { readFileAsync } from '../util/helpers'; | ||
import { BuildContext } from '../util/interfaces'; | ||
import { Logger } from '../logger/logger'; | ||
import { printDiagnostics, DiagnosticsType } from '../logger/logger-diagnostics'; | ||
import { runTsLintDiagnostics } from '../logger/logger-tslint'; | ||
|
||
export function isMpegFile(file: string) { | ||
var buffer = new Buffer(256); | ||
buffer.fill(0); | ||
|
||
const fd = fs.openSync(file, 'r'); | ||
try { | ||
fs.readSync(fd, buffer, 0, 256, null); | ||
if (buffer.readInt8(0) === 0x47 && buffer.readInt8(188) === 0x47) { | ||
Logger.debug(`tslint: ${file}: ignoring MPEG transport stream`); | ||
return true; | ||
} | ||
} finally { | ||
fs.closeSync(fd); | ||
} | ||
return false; | ||
} | ||
|
||
export function lintFile(context: BuildContext, program: Program, filePath: string): Promise<LintResult> { | ||
return Promise.resolve().then(() => { | ||
if (isMpegFile(filePath)) { | ||
throw new Error(`${filePath} is not a valid TypeScript file`); | ||
} | ||
return readFileAsync(filePath); | ||
}).then((fileContents: string) => { | ||
|
||
const linter = getLinter(filePath, fileContents, program); | ||
const lintResult = linter.lint(); | ||
|
||
return { | ||
filePath: filePath, | ||
failures: lintResult.failures | ||
}; | ||
}); | ||
} | ||
|
||
export function processLintResults(context: BuildContext, lintResults: LintResult[]) { | ||
const filesThatDidntPass: string[] = []; | ||
for (const lintResult of lintResults) { | ||
if (lintResult && lintResult.failures && lintResult.failures.length) { | ||
const diagnostics = runTsLintDiagnostics(context, <any>lintResult.failures); | ||
printDiagnostics(context, DiagnosticsType.TsLint, diagnostics, true, false); | ||
filesThatDidntPass.push(lintResult.filePath); | ||
} | ||
} | ||
if (filesThatDidntPass.length) { | ||
const errorMsg = generateFormattedErrorMsg(filesThatDidntPass); | ||
throw new BuildError(errorMsg); | ||
} | ||
} | ||
|
||
export function generateFormattedErrorMsg(failingFiles: string[]) { | ||
let listOfFilesString = ''; | ||
failingFiles.forEach(file => listOfFilesString = listOfFilesString + file + '\n'); | ||
return `The following files did not pass tslint: \n${listOfFilesString}`; | ||
} | ||
|
||
export interface LintResult { | ||
failures: any[]; | ||
filePath: string; | ||
}; |