This repository has been archived by the owner on Nov 16, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 86
/
noPaddingRule.ts
85 lines (72 loc) · 2.74 KB
/
noPaddingRule.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import * as Lint from "tslint";
import * as ts from "typescript";
import { failure } from "../util";
export class Rule extends Lint.Rules.AbstractRule {
static metadata: Lint.IRuleMetadata = {
ruleName: "no-padding",
description: "Forbids a blank line after `(` / `[` / `{`, or before `)` / `]` / `}`.",
optionsDescription: "Not configurable.",
options: null,
type: "style",
typescriptOnly: true,
};
static FAILURE_STRING(kind: "before" | "after", token: ts.SyntaxKind) {
return failure(
Rule.metadata.ruleName,
`Don't leave a blank line ${kind} '${ts.tokenToString(token)}'.`);
}
apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, walk);
}
}
function walk(ctx: Lint.WalkContext<void>): void {
const { sourceFile } = ctx;
function fail(kind: "before" | "after", child: ts.Node): void {
ctx.addFailureAtNode(child, Rule.FAILURE_STRING(kind, child.kind));
}
sourceFile.forEachChild(function cb(node) {
const children = node.getChildren();
for (let i = 0; i < children.length; i++) {
const child = children[i];
switch (child.kind) {
case ts.SyntaxKind.OpenParenToken:
case ts.SyntaxKind.OpenBracketToken:
case ts.SyntaxKind.OpenBraceToken:
if (i < children.length - 1 && blankLineInBetween(child.getEnd(), children[i + 1].getStart())) {
fail("after", child);
}
break;
case ts.SyntaxKind.CloseParenToken:
case ts.SyntaxKind.CloseBracketToken:
case ts.SyntaxKind.CloseBraceToken:
if (i > 0 && blankLineInBetween(child.getStart() - 1, children[i - 1].getEnd() - 1)) {
fail("before", child);
}
break;
default:
cb(child);
}
}
});
// Looks for two newlines (with nothing else in between besides whitespace)
function blankLineInBetween(start: number, end: number): boolean {
const step = start < end ? 1 : -1;
let seenLine = false;
for (let i = start; i !== end; i += step) {
switch (sourceFile.text[i]) {
case "\n":
if (seenLine) {
return true;
} else {
seenLine = true;
}
break;
case " ": case "\t": case "\r":
break;
default:
return false;
}
}
return false;
}
}