@magicspace/tslint-rules
Advanced tools
Comparing version 0.1.5 to 0.1.6
@@ -5,5 +5,5 @@ "use strict"; | ||
const tsutils_1 = require("tsutils"); | ||
const TypeScript = require("typescript"); | ||
const typescript_1 = require("typescript"); | ||
const failure_manager_1 = require("../utils/failure-manager"); | ||
const ERROR_MESSAGE_EXPLICIT_RETURN_TYPE = 'This function require a explicit return type.'; | ||
const ERROR_MESSAGE_EXPLICIT_RETURN_TYPE_REQUIRED = 'This function requires explicit return type.'; | ||
class Rule extends tslint_1.Rules.AbstractRule { | ||
@@ -31,22 +31,34 @@ apply(sourceFile) { | ||
let callback = (node) => { | ||
if ((tsutils_1.isArrowFunction(node) || | ||
tsutils_1.isFunctionDeclaration(node) || | ||
tsutils_1.isFunctionExpression(node) || | ||
tsutils_1.isMethodDeclaration(node) || | ||
tsutils_1.isGetAccessorDeclaration(node)) && | ||
!this.hasExplicitType(node)) { | ||
this.failureManager.append({ | ||
node, | ||
message: ERROR_MESSAGE_EXPLICIT_RETURN_TYPE, | ||
}); | ||
if (typescript_1.isArrowFunction(node) || | ||
typescript_1.isFunctionDeclaration(node) || | ||
typescript_1.isFunctionExpression(node) || | ||
typescript_1.isMethodDeclaration(node) || | ||
typescript_1.isGetAccessorDeclaration(node)) { | ||
if (!this.checkReturnType(node)) { | ||
this.failureManager.append({ | ||
node, | ||
message: ERROR_MESSAGE_EXPLICIT_RETURN_TYPE_REQUIRED, | ||
}); | ||
} | ||
} | ||
TypeScript.forEachChild(node, callback); | ||
typescript_1.forEachChild(node, callback); | ||
}; | ||
TypeScript.forEachChild(sourceFile, callback); | ||
typescript_1.forEachChild(sourceFile, callback); | ||
this.failureManager.throw(); | ||
} | ||
hasExplicitType(node) { | ||
if ('type' in node && node.type) { | ||
checkReturnType(node) { | ||
if (node.type) { | ||
return true; | ||
} | ||
if (typescript_1.isFunctionDeclaration(node)) { | ||
// function foo() {} | ||
return false; | ||
} | ||
if (typescript_1.isMethodDeclaration(node) && typescript_1.isClassDeclaration(node.parent)) { | ||
// class Foo {bar() {}} | ||
return false; | ||
} | ||
return this.checkExpressionType(node); | ||
} | ||
checkExpressionType(node) { | ||
let parent = node.parent; | ||
@@ -56,23 +68,30 @@ if (!parent) { | ||
} | ||
if (tsutils_1.isCallExpression(parent)) { | ||
// example: [].map(() => {}); | ||
if ( | ||
// let foo: Foo = () => {}; | ||
typescript_1.isVariableDeclaration(parent) || | ||
// class Foo {bar: Bar = () => {};} | ||
tsutils_1.isPropertyDeclaration(parent)) { | ||
return !!parent.type; | ||
} | ||
if ( | ||
// [].map(() => {}); | ||
typescript_1.isCallExpression(parent) || | ||
// foo.bar = () => {}; | ||
(typescript_1.isBinaryExpression(parent) && | ||
tsutils_1.isAssignmentKind(parent.operatorToken.kind))) { | ||
return true; | ||
} | ||
else if (tsutils_1.isVariableDeclaration(parent)) { | ||
// example: let foo: Foo = () => {}; | ||
return !!parent.type; | ||
if (typescript_1.isArrowFunction(parent)) { | ||
// foo: () => () => {}; | ||
return this.checkReturnType(parent); | ||
} | ||
else if ( | ||
// example: return () => {}; | ||
tsutils_1.isReturnStatement(parent) || | ||
// example: let foo: Foo = {bar() {}}; | ||
tsutils_1.isObjectLiteralExpression(parent) || | ||
TypeScript.isObjectLiteralElement(parent)) { | ||
return this.hasExplicitType(parent); | ||
if (typescript_1.isReturnStatement(parent)) { | ||
// return () => {}; | ||
let block = parent.parent; | ||
let functionLike = block.parent; | ||
return this.checkReturnType(functionLike); | ||
} | ||
else { | ||
return false; | ||
} | ||
return this.checkExpressionType(parent); | ||
} | ||
} | ||
//# sourceMappingURL=explicitReturnTypeRule.js.map |
@@ -18,2 +18,5 @@ "use strict"; | ||
this.parsedOptions = options.ruleArguments[0]; | ||
if (!this.parsedOptions || !this.parsedOptions.baseUrl) { | ||
throw new Error('Option baseUrl is required'); | ||
} | ||
} | ||
@@ -126,3 +129,3 @@ apply(sourceFile) { | ||
let rootPathCache; | ||
return function inner(currentPath, baseUrlDirSearchName) { | ||
return function inner(currentPath, baseUrlDirSearchName = 'tsconfig.json') { | ||
if (rootPathCache) { | ||
@@ -129,0 +132,0 @@ return rootPathCache; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const FS = require("fs"); | ||
const Path = require("path"); | ||
const _ = require("lodash"); | ||
const tslint_1 = require("tslint"); | ||
const tsutils_1 = require("tsutils"); | ||
const failure_manager_1 = require("../utils/failure-manager"); | ||
const path_1 = require("../utils/path"); | ||
const RELATIVE_PATH = /^(?:\.{1,2}[\\/])+/; | ||
const DIRECTORY_MODULE_PATH = /^\.{1,2}(?:[\\/]\.{2})*[\\/]?$/; | ||
const ERROR_MESSAGE_BANNED_PARENT_IMPORT = 'Importing from parent directory is not allowed.'; | ||
@@ -32,13 +29,6 @@ class Rule extends tslint_1.Rules.AbstractRule { | ||
this.importExpressions = []; | ||
this.failureManager = new failure_manager_1.FailureManager(this); | ||
} | ||
walk(sourceFile) { | ||
for (let statement of sourceFile.statements) { | ||
if (tsutils_1.isImportDeclaration(statement)) { | ||
let specifier = statement.moduleSpecifier; | ||
if (!RELATIVE_PATH.test(path_1.removeQuotes(specifier.getText()))) { | ||
continue; | ||
} | ||
this.importExpressions.push(specifier); | ||
} | ||
for (let expression of tsutils_1.findImports(sourceFile, 3 /* AllStaticImports */)) { | ||
this.importExpressions.push(expression); | ||
} | ||
@@ -49,43 +39,15 @@ this.validate(); | ||
let importExpressions = this.importExpressions; | ||
let sourceFileDirName = Path.dirname(this.sourceFile.fileName); | ||
// 从上至下寻找模块 | ||
let findSameModule = (currentDirName, pathParts, moduleName) => { | ||
let part = pathParts.shift(); | ||
if (!pathParts.length) { | ||
return; | ||
} | ||
currentDirName = currentDirName | ||
? Path.join(currentDirName, part) | ||
: Path.join(sourceFileDirName, part); | ||
let files = FS.readdirSync(currentDirName) | ||
.filter(file => { | ||
return FS.statSync(Path.join(currentDirName, file)).isFile(); | ||
}) | ||
.map(file => path_1.removeModuleFileExtension(file)); | ||
if (_.includes(files, moduleName)) { | ||
return Path.relative(sourceFileDirName, currentDirName); | ||
} | ||
else { | ||
return findSameModule(currentDirName, pathParts, moduleName); | ||
} | ||
}; | ||
let sourceDirName = Path.dirname(this.sourceFile.fileName); | ||
for (let expression of importExpressions) { | ||
let text = path_1.removeQuotes(expression.getText()); | ||
let importPath = Path.isAbsolute(text) | ||
? Path.relative(sourceFileDirName, text) | ||
: text; | ||
let moduleName = Path.basename(importPath); | ||
let modulePath = findSameModule(undefined, Path.dirname(importPath).split(Path.sep), path_1.removeModuleFileExtension(moduleName)); | ||
if (modulePath) { | ||
let node = expression.parent; | ||
this.failureManager.append({ | ||
node, | ||
message: ERROR_MESSAGE_BANNED_PARENT_IMPORT, | ||
fixer: new tslint_1.Replacement(expression.getStart(), expression.getEnd(), `'${Path.join(modulePath, moduleName)}'`), | ||
}); | ||
let modulePath = path_1.removeQuotes(expression.getText()); | ||
modulePath = Path.isAbsolute(modulePath) | ||
? Path.relative(sourceDirName, modulePath) | ||
: (modulePath = Path.relative(sourceDirName, Path.join(sourceDirName, modulePath))); | ||
if (!DIRECTORY_MODULE_PATH.test(modulePath) && modulePath !== '') { | ||
continue; | ||
} | ||
this.addFailureAtNode(expression.parent, ERROR_MESSAGE_BANNED_PARENT_IMPORT); | ||
} | ||
this.failureManager.throw(); | ||
} | ||
} | ||
//# sourceMappingURL=noParentImportRule.js.map |
@@ -6,5 +6,7 @@ "use strict"; | ||
const test_1 = require("tslint/lib/test"); | ||
let pattern = process.argv[2]; | ||
console.info('Testing Lint Rules:'); | ||
let testDirs = glob | ||
.sync('../../test/rules/**/tslint.json', { cwd: __dirname, absolute: true }) | ||
.filter(path => !pattern || path.includes(pattern)) | ||
.map(path => Path.dirname(path)); | ||
@@ -11,0 +13,0 @@ let allPassed = true; |
{ | ||
"name": "@magicspace/tslint-rules", | ||
"version": "0.1.5", | ||
"version": "0.1.6", | ||
"description": "Custom TSLint rules for MagicSpace.", | ||
@@ -5,0 +5,0 @@ "repository": "https://github.com/makeflow/magicspace.git", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
35622
915
11
1