@fimbul/mimir
Advanced tools
Comparing version 0.23.0-dev.20201218 to 0.23.0-dev.20210107
{ | ||
"name": "@fimbul/mimir", | ||
"version": "0.23.0-dev.20201218", | ||
"version": "0.23.0-dev.20210107", | ||
"description": "Core rules of the Fimbullinter project", | ||
@@ -33,3 +33,3 @@ "main": "recommended.yaml", | ||
"tslib": "^2.0.0", | ||
"tsutils": "^3.16.0" | ||
"tsutils": "^3.19.0" | ||
}, | ||
@@ -36,0 +36,0 @@ "peerDependencies": { |
@@ -40,3 +40,3 @@ # Mímir | ||
[`no-duplicate-spread-property`](docs/no-duplicate-spread-property.md) | :mag: Detects properties in object literals with object spread that are always overridden. | TSLint has no such rule. | ||
[`no-fallthrough`](docs/no-fallthrough.md) | Prevents unintentional fallthough in `switch` statements from one case to another. | Allows more comment variants such as `fallthrough` or `fall through`. | ||
[`no-fallthrough`](docs/no-fallthrough.md) | :mag_right: Prevents unintentional fallthough in `switch` statements from one case to another. | Allows more comment variants such as `fallthrough` or `fall through`. | ||
[`no-invalid-assertion`](docs/no-invalid-assertion.md) | :mag: Disallows asserting a literal type to a different literal type of the same widened type, e.g. `'foo' as 'bar'`.| TSLint has no similar rule. | ||
@@ -50,3 +50,3 @@ [`no-misused-generics`](docs/no-misused-generics.md) | Detects generic type parameters that cannot be inferred from the functions parameters. It also detects generics that don't enforce any constraint between types. | There's no similar TSLint rule. | ||
[`no-uninferred-type-parameter`](docs/no-uninferred-type-parameter.md) | :mag: Detects type parameters that are inferred as `{}` because the compiler cannot infer a type. | Really checks every type parameter of function, method and constructor calls. Correctly handles type parameters from JSDoc comments. Recognises type parameter defaults on all merged declarations. | ||
[`no-unreachable-code`](docs/no-unreachable-code.md) | Disallows statements that will never be executed. | TSLint removed their `no-unreachable` rule in v4.0.0. | ||
[`no-unreachable-code`](docs/no-unreachable-code.md) | :mag_right: Disallows statements that will never be executed. | TSLint removed their `no-unreachable` rule in v4.0.0. | ||
[`no-unsafe-finally`](docs/no-unsafe-finally.md) | Disallows control flow statements `return`, `throw`, `break` and `continue` inside the `finally` block of a try statement. | Performance! | ||
@@ -53,0 +53,0 @@ [`no-unstable-api-use`](docs/no-unstable-api-use.md) | :mag: Disallows uses of deprecated or experimental APIs. | This rule checks element accesses (`foo[bar]`), JSX elements, chained function calls (`getFn()()`) in addition to what TSLint's `deprecation` rule does and has more useful error reporting. |
@@ -79,3 +79,3 @@ "use strict"; | ||
else if (t.flags & ts.TypeFlags.BooleanLiteral) { | ||
result.add(formatPrimitive(prefixFn(t.intrinsicName === 'true'))); | ||
result.add(formatPrimitive(prefixFn(tsutils_1.isBooleanLiteralType(t, true)))); | ||
} | ||
@@ -158,3 +158,3 @@ else if (t.flags & ts.TypeFlags.Undefined) { | ||
return isBigInt(v) | ||
? utils_1.formatPseudoBigInt(v) | ||
? tsutils_1.formatPseudoBigInt(v) | ||
: typeof v === 'string' | ||
@@ -161,0 +161,0 @@ ? `"${v}"` |
@@ -11,2 +11,3 @@ "use strict"; | ||
apply() { | ||
var _a; | ||
for (const { caseBlock: { clauses } } of utils_1.switchStatements(this.context)) { | ||
@@ -16,3 +17,3 @@ for (let i = 1; i < clauses.length; ++i) { | ||
!ts.forEachLeadingCommentRange(this.sourceFile.text, clauses[i].pos, isFallthroughComment, this.sourceFile.text) && | ||
!tsutils_1.endsControlFlow(clauses[i - 1])) { | ||
!tsutils_1.endsControlFlow(clauses[i - 1], (_a = this.program) === null || _a === void 0 ? void 0 : _a.getTypeChecker())) { | ||
const kind = clauses[i].kind === ts.SyntaxKind.CaseClause ? 'case' : 'default'; | ||
@@ -19,0 +20,0 @@ const start = clauses[i].getStart(this.sourceFile); |
@@ -8,3 +8,2 @@ "use strict"; | ||
const ts = require("typescript"); | ||
const utils_1 = require("../utils"); | ||
let Rule = class Rule extends ymir_1.TypedRule { | ||
@@ -102,7 +101,7 @@ apply() { | ||
if (!seenBigint) | ||
result.bigint = append(result.bigint, utils_1.formatPseudoBigInt(t.value)); | ||
result.bigint = append(result.bigint, tsutils_1.formatPseudoBigInt(t.value)); | ||
} | ||
else if (t.flags & ts.TypeFlags.BooleanLiteral) { | ||
if (!seenBoolean) { | ||
const current = t.intrinsicName === 'true'; | ||
const current = tsutils_1.isBooleanLiteralType(t, true); | ||
if (result.boolean === undefined) { | ||
@@ -109,0 +108,0 @@ result.boolean = current; |
@@ -25,3 +25,3 @@ "use strict"; | ||
const flags = getModifierFlagsOfSymbol(symbol); | ||
if (lhs !== undefined && lhs.kind === ts.SyntaxKind.ThisKeyword && | ||
if ((lhs === null || lhs === void 0 ? void 0 : lhs.kind) === ts.SyntaxKind.ThisKeyword && | ||
flags & ts.ModifierFlags.Abstract && hasNonMethodDeclaration(symbol)) { | ||
@@ -32,3 +32,3 @@ const enclosingClass = getEnclosingClassOfAbstractPropertyAccess(errorNode.parent); | ||
} | ||
if (lhs !== undefined && lhs.kind === ts.SyntaxKind.SuperKeyword) { | ||
if ((lhs === null || lhs === void 0 ? void 0 : lhs.kind) === ts.SyntaxKind.SuperKeyword) { | ||
if (hasNonMethodDeclaration(symbol)) | ||
@@ -62,3 +62,3 @@ return this.addFindingAtNode(errorNode, "Only public and protected methods of the base class are accessible via the 'super' keyword."); | ||
const thisParameter = getThisParameterFromContext(node); | ||
if (thisParameter === undefined || thisParameter.type === undefined) | ||
if ((thisParameter === null || thisParameter === void 0 ? void 0 : thisParameter.type) === undefined) | ||
return; | ||
@@ -84,3 +84,3 @@ let thisType = this.checker.getTypeFromTypeNode(thisParameter.type); | ||
case ts.SyntaxKind.ClassExpression: { | ||
const declaredType = tsutils_1.getConstructorTypeOfClassLikeDeclaration(node, this.checker); | ||
const declaredType = tsutils_1.getInstanceTypeOfClassLikeDeclaration(node, this.checker); | ||
if (baseClasses.every((baseClass) => hasBase(declaredType, baseClass, typeContainsDeclaration))) | ||
@@ -97,3 +97,3 @@ return declaredType; | ||
printClass(declaration) { | ||
return this.checker.typeToString(tsutils_1.getConstructorTypeOfClassLikeDeclaration(declaration, this.checker)); | ||
return this.checker.typeToString(tsutils_1.getInstanceTypeOfClassLikeDeclaration(declaration, this.checker)); | ||
} | ||
@@ -100,0 +100,0 @@ }; |
@@ -8,2 +8,3 @@ import { AbstractRule } from '@fimbul/ymir'; | ||
private report; | ||
private nextStatementIsUnreachable; | ||
} |
@@ -27,3 +27,3 @@ "use strict"; | ||
checkBlock(node) { | ||
let i = node.statements.findIndex(nextStatementIsUnreachable); | ||
let i = node.statements.findIndex(this.nextStatementIsUnreachable, this); | ||
if (i === -1 || i === node.statements.length - 1) | ||
@@ -65,2 +65,22 @@ return; | ||
} | ||
nextStatementIsUnreachable(statement) { | ||
var _a; | ||
if (tsutils_1.endsControlFlow(statement, (_a = this.program) === null || _a === void 0 ? void 0 : _a.getTypeChecker())) | ||
return true; | ||
const labels = []; | ||
while (tsutils_1.isLabeledStatement(statement)) { | ||
labels.push(statement.label.text); | ||
statement = statement.statement; | ||
} | ||
switch (statement.kind) { | ||
case ts.SyntaxKind.ForStatement: | ||
case ts.SyntaxKind.WhileStatement: | ||
case ts.SyntaxKind.DoStatement: | ||
// statements after loops, that go on forever without breaking, are never executed | ||
return getConstantIterationCondition(statement) === true && | ||
!tsutils_1.getControlFlowEnd(statement.statement).statements.some((jump) => jump.kind === ts.SyntaxKind.BreakStatement && | ||
(jump.label === undefined || labels.includes(jump.label.text))); | ||
} | ||
return false; | ||
} | ||
}; | ||
@@ -71,20 +91,2 @@ Rule = tslib_1.__decorate([ | ||
exports.Rule = Rule; | ||
function nextStatementIsUnreachable(statement) { | ||
if (tsutils_1.endsControlFlow(statement)) | ||
return true; | ||
const labels = []; | ||
while (tsutils_1.isLabeledStatement(statement)) { | ||
labels.push(statement.label.text); | ||
statement = statement.statement; | ||
} | ||
switch (statement.kind) { | ||
case ts.SyntaxKind.ForStatement: | ||
case ts.SyntaxKind.WhileStatement: | ||
case ts.SyntaxKind.DoStatement: | ||
// statements after loops, that go on forever without breaking, are never executed | ||
return getConstantIterationCondition(statement) === true && | ||
!tsutils_1.getControlFlowEnd(statement.statement).statements.some((jump) => jump.kind === ts.SyntaxKind.BreakStatement && (jump.label === undefined || labels.includes(jump.label.text))); | ||
} | ||
return false; | ||
} | ||
function isExecutableStatement(node) { | ||
@@ -91,0 +93,0 @@ switch (node.kind) { |
@@ -63,3 +63,3 @@ "use strict"; | ||
const flags = getNullableFlags(this.checker.getBaseConstraintOfType(originalType) || originalType, ts.isOptionalChain(node) | ||
? (t) => isOptionalChainingMarkerType(this.checker, t) ? 0 : t.flags | ||
? (t) => tsutils_1.isOptionalChainingUndefinedMarkerType(this.checker, t) ? 0 : t.flags | ||
: undefined); | ||
@@ -214,5 +214,2 @@ if (flags !== 0) { // type is nullable | ||
} | ||
function isOptionalChainingMarkerType(checker, t) { | ||
return tsutils_1.isTypeFlagSet(t, ts.TypeFlags.Undefined) && checker.getNullableType(t.getNonNullableType(), ts.TypeFlags.Undefined) !== t; | ||
} | ||
//# sourceMappingURL=no-useless-assertion.js.map |
@@ -8,3 +8,2 @@ "use strict"; | ||
const tsutils_1 = require("tsutils"); | ||
const utils_1 = require("../utils"); | ||
const primitiveFlags = ts.TypeFlags.BigIntLike | ts.TypeFlags.BooleanLike | ts.TypeFlags.NumberLike | ts.TypeFlags.StringLike | | ||
@@ -195,3 +194,3 @@ ts.TypeFlags.ESSymbolLike | ts.TypeFlags.Undefined | ts.TypeFlags.Void; | ||
if (tsutils_1.isLiteralType(t)) | ||
return typeof t.value === 'object' ? utils_1.formatPseudoBigInt(t.value) : String(t.value); | ||
return typeof t.value === 'object' ? tsutils_1.formatPseudoBigInt(t.value) : String(t.value); | ||
if (t.flags & ts.TypeFlags.BooleanLiteral) | ||
@@ -287,3 +286,3 @@ return t.intrinsicName; | ||
return; | ||
const names = tsutils_1.getLateBoundPropertyNames(name, this.checker); // TODO lateBoundPropertyNames should also be aware of index signatures | ||
const names = tsutils_1.getLateBoundPropertyNames(name, this.checker); | ||
if (!names.known) | ||
@@ -290,0 +289,0 @@ return; |
@@ -11,4 +11,8 @@ "use strict"; | ||
for (const node of this.context.getFlatAst()) | ||
if (tsutils_1.isExpressionStatement(node) && tsutils_1.isCallExpression(node.expression) && this.returnsNever(node.expression)) | ||
this.addFindingAtNode(node, `This call never returns. Consider ${isReturnAllowed(node) ? 'return' : 'throw'}ing the result for better control flow analysis and type inference.`); | ||
if (tsutils_1.isExpressionStatement(node) && | ||
tsutils_1.isCallExpression(node.expression) && | ||
!ts.isOptionalChain(node.expression) && | ||
this.returnsNever(node.expression) && | ||
tsutils_1.callExpressionAffectsControlFlow(node.expression, this.checker) !== tsutils_1.SignatureEffect.Never) | ||
this.addFindingAtNode(node, `This call never returns, but TypeScript cannot use it for control flow analysis. Consider '${isReturnAllowed(node) ? 'return' : 'throw'}'ing the result to make the control flow effect explicit.`); | ||
} | ||
@@ -27,3 +31,5 @@ returnsNever(node) { | ||
node = node.parent; | ||
if (node.kind === ts.SyntaxKind.SourceFile || node.kind === ts.SyntaxKind.ModuleBlock) | ||
if (node.kind === ts.SyntaxKind.SourceFile || | ||
node.kind === ts.SyntaxKind.ModuleBlock || | ||
node.kind === ts.SyntaxKind.Block && tsutils_1.isTryStatement(node.parent) && node.parent.tryBlock === node) | ||
return false; | ||
@@ -30,0 +36,0 @@ if (tsutils_1.isFunctionScopeBoundary(node)) |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.isAmbientVariableDeclaration = exports.isAmbientPropertyDeclaration = exports.formatPseudoBigInt = exports.hasDirectivePrologue = exports.propertiesOfType = exports.elementAccessSymbols = exports.typesAreEqual = exports.objectLiteralNeedsParens = exports.expressionNeedsParensWhenReplacingNode = exports.childStatements = exports.isVariableReassignment = exports.isAsyncFunction = exports.tryStatements = exports.switchStatements = void 0; | ||
exports.isAmbientVariableDeclaration = exports.isAmbientPropertyDeclaration = exports.hasDirectivePrologue = exports.propertiesOfType = exports.elementAccessSymbols = exports.typesAreEqual = exports.objectLiteralNeedsParens = exports.expressionNeedsParensWhenReplacingNode = exports.childStatements = exports.isVariableReassignment = exports.isAsyncFunction = exports.tryStatements = exports.switchStatements = void 0; | ||
const ts = require("typescript"); | ||
@@ -194,6 +194,2 @@ const tsutils_1 = require("tsutils"); | ||
exports.hasDirectivePrologue = hasDirectivePrologue; | ||
function formatPseudoBigInt(v) { | ||
return `${v.negative ? '-' : ''}${v.base10Value}n`; | ||
} | ||
exports.formatPseudoBigInt = formatPseudoBigInt; | ||
/** Determines whether a property has the `declare` modifier or the containing class is ambient. */ | ||
@@ -200,0 +196,0 @@ function isAmbientPropertyDeclaration(node) { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
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
419398
4951
Updatedtsutils@^3.19.0