Skip to content
This repository has been archived by the owner on Mar 25, 2021. It is now read-only.

Commit

Permalink
Merge branch 'master' into next
Browse files Browse the repository at this point in the history
  • Loading branch information
Jason Killian committed Apr 21, 2016
2 parents af6bfdd + f6b64cb commit ca43e9b
Show file tree
Hide file tree
Showing 43 changed files with 511 additions and 99 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
Change Log
===

v3.7.4
---
* Stable release containing changes from the last dev release (v3.7.0-dev.5)

v3.7.0-dev.5
---
* [bugfix] Allow JS directives in namespaces (#1115)
Expand Down
3 changes: 0 additions & 3 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,6 @@ module.exports = function (grunt) {
},

tslint: {
options: {
configuration: grunt.file.readJSON("tslint.json")
},
src: [
"src/*.ts",
"src/formatters/**/*.ts",
Expand Down
29 changes: 20 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,17 @@ usage: `tslint [options] [file ...]`
Options:

```
-c, --config configuration file
-o, --out output file
-r, --rules-dir rules directory
-s, --formatters-dir formatters directory
-t, --format output format (prose, json) [default: "prose"]
-c, --config configuration file
--force return status code 0 even if there are lint errors
-h, --help display detailed help
-i, --init generate a tslint.json config file in the current working directory
-o, --out output file
-r, --rules-dir rules directory
-s, --formatters-dir formatters directory
-e, --exclude exclude globs from path expansion
-t, --format output format (prose, json, verbose, pmd, msbuild, checkstyle) [default: "prose"]
--test test that tslint produces the correct output for the specified directory
-v, --version current version
```

By default, configuration is loaded from `tslint.json`, if it exists in the current path, or the user's home directory, in that order.
Expand Down Expand Up @@ -100,7 +106,7 @@ tslint accepts the following command-line options:
This option can be supplied multiple times if you need multiple
globs to indicate which files to exclude.
-n, --force:
--force:
Return status code 0 even if there are any lint errors.
Useful while running as npm script.
Expand Down Expand Up @@ -130,7 +136,8 @@ tslint accepts the following command-line options:
The formatter to use to format the results of the linter before
outputting it to stdout or the file passed in --out. The core
formatters are prose (human readable), json (machine readable)
and verbose. prose is the default if this option is not used. Additonal
and verbose. prose is the default if this option is not used.
Other built-in options include pmd, msbuild, and checkstyle. Additonal
formatters can be added and used if the --formatters-dir option is set.
--test:
Expand Down Expand Up @@ -194,7 +201,7 @@ A sample configuration file with all options is available [here](https://github.
* `"check-uppercase"` enforces the rule that the first non-whitespace character of a comment must be uppercase, if applicable.
* `curly` enforces braces for `if`/`for`/`do`/`while` statements.
* `eofline` enforces the file to end with a newline.
* `forin` enforces a `for ... in` statement to be filtered with an `if` statement.*
* `forin` enforces a `for ... in` statement to be filtered with an `if` statement.
* `indent` enforces indentation with tabs or spaces. Rule options (one is required):
* `"tabs"` enforces consistent tabs.
* `"spaces"` enforces consistent spaces.
Expand Down Expand Up @@ -234,7 +241,9 @@ A sample configuration file with all options is available [here](https://github.
* `no-eval` disallows `eval` function invocations.
* `no-inferrable-types` disallows explicit type declarations for variables or parameters initialized to a number, string, or boolean.
* `no-internal-module` disallows internal `module` (use `namespace` instead).
* `no-null-keyword` disallows use of the `null` keyword literal
* `no-invalid-this` disallows using the `this` keyword outside of classes.
* `no-null-keyword` disallows use of the `null` keyword literal.
* `no-reference` disallows `/// <reference path=>` imports (use ES6-style imports instead).
* `no-require-imports` disallows invocation of `require()` (use ES6-style imports instead).
* `no-shadowed-variable` disallows shadowed variable declarations.
* `no-string-literal` disallows object access via string literals.
Expand Down Expand Up @@ -292,13 +301,15 @@ A sample configuration file with all options is available [here](https://github.
* `"parameter"` checks function parameters.
* `"property-declaration"` checks object property declarations.
* `"variable-declaration"` checks variable declaration.
* `use-isnan` enforces that you use the isNaN() function to check for NaN references instead of a comparison to the NaN constant.
* `use-strict` enforces ECMAScript 5's strict mode.
* `check-module` checks that all top-level modules are using strict mode.
* `check-function` checks that all top-level functions are using strict mode.
* `variable-name` checks variables names for various errors. Rule options:
* `"check-format"`: allows only camelCased or UPPER_CASED variable names
* `"allow-leading-underscore"` allows underscores at the beginning.
* `"allow-trailing-underscore"` allows underscores at the end.
* `"allow-pascal-case"` allows PascalCase in addition to camelCase.
* `"ban-keywords"`: disallows the use of certain TypeScript keywords (`any`, `Number`, `number`, `String`, `string`, `Boolean`, `boolean`, `undefined`) as variable or parameter names.
* `whitespace` enforces spacing whitespace. Rule options:
* `"check-branch"` checks branching statements (`if`/`else`/`for`/`while`) are followed by whitespace.
Expand Down
50 changes: 0 additions & 50 deletions docs/cli-options-verbose.txt

This file was deleted.

19 changes: 16 additions & 3 deletions docs/sample.tslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@
"arguments",
"statements"
],
"ban": false,
"ban": [
true,
[ "_", "forEach" ],
[ "_", "each" ],
[ "$", "each" ],
[ "angular", "forEach" ]
],
"class-name": true,
"comment-format": [
true,
Expand All @@ -20,7 +26,10 @@
true,
"spaces"
],
"interface-name": true,
"interface-name": [
true,
"always-prefix"
],
"jsdoc-format": true,
"label-position": true,
"label-undefined": true,
Expand Down Expand Up @@ -58,7 +67,9 @@
"no-eval": true,
"no-inferrable-types": false,
"no-internal-module": true,
"no-invalid-this": true,
"no-null-keyword": true,
"no-reference": true,
"no-require-imports": true,
"no-shadowed-variable": true,
"no-string-literal": true,
Expand Down Expand Up @@ -96,7 +107,8 @@
],
"triple-equals": [
true,
"allow-null-check"
"allow-null-check",
"allow-undefined-check"
],
"typedef": [
true,
Expand Down Expand Up @@ -124,6 +136,7 @@
"variable-declaration": "space"
}
],
"use-isnan": true,
"use-strict": [
true,
"check-module",
Expand Down
28 changes: 19 additions & 9 deletions src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import * as path from "path";
import * as findup from "findup-sync";
import * as pathIsAbsolute from "path-is-absolute";

import {arrayify, objectify} from "./utils";
import {arrayify, objectify, stripComments} from "./utils";

export interface IConfigurationFile {
extends?: string | string[];
Expand All @@ -43,13 +43,15 @@ export const DEFAULT_CONFIG = {
"quotemark": [true, "double"],
"semicolon": [true, "always"],
"triple-equals": [true, "allow-null-check"],
"typedef-whitespace": [true, {
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace",
}, ],
"typedef-whitespace": [
true, {
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace",
},
],
"variable-name": [true, "ban-keywords"],
"whitespace": [true,
"check-branch",
Expand Down Expand Up @@ -136,7 +138,15 @@ export function loadConfigurationFromPath(configFilePath: string): IConfiguratio
return require(configFilePath).tslintConfig;
} else {
const resolvedConfigFilePath = resolveConfigurationPath(configFilePath);
let configFile: IConfigurationFile = require(resolvedConfigFilePath);
let configFile: IConfigurationFile;
if (path.extname(resolvedConfigFilePath) === ".json") {
const fileContent = stripComments(fs.readFileSync(resolvedConfigFilePath).toString());
configFile = JSON.parse(fileContent);
} else {
configFile = require(resolvedConfigFilePath);
delete require.cache[resolvedConfigFilePath];
}

const configFileDir = path.dirname(resolvedConfigFilePath);

configFile.rulesDirectory = getRulesDirectories(configFile.rulesDirectory, configFileDir);
Expand Down
7 changes: 4 additions & 3 deletions src/enableDisableRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ export class EnableDisableRulesWalker extends SkippableTokenAwareRuleWalker {
return;
}

if (scanner.getToken() === ts.SyntaxKind.MultiLineCommentTrivia) {
if (scanner.getToken() === ts.SyntaxKind.MultiLineCommentTrivia ||
scanner.getToken() === ts.SyntaxKind.SingleLineCommentTrivia) {
const commentText = scanner.getTokenText();
const startPosition = scanner.getTokenPos();
this.handlePossibleTslintSwitch(commentText, startPosition);
Expand All @@ -45,8 +46,8 @@ export class EnableDisableRulesWalker extends SkippableTokenAwareRuleWalker {
}

private handlePossibleTslintSwitch(commentText: string, startingPosition: number) {
// regex is: start of string followed by "/*" followed by any amount of whitespace followed by "tslint:"
if (commentText.match(/^\/\*\s*tslint:/)) {
// regex is: start of string followed by "/*" or "//" followed by any amount of whitespace followed by "tslint:"
if (commentText.match(/^(\/\*|\/\/)\s*tslint:/)) {
const commentTextParts = commentText.split(":");
// regex is: start of string followed by either "enable" or "disable"
// followed by either whitespace or end of string
Expand Down
33 changes: 33 additions & 0 deletions src/formatters/checkstyleFormatter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {AbstractFormatter} from "../language/formatter/abstractFormatter";
import {RuleFailure} from "../language/rule/rule";

export class Formatter extends AbstractFormatter {
public format(failures: RuleFailure[]): string {
let output = '<?xml version="1.0" encoding="utf-8"?><checkstyle version="4.3">';

if (failures.length) {
output += `<file name="${this.escapeXml(failures[0].getFileName())}">`;
for (let failure of failures) {
output += `<error line="${failure.getStartPosition().getLineAndCharacter().line + 1}" `;
output += `column="${failure.getStartPosition().getLineAndCharacter().character + 1}" `;
output += `severity="warning" `;
output += `message="${this.escapeXml(failure.getFailure())}" `;
// checkstyle parser wants "source" to have structure like <anything>dot<category>dot<type>
output += `source="failure.tslint.${this.escapeXml(failure.getRuleName())}" />`;
}
output += "</file>";
}

output += "</checkstyle>";
return output;
}

private escapeXml(str: string): string {
return str
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/'/g, "&#39;")
.replace(/"/g, "&quot;");
}
}
7 changes: 4 additions & 3 deletions src/language/walker/scopeAwareRuleWalker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ export abstract class ScopeAwareRuleWalker<T> extends RuleWalker {
super(sourceFile, options);

// initialize stack with global scope
this.scopeStack = [this.createScope()];
this.scopeStack = [this.createScope(sourceFile)];
}

public abstract createScope(): T;
public abstract createScope(node: ts.Node): T;

public getCurrentScope(): T {
return this.scopeStack[this.scopeStack.length - 1];
Expand Down Expand Up @@ -57,7 +57,7 @@ export abstract class ScopeAwareRuleWalker<T> extends RuleWalker {
const isNewScope = this.isScopeBoundary(node);

if (isNewScope) {
this.scopeStack.push(this.createScope());
this.scopeStack.push(this.createScope(node));
}

this.onScopeStart();
Expand All @@ -80,6 +80,7 @@ export abstract class ScopeAwareRuleWalker<T> extends RuleWalker {
|| node.kind === ts.SyntaxKind.ArrowFunction
|| node.kind === ts.SyntaxKind.ParenthesizedExpression
|| node.kind === ts.SyntaxKind.ClassDeclaration
|| node.kind === ts.SyntaxKind.ClassExpression
|| node.kind === ts.SyntaxKind.InterfaceDeclaration
|| node.kind === ts.SyntaxKind.GetAccessor
|| node.kind === ts.SyntaxKind.SetAccessor;
Expand Down
51 changes: 51 additions & 0 deletions src/rules/noInvalidThisRule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* @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 ts from "typescript";
import * as Lint from "../lint";

export class Rule extends Lint.Rules.AbstractRule {
public static FAILURE_STRING = "the \"this\" keyword is disallowed outside of a class body" ;

public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(new NoInvalidThisWalker(sourceFile, this.getOptions()));
}
}

class NoInvalidThisWalker extends Lint.ScopeAwareRuleWalker<{inClass: boolean}> {
public createScope(node: ts.Node): { inClass: boolean } {
const isClassScope = node.kind === ts.SyntaxKind.ClassDeclaration || node.kind === ts.SyntaxKind.ClassExpression;

return {
inClass: isClassScope,
};
}

protected validateThisKeyword(node: ts.Node) {
if (!this.getAllScopes().some((scope) => scope.inClass)) {
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.FAILURE_STRING));
}
}

public visitNode(node: ts.Node) {
if (node.kind === ts.SyntaxKind.ThisKeyword) {
this.validateThisKeyword(node);
}

super.visitNode(node);
}
}
Loading

0 comments on commit ca43e9b

Please sign in to comment.