This repository has been archived by the owner on Mar 25, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 887
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
291 changed files
with
3,403 additions
and
3,756 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
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,120 @@ | ||
/** | ||
* @license | ||
* Copyright 2016 Palantir Technologies, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import * as colors from "colors"; | ||
import * as diff from "diff"; | ||
import * as fs from "fs"; | ||
import * as glob from "glob"; | ||
import * as path from "path"; | ||
|
||
import * as Linter from "./tslint"; | ||
import * as parse from "./test/parse"; | ||
import {LintError} from "./test/lintError"; | ||
|
||
const FILE_EXTENSION = ".lint"; | ||
|
||
export interface TestResult { | ||
directory: string; | ||
results: { | ||
[fileName: string]: { | ||
errorsFromMarkup: LintError[]; | ||
errorsFromLinter: LintError[]; | ||
markupFromLinter: string; | ||
markupFromMarkup: string; | ||
} | ||
}; | ||
} | ||
|
||
export function runTest(testDirectory: string): TestResult { | ||
const filesToLint = glob.sync(path.join(testDirectory, `**/*${FILE_EXTENSION}`)); | ||
const tslintConfig = JSON.parse(fs.readFileSync(path.join(testDirectory, "tslint.json"), "utf8")); | ||
const results: TestResult = { directory: testDirectory, results: {} }; | ||
|
||
for (const fileToLint of filesToLint) { | ||
const fileBasename = path.basename(fileToLint, FILE_EXTENSION); | ||
const fileText = fs.readFileSync(fileToLint, "utf8"); | ||
const fileTextWithoutMarkup = parse.removeErrorMarkup(fileText); | ||
const errorsFromMarkup = parse.parseErrorsFromMarkup(fileText); | ||
|
||
const lintOptions = { | ||
configuration: tslintConfig, | ||
formatter: "prose", | ||
formattersDirectory: "", | ||
rulesDirectory: "", | ||
}; | ||
const linter = new Linter(fileBasename, fileTextWithoutMarkup, lintOptions); | ||
const errorsFromLinter: LintError[] = linter.lint().failures.map((failure) => { | ||
const startLineAndCharacter = failure.getStartPosition().getLineAndCharacter(); | ||
const endLineAndCharacter = failure.getEndPosition().getLineAndCharacter(); | ||
|
||
return { | ||
endPos: { | ||
col: endLineAndCharacter.character, | ||
line: endLineAndCharacter.line | ||
}, | ||
message: failure.getFailure(), | ||
startPos: { | ||
col: startLineAndCharacter.character, | ||
line: startLineAndCharacter.line | ||
}, | ||
}; | ||
}); | ||
|
||
results.results[fileToLint] = { | ||
errorsFromMarkup, | ||
errorsFromLinter, | ||
markupFromLinter: parse.createMarkupFromErrors(fileTextWithoutMarkup, errorsFromMarkup), | ||
markupFromMarkup: parse.createMarkupFromErrors(fileTextWithoutMarkup, errorsFromLinter), | ||
}; | ||
} | ||
|
||
return results; | ||
} | ||
|
||
export function consoleTestResultHandler(testResult: TestResult): boolean { | ||
let didAllTestsPass = true; | ||
|
||
for (const fileName of Object.keys(testResult.results)) { | ||
const results = testResult.results[fileName]; | ||
process.stdout.write(`${fileName}:`); | ||
|
||
const diffResults = diff.diffLines(results.markupFromMarkup, results.markupFromLinter); | ||
const didTestPass = !diffResults.some((diff) => diff.added || diff.removed); | ||
|
||
if (didTestPass) { | ||
console.log(colors.green(" Passed")); | ||
} else { | ||
console.log(colors.red(" Failed!")); | ||
console.log(colors.green(`Expected (from ${FILE_EXTENSION} file)`)); | ||
console.log(colors.red("Actual (from TSLint)")); | ||
|
||
didAllTestsPass = false; | ||
|
||
for (const diffResult of diffResults) { | ||
let color = colors.gray; | ||
if (diffResult.added) { | ||
color = colors.green; | ||
} else if (diffResult.removed) { | ||
color = colors.red; | ||
} | ||
process.stdout.write(color(diffResult.value)); | ||
} | ||
} | ||
} | ||
|
||
return didAllTestsPass; | ||
} |
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,109 @@ | ||
/* | ||
* Copyright 2016 Palantir Technologies, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import {replicateStr} from "./utils"; | ||
|
||
// Use classes here instead of interfaces because we want runtime type data | ||
export class Line { } | ||
export class CodeLine extends Line { constructor(public contents: string) { super(); } } | ||
export class MessageSubstitutionLine extends Line { constructor(public key: string, public message: string) { super(); } } | ||
|
||
export class ErrorLine extends Line { constructor(public startCol: number) { super(); } } | ||
export class MultilineErrorLine extends ErrorLine { constructor(startCol: number) { super(startCol); } } | ||
export class EndErrorLine extends ErrorLine { | ||
constructor(startCol: number, public endCol: number, public message: string) { super(startCol); } | ||
} | ||
|
||
// example matches (between the quotes): | ||
// " ~~~~~~~~" | ||
const multilineErrorRegex = /^\s*(~+|~nil)$/; | ||
// " ~~~~~~~~~ [some error message]" | ||
const endErrorRegex = /^\s*(~+|~nil)\s*\[(.+)\]\s*$/; | ||
// "[shortcut]: full messages goes here!! " | ||
const messageSubstitutionRegex = /^\[([\w\-\_]+?)]: \s*(.+?)\s*$/; | ||
|
||
export const ZERO_LENGTH_ERROR = "~nil"; | ||
|
||
/** | ||
* Maps a line of text from a .lint file to an appropriate Line object | ||
*/ | ||
export function parseLine(text: string): Line { | ||
const multilineErrorMatch = text.match(multilineErrorRegex); | ||
if (multilineErrorMatch != null) { | ||
const startErrorCol = text.indexOf("~"); | ||
return new MultilineErrorLine(startErrorCol); | ||
} | ||
|
||
const endErrorMatch = text.match(endErrorRegex); | ||
if (endErrorMatch != null) { | ||
const [, squiggles, message] = endErrorMatch; | ||
const startErrorCol = text.indexOf("~"); | ||
const zeroLengthError = (squiggles === ZERO_LENGTH_ERROR); | ||
const endErrorCol = zeroLengthError ? startErrorCol : text.lastIndexOf("~") + 1; | ||
return new EndErrorLine(startErrorCol, endErrorCol, message); | ||
} | ||
|
||
const messageSubstitutionMatch = text.match(messageSubstitutionRegex); | ||
if (messageSubstitutionMatch != null) { | ||
const [, key, message] = messageSubstitutionMatch; | ||
return new MessageSubstitutionLine(key, message); | ||
} | ||
|
||
// line doesn't match any syntax for error markup, so it's a line of code to be linted | ||
return new CodeLine(text); | ||
} | ||
|
||
/** | ||
* Maps a Line object to a matching line of text that could be in a .lint file. | ||
* This is almost the inverse of parseLine. | ||
* If you ran `printLine(parseLine(someText), code)`, the whitespace in the result may be different than in someText | ||
* @param line - A Line object to convert to text | ||
* @param code - If line represents error markup, this is the line of code preceding the markup. | ||
* Otherwise, this parameter is not required. | ||
*/ | ||
export function printLine(line: Line, code?: string): string { | ||
if (line instanceof ErrorLine) { | ||
if (code == null) { | ||
throw new Error("Must supply argument for code parameter when line is an ErrorLine"); | ||
} | ||
|
||
const leadingSpaces = replicateStr(" ", line.startCol); | ||
if (line instanceof MultilineErrorLine) { | ||
// special case for when the line of code is simply a newline. | ||
// use "~nil" to indicate the error continues on that line | ||
if (code.length === 0 && line.startCol === 0) { | ||
return ZERO_LENGTH_ERROR; | ||
} | ||
|
||
const tildes = replicateStr("~", code.length - leadingSpaces.length); | ||
return `${leadingSpaces}${tildes}`; | ||
} else if (line instanceof EndErrorLine) { | ||
let tildes = replicateStr("~", line.endCol - line.startCol); | ||
let endSpaces = replicateStr(" ", code.length - line.endCol); | ||
if (tildes.length === 0) { | ||
tildes = ZERO_LENGTH_ERROR; | ||
// because we add "~nil" we need four less spaces than normal at the end | ||
// always make sure we have at least one space though | ||
endSpaces = endSpaces.substring(0, Math.max(endSpaces.length - 4, 1)); | ||
} | ||
return `${leadingSpaces}${tildes}${endSpaces} [${line.message}]`; | ||
} | ||
} else if (line instanceof MessageSubstitutionLine) { | ||
return `[${line.key}]: ${line.message}`; | ||
} else if (line instanceof CodeLine) { | ||
return line.contents; | ||
} | ||
} |
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,44 @@ | ||
/* | ||
* Copyright 2016 Palantir Technologies, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
export interface PositionInFile { | ||
line: number; | ||
col: number; | ||
} | ||
|
||
export interface LintError { | ||
startPos: PositionInFile; | ||
endPos: PositionInFile; | ||
message: string; | ||
} | ||
|
||
export function errorComparator(err1: LintError, err2: LintError) { | ||
if (err1.startPos.line !== err2.startPos.line) { | ||
return err1.startPos.line - err2.startPos.line; | ||
} else if (err1.startPos.col !== err2.startPos.col) { | ||
return err1.startPos.col - err2.startPos.col; | ||
} else if (err1.endPos.line !== err2.endPos.line) { | ||
return err1.endPos.line - err2.endPos.line; | ||
} else if (err1.endPos.col !== err2.endPos.col) { | ||
return err1.endPos.col - err2.endPos.col; | ||
} else { | ||
return err1.message.localeCompare(err2.message); | ||
} | ||
} | ||
|
||
export function lintSyntaxError(message: string) { | ||
return new Error(`Lint File Syntax Error: ${message}`); | ||
} |
Oops, something went wrong.