@fimbul/mimir
Advanced tools
Comparing version 0.24.0-dev.20210120 to 0.24.0-dev.20210121
{ | ||
"name": "@fimbul/mimir", | ||
"version": "0.24.0-dev.20210120", | ||
"version": "0.24.0-dev.20210121", | ||
"description": "Core rules of the Fimbullinter project", | ||
@@ -5,0 +5,0 @@ "main": "recommended.yaml", |
@@ -44,2 +44,3 @@ # Mímir | ||
[`no-nan-compare`](docs/no-nan-compare.md) | Disallows comparing with `NaN`, use `isNaN(number)` or `Number.isNaN(number)` instead. | Performance! | ||
[`no-object-spread-of-iterable`](docs/no-object-spread-of-iterable.md) | :mag: Disallows spreading iterable types into an object. | | ||
[`no-octal-escape`](docs/no-octal-escape.md) | :wrench: Disallows octal escape sequences in strings and template strings. | No such rule in TSLint. | ||
@@ -46,0 +47,0 @@ [`no-restricted-property-access`](docs/no-restricted-property-access.md) | :mag: Disallows accessing properties via computed name that would not be accessible using a static name. | TSLint has no similar rule. |
@@ -6,6 +6,2 @@ import { TypedRule } from '@fimbul/ymir'; | ||
private checkForStatement; | ||
private isIterationPossible; | ||
private isIterationProtocolAvailable; | ||
private isArrayLike; | ||
private isIterable; | ||
} |
@@ -8,3 +8,3 @@ "use strict"; | ||
const tsutils_1 = require("tsutils"); | ||
const utils_1 = require("../utils"); | ||
const iteration_1 = require("../iteration"); | ||
let Rule = class Rule extends ymir_1.TypedRule { | ||
@@ -35,50 +35,5 @@ get usage() { | ||
return; | ||
if (this.isIterationPossible(arrayVariable)) | ||
if (iteration_1.isExpressionIterable(arrayVariable, this.checker, this.context.compilerOptions, true)) | ||
this.addFinding(node.getStart(this.sourceFile), node.statement.pos, `Prefer a 'for-of' loop over a 'for' loop for this simple iteration.`); | ||
} | ||
isIterationPossible(node) { | ||
const type = this.checker.getTypeAtLocation(node); | ||
return this.isIterationProtocolAvailable() | ||
? this.isIterable(this.checker.getApparentType(type), node) | ||
: tsutils_1.unionTypeParts(utils_1.tryGetBaseConstraintType(type, this.checker)).every(this.isArrayLike, this); | ||
} | ||
isIterationProtocolAvailable() { | ||
return this.sourceFile.languageVersion >= ts.ScriptTarget.ES2015 || this.context.compilerOptions.downlevelIteration === true; | ||
} | ||
isArrayLike(type) { | ||
if (tsutils_1.isTypeReference(type)) | ||
type = type.target; | ||
if (type.getNumberIndexType() === undefined) | ||
return false; | ||
if (type.flags & ts.TypeFlags.StringLike) | ||
return this.sourceFile.languageVersion >= ts.ScriptTarget.ES5; // iterating string is only possible starting from ES5 | ||
if (type.symbol !== undefined && /^(Concat|Readonly)?Array$/.test(type.symbol.escapedName) && | ||
type.symbol.declarations !== undefined && type.symbol.declarations.some((node) => node.getSourceFile().hasNoDefaultLib)) | ||
return true; | ||
if (tsutils_1.isIntersectionType(type)) | ||
return type.types.some(this.isArrayLike, this); | ||
const baseTypes = type.getBaseTypes(); | ||
return baseTypes !== undefined && baseTypes.some(this.isArrayLike, this); | ||
} | ||
isIterable(type, node) { | ||
const indexType = type.getNumberIndexType() || type.getStringIndexType(); | ||
if (indexType === undefined) | ||
return false; | ||
const iteratorFn = tsutils_1.getPropertyOfType(type, '__@iterator'); | ||
if (!isPresentPublicAndRequired(iteratorFn)) | ||
return false; | ||
return checkReturnTypeAndRequireZeroArity(this.checker.getTypeOfSymbolAtLocation(iteratorFn, node), (iterator) => { | ||
const next = iterator.getProperty('next'); | ||
return isPresentPublicAndRequired(next) && | ||
checkReturnTypeAndRequireZeroArity(this.checker.getTypeOfSymbolAtLocation(next, node), (iteratorResult) => { | ||
const done = iteratorResult.getProperty('done'); | ||
if (!isPresentAndPublic(done) || | ||
tsutils_1.someTypePart(tsutils_1.removeOptionalityFromType(this.checker, this.checker.getTypeOfSymbolAtLocation(done, node)), tsutils_1.isUnionType, (t) => !tsutils_1.isTypeFlagSet(t, ts.TypeFlags.BooleanLike))) | ||
return false; | ||
const value = tsutils_1.getIteratorYieldResultFromIteratorResult(iteratorResult, node, this.checker).getProperty('value'); | ||
return isPresentAndPublic(value) && | ||
utils_1.typesAreEqual(this.checker.getTypeOfSymbolAtLocation(value, node), indexType, this.checker); | ||
}); | ||
}); | ||
} | ||
}; | ||
@@ -89,39 +44,2 @@ Rule = tslib_1.__decorate([ | ||
exports.Rule = Rule; | ||
function checkReturnTypeAndRequireZeroArity(type, cb) { | ||
let zeroArity = false; | ||
for (const signature of type.getCallSignatures()) { | ||
if (!cb(signature.getReturnType())) | ||
return false; | ||
if (signatureHasArityZero(signature)) | ||
zeroArity = true; | ||
} | ||
return zeroArity; | ||
} | ||
function signatureHasArityZero(signature) { | ||
if (signature.parameters.length === 0) | ||
return true; | ||
const decl = signature.parameters[0].declarations[0]; | ||
return decl !== undefined && isOptionalParameter(decl); | ||
} | ||
function isOptionalParameter(node) { | ||
if (node.questionToken !== undefined || node.dotDotDotToken !== undefined) | ||
return true; | ||
if (node.flags & ts.NodeFlags.JavaScriptFile && ts.getJSDocParameterTags(node).some((tag) => tag.isBracketed)) | ||
return true; | ||
if (node.initializer === undefined) | ||
return false; | ||
const parameters = node.parent.parameters; | ||
const nextIndex = parameters.indexOf(node) + 1; | ||
if (nextIndex === parameters.length) | ||
return true; | ||
return isOptionalParameter(parameters[nextIndex]); | ||
} | ||
function isPresentPublicAndRequired(symbol) { | ||
return isPresentAndPublic(symbol) && !tsutils_1.isSymbolFlagSet(symbol, ts.SymbolFlags.Optional); | ||
} | ||
function isPresentAndPublic(symbol) { | ||
return symbol !== undefined && | ||
(symbol.declarations === undefined || | ||
symbol.declarations.every((d) => (ts.getCombinedModifierFlags(d) & ts.ModifierFlags.NonPublicAccessibilityModifier) === 0)); | ||
} | ||
function isReadonlyArrayAccess(uses, arrayVariable, statement, sourceFile) { | ||
@@ -128,0 +46,0 @@ let arrayAccess = false; |
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
442314
165
5195
92