mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-17 00:41:32 +00:00
Give some love to the linter
This commit is contained in:
56
lib/lint/src/formatters/asFormatter.ts
Normal file
56
lib/lint/src/formatters/asFormatter.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import { AbstractFormatter } from "tslint/lib/language/formatter/abstractFormatter";
|
||||
import { IFormatterMetadata } from "tslint/lib/language/formatter/formatter";
|
||||
import { RuleFailure } from "tslint/lib/language/rule/rule";
|
||||
|
||||
const colorBlue: string = "\u001b[93m";
|
||||
const colorYellow: string = "\u001b[93m";
|
||||
const colorRed: string = "\u001b[91m";
|
||||
const colorReset: string = "\u001b[0m";
|
||||
|
||||
export class Formatter extends AbstractFormatter {
|
||||
|
||||
static metadata: IFormatterMetadata = {
|
||||
formatterName: "as",
|
||||
description: "AssemblyScript's TSLint formatter.",
|
||||
sample: "Similar to ASC's output.",
|
||||
consumer: "human",
|
||||
};
|
||||
|
||||
lastSeverity: string;
|
||||
lastFailure: string;
|
||||
|
||||
format(failures: RuleFailure[]): string {
|
||||
return `${this.mapToMessages(failures).join("\n")}\n`;
|
||||
}
|
||||
|
||||
mapToMessages(failures: RuleFailure[]): string[] {
|
||||
return failures.map((failure: RuleFailure) => {
|
||||
var fileName = failure.getFileName();
|
||||
var failureString = failure.getFailure();
|
||||
var ruleName = failure.getRuleName();
|
||||
var lineAndCharacter = failure.getStartPosition().getLineAndCharacter();
|
||||
var positionTuple = `:${lineAndCharacter.line + 1}:${lineAndCharacter.character + 1}`;
|
||||
if (this.lastSeverity == failure.getRuleSeverity() && this.lastFailure == failureString) {
|
||||
return " in " + fileName + positionTuple;
|
||||
} else {
|
||||
let message = this.lastSeverity ? "\n" : "";
|
||||
switch (this.lastSeverity = failure.getRuleSeverity()) {
|
||||
case "warning": {
|
||||
message += colorYellow + "WARNING:" + colorReset;
|
||||
break;
|
||||
}
|
||||
case "error": {
|
||||
message += colorRed + "ERROR:" + colorReset;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
message += failure.getRuleSeverity();
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.lastFailure = failureString;
|
||||
return message + " " + failureString + " [" + ruleName + "]\n in " + fileName + positionTuple;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
68
lib/lint/src/rules/asTypesRule.ts
Normal file
68
lib/lint/src/rules/asTypesRule.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import * as ts from "typescript";
|
||||
import * as Lint from "tslint";
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
|
||||
static MISSING_TYPE_OR_INITIALIZER = "Missing type or initializer.";
|
||||
static MISSING_RETURN_TYPE = "Missing return type.";
|
||||
|
||||
apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new DiagnosticsWalker(sourceFile, this.getOptions()));
|
||||
}
|
||||
}
|
||||
|
||||
class DiagnosticsWalker extends Lint.RuleWalker {
|
||||
|
||||
visitVariableDeclaration(node: ts.VariableDeclaration) {
|
||||
var list = node.parent;
|
||||
if (list) {
|
||||
let stmt = list.parent;
|
||||
if (stmt && stmt.kind != ts.SyntaxKind.ForOfStatement) {
|
||||
this.checkTypeOrInitializer(node);
|
||||
}
|
||||
}
|
||||
super.visitVariableDeclaration(node);
|
||||
}
|
||||
|
||||
visitPropertyDeclaration(node: ts.PropertyDeclaration) {
|
||||
this.checkTypeOrInitializer(node);
|
||||
super.visitPropertyDeclaration(node);
|
||||
}
|
||||
|
||||
visitParameterDeclaration(node: ts.ParameterDeclaration) {
|
||||
this.checkTypeOrInitializer(node);
|
||||
super.visitParameterDeclaration(node);
|
||||
}
|
||||
|
||||
private checkTypeOrInitializer(node: ts.NamedDeclaration & { type?: ts.TypeNode, initializer?: ts.Expression }) {
|
||||
if (!node.type && !node.initializer) {
|
||||
this.addFailureAtNode(node, Rule.MISSING_TYPE_OR_INITIALIZER);
|
||||
}
|
||||
}
|
||||
|
||||
visitFunctionDeclaration(node: ts.FunctionDeclaration) {
|
||||
this.checkFunctionReturnType(node);
|
||||
super.visitFunctionDeclaration(node);
|
||||
}
|
||||
|
||||
visitArrowFunction(node: ts.ArrowFunction) {
|
||||
this.checkFunctionReturnType(node);
|
||||
super.visitArrowFunction(node);
|
||||
}
|
||||
|
||||
visitMethodDeclaration(node: ts.MethodDeclaration) {
|
||||
this.checkFunctionReturnType(node);
|
||||
super.visitMethodDeclaration(node);
|
||||
}
|
||||
|
||||
visitGetAccessor(node: ts.GetAccessorDeclaration) {
|
||||
this.checkFunctionReturnType(node);
|
||||
super.visitGetAccessor(node);
|
||||
}
|
||||
|
||||
private checkFunctionReturnType(node: ts.FunctionLikeDeclaration) {
|
||||
if (!node.type) {
|
||||
this.addFailureAtNode(node, Rule.MISSING_RETURN_TYPE);
|
||||
}
|
||||
}
|
||||
}
|
55
lib/lint/src/rules/asVariablesRule.ts
Normal file
55
lib/lint/src/rules/asVariablesRule.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import * as ts from "typescript";
|
||||
import * as Lint from "tslint";
|
||||
import {
|
||||
getVariableDeclarationKind,
|
||||
VariableDeclarationKind,
|
||||
isVariableStatement,
|
||||
isBlock,
|
||||
isFunctionScopeBoundary,
|
||||
isSourceFile,
|
||||
isNamespaceDeclaration,
|
||||
isExportSpecifier,
|
||||
isModuleBlock
|
||||
} from "tsutils";
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
|
||||
static TOP_LEVEL_VAR = "Top-level variable should be 'var' (distinct local or global).";
|
||||
static BLOCK_LEVEL_LET = "Block-level variable should be 'let' (shared local).";
|
||||
|
||||
apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new VariablesWalker(sourceFile, this.getOptions()));
|
||||
}
|
||||
}
|
||||
|
||||
class VariablesWalker extends Lint.RuleWalker {
|
||||
|
||||
visitVariableDeclarationList(node: ts.VariableDeclarationList): void {
|
||||
if (isVariableStatement(node.parent)) {
|
||||
if (isBlock(node.parent.parent)) {
|
||||
if (
|
||||
isFunctionScopeBoundary(node.parent.parent.parent) ||
|
||||
isNamespaceDeclaration(node.parent.parent.parent)
|
||||
) {
|
||||
if (getVariableDeclarationKind(node) == VariableDeclarationKind.Let) {
|
||||
this.addFailureAtNode(node, Rule.TOP_LEVEL_VAR);
|
||||
}
|
||||
} else if (getVariableDeclarationKind(node) == VariableDeclarationKind.Var) {
|
||||
this.addFailureAtNode(node, Rule.BLOCK_LEVEL_LET);
|
||||
}
|
||||
} else if (
|
||||
isSourceFile(node.parent.parent) ||
|
||||
isModuleBlock(node.parent.parent)
|
||||
) {
|
||||
if (getVariableDeclarationKind(node) == VariableDeclarationKind.Let) {
|
||||
this.addFailureAtNode(node, Rule.TOP_LEVEL_VAR);
|
||||
}
|
||||
} else if (getVariableDeclarationKind(node) == VariableDeclarationKind.Var) {
|
||||
this.addFailureAtNode(node, Rule.BLOCK_LEVEL_LET);
|
||||
}
|
||||
} else if (getVariableDeclarationKind(node) == VariableDeclarationKind.Var) {
|
||||
this.addFailureAtNode(node, Rule.BLOCK_LEVEL_LET);
|
||||
}
|
||||
super.visitVariableDeclarationList(node);
|
||||
}
|
||||
}
|
39
lib/lint/src/rules/internal/asInternalCaseRule.ts
Normal file
39
lib/lint/src/rules/internal/asInternalCaseRule.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import * as ts from "typescript";
|
||||
import * as Lint from "tslint";
|
||||
import { isSameLine } from "tsutils";
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
|
||||
static NOT_BRACED = "Multi-line case clauses should be braced.";
|
||||
|
||||
apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new CaseWalker(sourceFile, this.getOptions()));
|
||||
}
|
||||
}
|
||||
|
||||
class CaseWalker extends Lint.RuleWalker {
|
||||
|
||||
visitDefaultClause(node: ts.DefaultClause) {
|
||||
this.checkDefaultOrCaseClause(node);
|
||||
super.visitDefaultClause(node);
|
||||
}
|
||||
|
||||
visitCaseClause(node: ts.CaseClause) {
|
||||
this.checkDefaultOrCaseClause(node);
|
||||
super.visitCaseClause(node);
|
||||
}
|
||||
|
||||
private checkDefaultOrCaseClause(node: ts.DefaultClause | ts.CaseClause) {
|
||||
var count = node.statements.length;
|
||||
if (count > 1) {
|
||||
this.addFailureAtNode(node, Rule.NOT_BRACED);
|
||||
} else if (count == 1) {
|
||||
let stmt = node.statements[0];
|
||||
if (stmt.kind != ts.SyntaxKind.Block) {
|
||||
if (!isSameLine(node.getSourceFile(), node.getStart(), stmt.getStart())) {
|
||||
this.addFailureAtNode(node, Rule.NOT_BRACED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
27
lib/lint/src/rules/internal/asInternalDiagnosticsRule.ts
Normal file
27
lib/lint/src/rules/internal/asInternalDiagnosticsRule.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import * as ts from "typescript";
|
||||
import * as Lint from "tslint";
|
||||
import { isSameLine } from "tsutils";
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
|
||||
static NOT_ON_SEPARATE_LINE = "Diagnostic message not on a separate line.";
|
||||
|
||||
apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new DiagnosticsWalker(sourceFile, this.getOptions()));
|
||||
}
|
||||
}
|
||||
|
||||
class DiagnosticsWalker extends Lint.RuleWalker {
|
||||
|
||||
visitPropertyAccessExpression(node: ts.PropertyAccessExpression) {
|
||||
if (node.expression.kind === ts.SyntaxKind.Identifier) {
|
||||
if (
|
||||
(node.expression as ts.Identifier).text == "DiagnosticCode" &&
|
||||
isSameLine(node.getSourceFile(), node.parent.getStart(), node.getStart())
|
||||
) {
|
||||
this.addFailureAtNode(node, Rule.NOT_ON_SEPARATE_LINE);
|
||||
}
|
||||
}
|
||||
super.visitPropertyAccessExpression(node);
|
||||
}
|
||||
}
|
10
lib/lint/src/tsconfig.json
Normal file
10
lib/lint/src/tsconfig.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"lib": ["es6", "es2015.collection"]
|
||||
},
|
||||
"include": [
|
||||
"./**/**.ts"
|
||||
]
|
||||
}
|
Reference in New Issue
Block a user