Skip to content

Commit

Permalink
Add new file-header rule to enforce headers matched by regexp (pala…
Browse files Browse the repository at this point in the history
…ntir#1441)

- Checks for comments at the very beginning of files
- Ignores #!
- Matches comment contents with header regexp
  • Loading branch information
ScottSWu authored and jkillian committed Aug 9, 2016
1 parent 5bdc21e commit 2cfdd33
Show file tree
Hide file tree
Showing 15 changed files with 184 additions and 0 deletions.
61 changes: 61 additions & 0 deletions src/rules/fileHeaderRule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import * as ts from "typescript";

import * as Lint from "../lint";

export class Rule extends Lint.Rules.AbstractRule {
/* tslint:disable:object-literal-sort-keys */
public static metadata: Lint.IRuleMetadata = {
ruleName: "file-header",
description: "Enforces a certain header comment for all files, matched by a regular expression.",
optionsDescription: "Regular expression to match the header.",
options: {
type: "string",
},
optionExamples: ['"true", "Copyright \\d{4}"'],
type: "style",
};
/* tslint:enable:object-literal-sort-keys */

public static FAILURE_STRING = "missing file header";

public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
const walker = new FileHeaderWalker(sourceFile, this.getOptions());
const options = this.getOptions().ruleArguments;
walker.setRegexp(new RegExp(options[0].toString()));
return this.applyWithWalker(walker);
}
}

class FileHeaderWalker extends Lint.RuleWalker {
// match a single line or multi line comment with leading whitespace
// the wildcard dot does not match new lines - we can use [\s\S] instead
private commentRegexp: RegExp = /^\s*(\/\/(.*?)|\/\*([\s\S]*?)\*\/)/;
private headerRegexp: RegExp;

public setRegexp(headerRegexp: RegExp) {
this.headerRegexp = headerRegexp;
}

public visitSourceFile(node: ts.SourceFile) {
if (this.headerRegexp) {
let text = node.getFullText();
let offset = 0;
// ignore shebang if it exists
if (text.indexOf("#!") === 0) {
offset = text.indexOf("\n") + 1;
text = text.substring(offset);
}
// check for a comment
const match = text.match(this.commentRegexp);
if (!match) {
this.addFailure(this.createFailure(offset, 0, Rule.FAILURE_STRING));
} else {
// either the third or fourth capture group contains the comment contents
const comment = match[2] ? match[2] : match[3];
if (comment.search(this.headerRegexp) < 0) {
this.addFailure(this.createFailure(offset, 0, Rule.FAILURE_STRING));
}
}
}
}
}
1 change: 1 addition & 0 deletions src/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"rules/commentFormatRule.ts",
"rules/curlyRule.ts",
"rules/eoflineRule.ts",
"rules/fileHeaderRule.ts",
"rules/forinRule.ts",
"rules/indentRule.ts",
"rules/interfaceNameRule.ts",
Expand Down
18 changes: 18 additions & 0 deletions test/rules/file-header/bad-shebang/test.ts.lint
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env node

~nil [missing file header]
/*
* Bad header 3
*/

export class A {
public x = 1;

public B() {
return 2;
}
}

/*
* Good header 4
*/
5 changes: 5 additions & 0 deletions test/rules/file-header/bad-shebang/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rules": {
"file-header": [true, "Good header \\d"]
}
}
18 changes: 18 additions & 0 deletions test/rules/file-header/bad-use-strict/test.ts.lint
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"use strict";
~nil [missing file header]

/*
* Bad header 5
*/

export class A {
public x = 1;

public B() {
return 2;
}
}

/*
* Good header 6
*/
5 changes: 5 additions & 0 deletions test/rules/file-header/bad-use-strict/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rules": {
"file-header": [true, "Good header \\d"]
}
}
16 changes: 16 additions & 0 deletions test/rules/file-header/bad/test.ts.lint
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
~nil [missing file header]
* Bad header 1
*/

export class A {
public x = 1;

public B() {
return 2;
}
}

/*
* Good header 2
*/
5 changes: 5 additions & 0 deletions test/rules/file-header/bad/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rules": {
"file-header": [true, "Good header \\d"]
}
}
14 changes: 14 additions & 0 deletions test/rules/file-header/good-shebang/test.ts.lint
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env node


/*
* Good header 2
*/

export class A {
public x = 1;

public B() {
return 2;
}
}
5 changes: 5 additions & 0 deletions test/rules/file-header/good-shebang/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rules": {
"file-header": [true, "Good header \\d"]
}
}
13 changes: 13 additions & 0 deletions test/rules/file-header/good-use-strict/test.ts.lint
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Good header 3
*/

"use strict";

export class A {
public x = 1;

public B() {
return 2;
}
}
5 changes: 5 additions & 0 deletions test/rules/file-header/good-use-strict/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rules": {
"file-header": [true, "Good header \\d"]
}
}
12 changes: 12 additions & 0 deletions test/rules/file-header/good/test.ts.lint
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

/*
* Good header 1
*/

export class A {
public x = 1;

public B() {
return 2;
}
}
5 changes: 5 additions & 0 deletions test/rules/file-header/good/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rules": {
"file-header": [true, "Good header \\d"]
}
}
1 change: 1 addition & 0 deletions test/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
"../src/rules/commentFormatRule.ts",
"../src/rules/curlyRule.ts",
"../src/rules/eoflineRule.ts",
"../src/rules/fileHeaderRule.ts",
"../src/rules/forinRule.ts",
"../src/rules/indentRule.ts",
"../src/rules/interfaceNameRule.ts",
Expand Down

0 comments on commit 2cfdd33

Please sign in to comment.