type-coverage
Advanced tools
Comparing version 1.10.0 to 1.11.0
1049
dist/core.js
@@ -6,10 +6,7 @@ "use strict"; | ||
const path = tslib_1.__importStar(require("path")); | ||
const utils = tslib_1.__importStar(require("tsutils/util")); | ||
const fs = tslib_1.__importStar(require("fs")); | ||
const util_1 = require("util"); | ||
const crypto = tslib_1.__importStar(require("crypto")); | ||
const tsconfig_1 = require("./tsconfig"); | ||
const readFileAsync = util_1.promisify(fs.readFile); | ||
const writeFileAsync = util_1.promisify(fs.writeFile); | ||
const mkdirAsync = util_1.promisify(fs.mkdir); | ||
const checker_1 = require("./checker"); | ||
const dependencies_1 = require("./dependencies"); | ||
const ignore_1 = require("./ignore"); | ||
const cache_1 = require("./cache"); | ||
// tslint:disable-next-line:no-big-function cognitive-complexity | ||
@@ -26,880 +23,5 @@ async function lint(project, detail, debug, files, oldProgram, strict = false, enableCache = false) { | ||
const checker = program.getTypeChecker(); | ||
const ingoreMap = {}; | ||
function collectAny(node, { file, sourceFile, typeCheckResult }) { | ||
const { line, character } = typescript_1.default.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)); | ||
if (ingoreMap[file] && ingoreMap[file].has(line)) { | ||
return false; | ||
} | ||
if (debug) { | ||
console.log(`type === any: ${file}:${line + 1}:${character + 1}: ${node.getText(sourceFile)}`); | ||
} | ||
else if (detail) { | ||
typeCheckResult.anys.push({ file, line, character, text: node.getText(sourceFile) }); | ||
} | ||
return true; | ||
} | ||
function collectNotAny(node, { file, sourceFile, typeCheckResult }, type) { | ||
typeCheckResult.correctCount++; | ||
if (debug) { | ||
const { line, character } = typescript_1.default.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)); | ||
console.log(`type !== any: ${file}:${line + 1}:${character + 1}: ${node.getText(sourceFile)} ${node.kind}(kind) ${type.flags}(flag) ${type.intrinsicName || ''}`); | ||
} | ||
} | ||
function collectData(node, context) { | ||
const type = checker.getTypeAtLocation(node); | ||
if (type) { | ||
context.typeCheckResult.totalCount++; | ||
if (typeIsStrictAny(type, strict)) { | ||
const success = collectAny(node, context); | ||
if (!success) { | ||
collectNotAny(node, context, type); | ||
} | ||
} | ||
else { | ||
collectNotAny(node, context, type); | ||
} | ||
} | ||
} | ||
function handleNodes(nodes, context) { | ||
if (nodes === undefined) { | ||
return; | ||
} | ||
for (const node of nodes) { | ||
handleNode(node, context); | ||
} | ||
} | ||
// tslint:disable-next-line:no-big-function | ||
function handleNode(node, context) { | ||
if (node === undefined) { | ||
return; | ||
} | ||
if (debug) { | ||
const { line, character } = typescript_1.default.getLineAndCharacterOfPosition(context.sourceFile, node.getStart(context.sourceFile)); | ||
console.log(`node: ${context.file}:${line + 1}:${character + 1}: ${node.getText(context.sourceFile)} ${node.kind}(kind)`); | ||
} | ||
handleNodes(node.decorators, context); | ||
handleNodes(node.modifiers, context); | ||
// tslint:disable-next-line:max-switch-cases | ||
switch (node.kind) { | ||
case typescript_1.default.SyntaxKind.Unknown: | ||
case typescript_1.default.SyntaxKind.EndOfFileToken: | ||
case typescript_1.default.SyntaxKind.SingleLineCommentTrivia: | ||
case typescript_1.default.SyntaxKind.MultiLineCommentTrivia: | ||
case typescript_1.default.SyntaxKind.NewLineTrivia: | ||
case typescript_1.default.SyntaxKind.WhitespaceTrivia: | ||
case typescript_1.default.SyntaxKind.ShebangTrivia: | ||
case typescript_1.default.SyntaxKind.ConflictMarkerTrivia: | ||
case typescript_1.default.SyntaxKind.NumericLiteral: | ||
case typescript_1.default.SyntaxKind.StringLiteral: | ||
case typescript_1.default.SyntaxKind.JsxText: | ||
case typescript_1.default.SyntaxKind.JsxTextAllWhiteSpaces: | ||
case typescript_1.default.SyntaxKind.RegularExpressionLiteral: | ||
case typescript_1.default.SyntaxKind.NoSubstitutionTemplateLiteral: | ||
case typescript_1.default.SyntaxKind.TemplateHead: | ||
case typescript_1.default.SyntaxKind.TemplateMiddle: | ||
case typescript_1.default.SyntaxKind.TemplateTail: | ||
case typescript_1.default.SyntaxKind.OpenBraceToken: | ||
case typescript_1.default.SyntaxKind.CloseBraceToken: | ||
case typescript_1.default.SyntaxKind.OpenParenToken: | ||
case typescript_1.default.SyntaxKind.CloseParenToken: | ||
case typescript_1.default.SyntaxKind.OpenBracketToken: | ||
case typescript_1.default.SyntaxKind.CloseBracketToken: | ||
case typescript_1.default.SyntaxKind.DotToken: | ||
case typescript_1.default.SyntaxKind.DotDotDotToken: | ||
case typescript_1.default.SyntaxKind.SemicolonToken: | ||
case typescript_1.default.SyntaxKind.CommaToken: | ||
case typescript_1.default.SyntaxKind.LessThanToken: | ||
case typescript_1.default.SyntaxKind.LessThanSlashToken: | ||
case typescript_1.default.SyntaxKind.GreaterThanToken: | ||
case typescript_1.default.SyntaxKind.LessThanEqualsToken: | ||
case typescript_1.default.SyntaxKind.GreaterThanEqualsToken: | ||
case typescript_1.default.SyntaxKind.EqualsEqualsToken: | ||
case typescript_1.default.SyntaxKind.ExclamationEqualsToken: | ||
case typescript_1.default.SyntaxKind.EqualsEqualsEqualsToken: | ||
case typescript_1.default.SyntaxKind.ExclamationEqualsEqualsToken: | ||
case typescript_1.default.SyntaxKind.EqualsGreaterThanToken: | ||
case typescript_1.default.SyntaxKind.PlusToken: | ||
case typescript_1.default.SyntaxKind.MinusToken: | ||
case typescript_1.default.SyntaxKind.AsteriskToken: | ||
case typescript_1.default.SyntaxKind.AsteriskAsteriskToken: | ||
case typescript_1.default.SyntaxKind.SlashToken: | ||
case typescript_1.default.SyntaxKind.PercentToken: | ||
case typescript_1.default.SyntaxKind.PlusPlusToken: | ||
case typescript_1.default.SyntaxKind.MinusMinusToken: | ||
case typescript_1.default.SyntaxKind.LessThanLessThanToken: | ||
case typescript_1.default.SyntaxKind.GreaterThanGreaterThanToken: | ||
case typescript_1.default.SyntaxKind.GreaterThanGreaterThanGreaterThanToken: | ||
case typescript_1.default.SyntaxKind.AmpersandToken: | ||
case typescript_1.default.SyntaxKind.BarToken: | ||
case typescript_1.default.SyntaxKind.CaretToken: | ||
case typescript_1.default.SyntaxKind.ExclamationToken: | ||
case typescript_1.default.SyntaxKind.TildeToken: | ||
case typescript_1.default.SyntaxKind.AmpersandAmpersandToken: | ||
case typescript_1.default.SyntaxKind.BarBarToken: | ||
case typescript_1.default.SyntaxKind.QuestionToken: | ||
case typescript_1.default.SyntaxKind.ColonToken: | ||
case typescript_1.default.SyntaxKind.AtToken: | ||
case typescript_1.default.SyntaxKind.EqualsToken: | ||
case typescript_1.default.SyntaxKind.PlusEqualsToken: | ||
case typescript_1.default.SyntaxKind.MinusEqualsToken: | ||
case typescript_1.default.SyntaxKind.AsteriskEqualsToken: | ||
case typescript_1.default.SyntaxKind.AsteriskAsteriskEqualsToken: | ||
case typescript_1.default.SyntaxKind.SlashEqualsToken: | ||
case typescript_1.default.SyntaxKind.PercentEqualsToken: | ||
case typescript_1.default.SyntaxKind.LessThanLessThanEqualsToken: | ||
case typescript_1.default.SyntaxKind.GreaterThanGreaterThanEqualsToken: | ||
case typescript_1.default.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: | ||
case typescript_1.default.SyntaxKind.AmpersandEqualsToken: | ||
case typescript_1.default.SyntaxKind.BarEqualsToken: | ||
case typescript_1.default.SyntaxKind.CaretEqualsToken: | ||
break; | ||
case typescript_1.default.SyntaxKind.Identifier: | ||
collectData(node, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.BreakKeyword: | ||
case typescript_1.default.SyntaxKind.CaseKeyword: | ||
case typescript_1.default.SyntaxKind.CatchKeyword: | ||
case typescript_1.default.SyntaxKind.ClassKeyword: | ||
case typescript_1.default.SyntaxKind.ConstKeyword: | ||
case typescript_1.default.SyntaxKind.ContinueKeyword: | ||
case typescript_1.default.SyntaxKind.DebuggerKeyword: | ||
case typescript_1.default.SyntaxKind.DefaultKeyword: | ||
case typescript_1.default.SyntaxKind.DeleteKeyword: | ||
case typescript_1.default.SyntaxKind.DoKeyword: | ||
case typescript_1.default.SyntaxKind.ElseKeyword: | ||
case typescript_1.default.SyntaxKind.EnumKeyword: | ||
case typescript_1.default.SyntaxKind.ExportKeyword: | ||
case typescript_1.default.SyntaxKind.ExtendsKeyword: | ||
case typescript_1.default.SyntaxKind.FalseKeyword: | ||
case typescript_1.default.SyntaxKind.FinallyKeyword: | ||
case typescript_1.default.SyntaxKind.ForKeyword: | ||
case typescript_1.default.SyntaxKind.FunctionKeyword: | ||
case typescript_1.default.SyntaxKind.IfKeyword: | ||
case typescript_1.default.SyntaxKind.ImportKeyword: | ||
case typescript_1.default.SyntaxKind.InKeyword: | ||
case typescript_1.default.SyntaxKind.InstanceOfKeyword: | ||
case typescript_1.default.SyntaxKind.NewKeyword: | ||
case typescript_1.default.SyntaxKind.NullKeyword: | ||
case typescript_1.default.SyntaxKind.ReturnKeyword: | ||
case typescript_1.default.SyntaxKind.SuperKeyword: | ||
case typescript_1.default.SyntaxKind.SwitchKeyword: | ||
break; | ||
case typescript_1.default.SyntaxKind.ThisKeyword: | ||
collectData(node, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ThrowKeyword: | ||
case typescript_1.default.SyntaxKind.TrueKeyword: | ||
case typescript_1.default.SyntaxKind.TryKeyword: | ||
case typescript_1.default.SyntaxKind.TypeOfKeyword: | ||
case typescript_1.default.SyntaxKind.VarKeyword: | ||
case typescript_1.default.SyntaxKind.VoidKeyword: | ||
case typescript_1.default.SyntaxKind.WhileKeyword: | ||
case typescript_1.default.SyntaxKind.WithKeyword: | ||
case typescript_1.default.SyntaxKind.ImplementsKeyword: | ||
case typescript_1.default.SyntaxKind.InterfaceKeyword: | ||
case typescript_1.default.SyntaxKind.LetKeyword: | ||
case typescript_1.default.SyntaxKind.PackageKeyword: | ||
case typescript_1.default.SyntaxKind.PrivateKeyword: | ||
case typescript_1.default.SyntaxKind.ProtectedKeyword: | ||
case typescript_1.default.SyntaxKind.PublicKeyword: | ||
case typescript_1.default.SyntaxKind.StaticKeyword: | ||
case typescript_1.default.SyntaxKind.YieldKeyword: | ||
case typescript_1.default.SyntaxKind.AbstractKeyword: | ||
case typescript_1.default.SyntaxKind.AsKeyword: | ||
case typescript_1.default.SyntaxKind.AnyKeyword: | ||
case typescript_1.default.SyntaxKind.AsyncKeyword: | ||
case typescript_1.default.SyntaxKind.AwaitKeyword: | ||
case typescript_1.default.SyntaxKind.BooleanKeyword: | ||
case typescript_1.default.SyntaxKind.ConstructorKeyword: | ||
case typescript_1.default.SyntaxKind.DeclareKeyword: | ||
case typescript_1.default.SyntaxKind.GetKeyword: | ||
case typescript_1.default.SyntaxKind.IsKeyword: | ||
case typescript_1.default.SyntaxKind.KeyOfKeyword: | ||
case typescript_1.default.SyntaxKind.ModuleKeyword: | ||
case typescript_1.default.SyntaxKind.NamespaceKeyword: | ||
case typescript_1.default.SyntaxKind.NeverKeyword: | ||
case typescript_1.default.SyntaxKind.ReadonlyKeyword: | ||
case typescript_1.default.SyntaxKind.RequireKeyword: | ||
case typescript_1.default.SyntaxKind.NumberKeyword: | ||
case typescript_1.default.SyntaxKind.ObjectKeyword: | ||
case typescript_1.default.SyntaxKind.SetKeyword: | ||
case typescript_1.default.SyntaxKind.StringKeyword: | ||
case typescript_1.default.SyntaxKind.SymbolKeyword: | ||
case typescript_1.default.SyntaxKind.TypeKeyword: | ||
case typescript_1.default.SyntaxKind.UndefinedKeyword: | ||
case typescript_1.default.SyntaxKind.UniqueKeyword: | ||
case typescript_1.default.SyntaxKind.UnknownKeyword: | ||
case typescript_1.default.SyntaxKind.FromKeyword: | ||
case typescript_1.default.SyntaxKind.GlobalKeyword: | ||
case typescript_1.default.SyntaxKind.BigIntKeyword: | ||
case typescript_1.default.SyntaxKind.OfKeyword: | ||
break; | ||
case typescript_1.default.SyntaxKind.QualifiedName: | ||
const qualifiedName = node; | ||
handleNode(qualifiedName.left, context); | ||
handleNode(qualifiedName.right, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ComputedPropertyName: | ||
const computedPropertyName = node; | ||
handleNode(computedPropertyName.expression, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.TypeParameter: | ||
const typeParameterDeclaration = node; | ||
handleNode(typeParameterDeclaration.name, context); | ||
handleNode(typeParameterDeclaration.default, context); | ||
handleNode(typeParameterDeclaration.expression, context); | ||
handleNode(typeParameterDeclaration.constraint, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.Parameter: | ||
const parameterDeclaration = node; | ||
handleNode(parameterDeclaration.dotDotDotToken, context); | ||
handleNode(parameterDeclaration.name, context); | ||
handleNode(parameterDeclaration.initializer, context); | ||
handleNode(parameterDeclaration.type, context); | ||
handleNode(parameterDeclaration.questionToken, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.Decorator: | ||
const decorator = node; | ||
handleNode(decorator.expression, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.PropertySignature: | ||
const propertySignature = node; | ||
handleNode(propertySignature.name, context); | ||
handleNode(propertySignature.questionToken, context); | ||
handleNode(propertySignature.type, context); | ||
handleNode(propertySignature.initializer, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.PropertyDeclaration: | ||
const propertyDeclaration = node; | ||
handleNode(propertyDeclaration.name, context); | ||
handleNode(propertyDeclaration.initializer, context); | ||
handleNode(propertyDeclaration.type, context); | ||
handleNode(propertyDeclaration.questionToken, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.MethodSignature: | ||
const methodSignature = node; | ||
handleNode(methodSignature.name, context); | ||
handleNodes(methodSignature.parameters, context); | ||
handleNode(methodSignature.questionToken, context); | ||
handleNode(methodSignature.type, context); | ||
handleNodes(methodSignature.typeParameters, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.MethodDeclaration: | ||
case typescript_1.default.SyntaxKind.Constructor: | ||
case typescript_1.default.SyntaxKind.GetAccessor: | ||
case typescript_1.default.SyntaxKind.SetAccessor: | ||
const functionLikeDeclarationBase = node; | ||
handleNode(functionLikeDeclarationBase.name, context); | ||
handleNodes(functionLikeDeclarationBase.parameters, context); | ||
handleNode(functionLikeDeclarationBase.body, context); | ||
handleNode(functionLikeDeclarationBase.asteriskToken, context); | ||
handleNode(functionLikeDeclarationBase.questionToken, context); | ||
handleNode(functionLikeDeclarationBase.type, context); | ||
handleNodes(functionLikeDeclarationBase.typeParameters, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.CallSignature: | ||
const callSignatureDeclaration = node; | ||
handleNode(callSignatureDeclaration.name, context); | ||
handleNodes(callSignatureDeclaration.parameters, context); | ||
handleNode(callSignatureDeclaration.questionToken, context); | ||
handleNode(callSignatureDeclaration.type, context); | ||
handleNodes(callSignatureDeclaration.typeParameters, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ConstructSignature: | ||
const constructSignatureDeclaration = node; | ||
handleNode(constructSignatureDeclaration.name, context); | ||
handleNodes(constructSignatureDeclaration.parameters, context); | ||
handleNode(constructSignatureDeclaration.questionToken, context); | ||
handleNode(constructSignatureDeclaration.type, context); | ||
handleNodes(constructSignatureDeclaration.typeParameters, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.IndexSignature: | ||
const indexSignatureDeclaration = node; | ||
handleNode(indexSignatureDeclaration.name, context); | ||
handleNodes(indexSignatureDeclaration.parameters, context); | ||
handleNode(indexSignatureDeclaration.questionToken, context); | ||
handleNode(indexSignatureDeclaration.type, context); | ||
handleNodes(indexSignatureDeclaration.typeParameters, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.TypePredicate: | ||
const typePredicateNode = node; | ||
handleNode(typePredicateNode.type, context); | ||
handleNode(typePredicateNode.parameterName, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.TypeReference: | ||
const typeReferenceNode = node; | ||
handleNode(typeReferenceNode.typeName, context); | ||
handleNodes(typeReferenceNode.typeArguments, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.FunctionType: | ||
case typescript_1.default.SyntaxKind.ConstructorType: | ||
const signatureDeclarationBase = node; | ||
handleNode(signatureDeclarationBase.name, context); | ||
handleNodes(signatureDeclarationBase.parameters, context); | ||
handleNode(signatureDeclarationBase.type, context); | ||
handleNodes(signatureDeclarationBase.typeParameters, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.TypeQuery: | ||
const typeQueryNode = node; | ||
handleNode(typeQueryNode.exprName, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.TypeLiteral: | ||
const typeLiteralNode = node; | ||
handleNodes(typeLiteralNode.members, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ArrayType: | ||
const arrayTypeNode = node; | ||
handleNode(arrayTypeNode.elementType, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.TupleType: | ||
const tupleTypeNode = node; | ||
handleNodes(tupleTypeNode.elementTypes, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.OptionalType: | ||
break; | ||
case typescript_1.default.SyntaxKind.RestType: | ||
const restTypeNode = node; | ||
handleNode(restTypeNode.type, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.UnionType: | ||
const unionTypeNode = node; | ||
handleNodes(unionTypeNode.types, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.IntersectionType: | ||
const intersectionTypeNode = node; | ||
handleNodes(intersectionTypeNode.types, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ConditionalType: | ||
const conditionalTypeNode = node; | ||
handleNode(conditionalTypeNode.checkType, context); | ||
handleNode(conditionalTypeNode.extendsType, context); | ||
handleNode(conditionalTypeNode.trueType, context); | ||
handleNode(conditionalTypeNode.falseType, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.InferType: | ||
const inferTypeNode = node; | ||
handleNode(inferTypeNode.typeParameter, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ParenthesizedType: | ||
const parenthesizedTypeNode = node; | ||
handleNode(parenthesizedTypeNode.type, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ThisType: | ||
break; | ||
case typescript_1.default.SyntaxKind.TypeOperator: | ||
const typeOperatorNode = node; | ||
handleNode(typeOperatorNode.type, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.IndexedAccessType: | ||
const indexedAccessTypeNode = node; | ||
handleNode(indexedAccessTypeNode.objectType, context); | ||
handleNode(indexedAccessTypeNode.indexType, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.MappedType: | ||
const mappedTypeNode = node; | ||
handleNode(mappedTypeNode.questionToken, context); | ||
handleNode(mappedTypeNode.readonlyToken, context); | ||
handleNode(mappedTypeNode.type, context); | ||
handleNode(mappedTypeNode.typeParameter, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.LiteralType: | ||
const literalTypeNode = node; | ||
handleNode(literalTypeNode.literal, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ImportType: | ||
const importTypeNode = node; | ||
handleNode(importTypeNode.qualifier, context); | ||
handleNode(importTypeNode.argument, context); | ||
handleNodes(importTypeNode.typeArguments, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ObjectBindingPattern: | ||
const objectBindingPattern = node; | ||
handleNodes(objectBindingPattern.elements, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ArrayBindingPattern: | ||
const arrayBindingPattern = node; | ||
handleNodes(arrayBindingPattern.elements, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.BindingElement: | ||
const bindingElement = node; | ||
handleNode(bindingElement.name, context); | ||
handleNode(bindingElement.initializer, context); | ||
handleNode(bindingElement.dotDotDotToken, context); | ||
handleNode(bindingElement.propertyName, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ArrayLiteralExpression: | ||
const arrayLiteralExpression = node; | ||
handleNodes(arrayLiteralExpression.elements, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ObjectLiteralExpression: | ||
const objectLiteralExpression = node; | ||
handleNodes(objectLiteralExpression.properties, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.PropertyAccessExpression: | ||
const propertyAccessExpression = node; | ||
handleNode(propertyAccessExpression.expression, context); | ||
handleNode(propertyAccessExpression.name, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ElementAccessExpression: | ||
const elementAccessExpression = node; | ||
handleNode(elementAccessExpression.expression, context); | ||
handleNode(elementAccessExpression.argumentExpression, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.CallExpression: | ||
const callExpression = node; | ||
handleNode(callExpression.expression, context); | ||
handleNodes(callExpression.arguments, context); | ||
handleNodes(callExpression.typeArguments, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.NewExpression: | ||
const newExpression = node; | ||
handleNode(newExpression.expression, context); | ||
handleNodes(newExpression.arguments, context); | ||
handleNodes(newExpression.typeArguments, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.TaggedTemplateExpression: | ||
const taggedTemplateExpression = node; | ||
handleNode(taggedTemplateExpression.template, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.TypeAssertionExpression: | ||
const typeAssertion = node; | ||
handleNode(typeAssertion.expression, context); | ||
handleNode(typeAssertion.type, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ParenthesizedExpression: | ||
const parenthesizedExpression = node; | ||
handleNode(parenthesizedExpression.expression, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.FunctionExpression: | ||
const functionExpression = node; | ||
handleNode(functionExpression.name, context); | ||
handleNodes(functionExpression.parameters, context); | ||
handleNode(functionExpression.body, context); | ||
handleNode(functionExpression.asteriskToken, context); | ||
handleNode(functionExpression.questionToken, context); | ||
handleNode(functionExpression.type, context); | ||
handleNodes(functionExpression.typeParameters, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ArrowFunction: | ||
const arrowFunction = node; | ||
handleNode(arrowFunction.name, context); | ||
handleNodes(arrowFunction.parameters, context); | ||
handleNode(arrowFunction.body, context); | ||
handleNode(arrowFunction.asteriskToken, context); | ||
handleNode(arrowFunction.questionToken, context); | ||
handleNode(arrowFunction.type, context); | ||
handleNodes(arrowFunction.typeParameters, context); | ||
handleNode(arrowFunction.equalsGreaterThanToken, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.DeleteExpression: | ||
const deleteExpression = node; | ||
handleNode(deleteExpression.expression, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.TypeOfExpression: | ||
const typeOfExpression = node; | ||
handleNode(typeOfExpression.expression, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.VoidExpression: | ||
const voidExpression = node; | ||
handleNode(voidExpression.expression, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.AwaitExpression: | ||
const awaitExpression = node; | ||
handleNode(awaitExpression.expression, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.PrefixUnaryExpression: | ||
const prefixUnaryExpression = node; | ||
handleNode(prefixUnaryExpression.operand, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.PostfixUnaryExpression: | ||
const postfixUnaryExpression = node; | ||
handleNode(postfixUnaryExpression.operand, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.BinaryExpression: | ||
const binaryExpression = node; | ||
handleNode(binaryExpression.left, context); | ||
handleNode(binaryExpression.right, context); | ||
handleNode(binaryExpression.operatorToken, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ConditionalExpression: | ||
const conditionalExpression = node; | ||
handleNode(conditionalExpression.condition, context); | ||
handleNode(conditionalExpression.colonToken, context); | ||
handleNode(conditionalExpression.questionToken, context); | ||
handleNode(conditionalExpression.whenTrue, context); | ||
handleNode(conditionalExpression.whenFalse, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.TemplateExpression: | ||
const templateExpression = node; | ||
handleNodes(templateExpression.templateSpans, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.YieldExpression: | ||
const yieldExpression = node; | ||
handleNode(yieldExpression.asteriskToken, context); | ||
handleNode(yieldExpression.expression, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.SpreadElement: | ||
const spreadElement = node; | ||
handleNode(spreadElement.expression, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ClassExpression: | ||
const classExpression = node; | ||
handleNode(classExpression.name, context); | ||
handleNodes(classExpression.typeParameters, context); | ||
handleNodes(classExpression.members, context); | ||
handleNodes(classExpression.heritageClauses, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.OmittedExpression: | ||
break; | ||
case typescript_1.default.SyntaxKind.ExpressionWithTypeArguments: | ||
const expressionWithTypeArguments = node; | ||
handleNode(expressionWithTypeArguments.expression, context); | ||
handleNodes(expressionWithTypeArguments.typeArguments, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.AsExpression: | ||
const asExpression = node; | ||
handleNode(asExpression.expression, context); | ||
handleNode(asExpression.type, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.NonNullExpression: | ||
const nonNullExpression = node; | ||
handleNode(nonNullExpression.expression, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.MetaProperty: | ||
const metaProperty = node; | ||
handleNode(metaProperty.name, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.TemplateSpan: | ||
const templateSpan = node; | ||
handleNode(templateSpan.expression, context); | ||
handleNode(templateSpan.literal, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.SemicolonClassElement: | ||
const semicolonClassElement = node; | ||
handleNode(semicolonClassElement.name, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.Block: | ||
const block = node; | ||
handleNodes(block.statements, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.VariableStatement: | ||
const variableStatement = node; | ||
handleNode(variableStatement.declarationList, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.EmptyStatement: | ||
break; | ||
case typescript_1.default.SyntaxKind.ExpressionStatement: | ||
const expressionStatement = node; | ||
handleNode(expressionStatement.expression, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.IfStatement: | ||
const ifStatement = node; | ||
handleNode(ifStatement.expression, context); | ||
handleNode(ifStatement.thenStatement, context); | ||
handleNode(ifStatement.elseStatement, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.DoStatement: | ||
const doStatement = node; | ||
handleNode(doStatement.expression, context); | ||
handleNode(doStatement.statement, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.WhileStatement: | ||
const whileStatement = node; | ||
handleNode(whileStatement.statement, context); | ||
handleNode(whileStatement.expression, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ForStatement: | ||
const forStatement = node; | ||
handleNode(forStatement.initializer, context); | ||
handleNode(forStatement.condition, context); | ||
handleNode(forStatement.incrementor, context); | ||
handleNode(forStatement.statement, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ForInStatement: | ||
const forInStatement = node; | ||
handleNode(forInStatement.initializer, context); | ||
handleNode(forInStatement.expression, context); | ||
handleNode(forInStatement.statement, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ForOfStatement: | ||
const forOfStatement = node; | ||
handleNode(forOfStatement.initializer, context); | ||
handleNode(forOfStatement.statement, context); | ||
handleNode(forOfStatement.expression, context); | ||
handleNode(forOfStatement.awaitModifier, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ContinueStatement: | ||
case typescript_1.default.SyntaxKind.BreakStatement: | ||
break; | ||
case typescript_1.default.SyntaxKind.ReturnStatement: | ||
const returnStatement = node; | ||
handleNode(returnStatement.expression, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.WithStatement: | ||
const withStatement = node; | ||
handleNode(withStatement.expression, context); | ||
handleNode(withStatement.statement, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.SwitchStatement: | ||
const switchStatement = node; | ||
handleNode(switchStatement.expression, context); | ||
handleNode(switchStatement.caseBlock, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.LabeledStatement: | ||
const labeledStatement = node; | ||
handleNode(labeledStatement.label, context); | ||
handleNode(labeledStatement.statement, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ThrowStatement: | ||
const throwStatement = node; | ||
handleNode(throwStatement.expression, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.TryStatement: | ||
const tryStatement = node; | ||
handleNode(tryStatement.tryBlock, context); | ||
handleNode(tryStatement.catchClause, context); | ||
handleNode(tryStatement.finallyBlock, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.DebuggerStatement: | ||
break; | ||
case typescript_1.default.SyntaxKind.VariableDeclaration: | ||
const variableDeclaration = node; | ||
handleNode(variableDeclaration.name, context); | ||
handleNode(variableDeclaration.type, context); | ||
handleNode(variableDeclaration.initializer, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.VariableDeclarationList: | ||
const declarationList = node; | ||
handleNodes(declarationList.declarations, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.FunctionDeclaration: | ||
const functionDeclaration = node; | ||
handleNode(functionDeclaration.name, context); | ||
handleNodes(functionDeclaration.parameters, context); | ||
handleNode(functionDeclaration.body, context); | ||
handleNode(functionDeclaration.asteriskToken, context); | ||
handleNode(functionDeclaration.questionToken, context); | ||
handleNode(functionDeclaration.type, context); | ||
handleNodes(functionDeclaration.typeParameters, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ClassDeclaration: | ||
const classDeclaration = node; | ||
handleNode(classDeclaration.name, context); | ||
handleNodes(classDeclaration.members, context); | ||
handleNodes(classDeclaration.typeParameters, context); | ||
handleNodes(classDeclaration.heritageClauses, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.InterfaceDeclaration: | ||
const interfaceDeclaration = node; | ||
handleNode(interfaceDeclaration.name, context); | ||
handleNodes(interfaceDeclaration.members, context); | ||
handleNodes(interfaceDeclaration.typeParameters, context); | ||
handleNodes(interfaceDeclaration.heritageClauses, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.TypeAliasDeclaration: | ||
const typeAliasDeclaration = node; | ||
handleNode(typeAliasDeclaration.name, context); | ||
handleNode(typeAliasDeclaration.type, context); | ||
handleNodes(typeAliasDeclaration.typeParameters, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.EnumDeclaration: | ||
const enumDeclaration = node; | ||
handleNode(enumDeclaration.name, context); | ||
handleNodes(enumDeclaration.members, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ModuleDeclaration: | ||
const moduleDeclaration = node; | ||
handleNode(moduleDeclaration.name, context); | ||
handleNode(moduleDeclaration.body, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ModuleBlock: | ||
const moduleBlock = node; | ||
handleNodes(moduleBlock.statements, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.CaseBlock: | ||
const caseBlock = node; | ||
handleNodes(caseBlock.clauses, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.NamespaceExportDeclaration: | ||
const namespaceExportDeclaration = node; | ||
handleNode(namespaceExportDeclaration.name, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ImportEqualsDeclaration: | ||
const importEqualsDeclaration = node; | ||
handleNode(importEqualsDeclaration.name, context); | ||
handleNode(importEqualsDeclaration.moduleReference, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ImportDeclaration: | ||
const importDeclaration = node; | ||
handleNode(importDeclaration.importClause, context); | ||
handleNode(importDeclaration.moduleSpecifier, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ImportClause: | ||
const importClause = node; | ||
handleNode(importClause.name, context); | ||
handleNode(importClause.namedBindings, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.NamespaceImport: | ||
const namespaceImport = node; | ||
handleNode(namespaceImport.name, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.NamedImports: | ||
const namedImports = node; | ||
handleNodes(namedImports.elements, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ImportSpecifier: | ||
const importSpecifier = node; | ||
handleNode(importSpecifier.name, context); | ||
handleNode(importSpecifier.propertyName, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ExportAssignment: | ||
const exportAssignment = node; | ||
handleNode(exportAssignment.name, context); | ||
handleNode(exportAssignment.expression, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ExportDeclaration: | ||
const exportDeclaration = node; | ||
handleNode(exportDeclaration.exportClause, context); | ||
handleNode(exportDeclaration.name, context); | ||
handleNode(exportDeclaration.moduleSpecifier, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.NamedExports: | ||
const namedExports = node; | ||
handleNodes(namedExports.elements, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ExportSpecifier: | ||
const exportSpecifier = node; | ||
handleNode(exportSpecifier.name, context); | ||
handleNode(exportSpecifier.propertyName, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.MissingDeclaration: | ||
const missingDeclaration = node; | ||
handleNode(missingDeclaration.name, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ExternalModuleReference: | ||
const externalModuleReference = node; | ||
handleNode(externalModuleReference.expression, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.JsxElement: | ||
const jsxElement = node; | ||
handleNode(jsxElement.openingElement, context); | ||
handleNode(jsxElement.closingElement, context); | ||
handleNodes(jsxElement.children, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.JsxSelfClosingElement: | ||
const jsxSelfClosingElement = node; | ||
handleNode(jsxSelfClosingElement.attributes, context); | ||
handleNode(jsxSelfClosingElement.tagName, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.JsxOpeningElement: | ||
const jsxOpeningElement = node; | ||
handleNode(jsxOpeningElement.attributes, context); | ||
handleNode(jsxOpeningElement.tagName, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.JsxClosingElement: | ||
const jsxClosingElement = node; | ||
handleNode(jsxClosingElement.tagName, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.JsxFragment: | ||
const jsxFragment = node; | ||
handleNode(jsxFragment.openingFragment, context); | ||
handleNode(jsxFragment.closingFragment, context); | ||
handleNodes(jsxFragment.children, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.JsxOpeningFragment: | ||
break; | ||
case typescript_1.default.SyntaxKind.JsxClosingFragment: | ||
break; | ||
case typescript_1.default.SyntaxKind.JsxAttribute: | ||
const jsxAttribute = node; | ||
handleNode(jsxAttribute.name, context); | ||
handleNode(jsxAttribute.initializer, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.JsxAttributes: | ||
const jsxAttributes = node; | ||
handleNodes(jsxAttributes.properties, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.JsxSpreadAttribute: | ||
const jsxSpreadAttribute = node; | ||
handleNode(jsxSpreadAttribute.name, context); | ||
handleNode(jsxSpreadAttribute.expression, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.JsxExpression: | ||
const jsxExpression = node; | ||
handleNode(jsxExpression.dotDotDotToken, context); | ||
handleNode(jsxExpression.expression, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.CaseClause: | ||
const caseClause = node; | ||
handleNodes(caseClause.statements, context); | ||
handleNode(caseClause.expression, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.DefaultClause: | ||
const defaultClause = node; | ||
handleNodes(defaultClause.statements, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.HeritageClause: | ||
const heritageClause = node; | ||
handleNodes(heritageClause.types, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.CatchClause: | ||
const catchClause = node; | ||
handleNode(catchClause.variableDeclaration, context); | ||
handleNode(catchClause.block, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.PropertyAssignment: | ||
const propertyAssignmentExpression = node; | ||
handleNode(propertyAssignmentExpression.name, context); | ||
handleNode(propertyAssignmentExpression.questionToken, context); | ||
handleNode(propertyAssignmentExpression.initializer, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.ShorthandPropertyAssignment: | ||
const shorthandPropertyAssignment = node; | ||
handleNode(shorthandPropertyAssignment.name, context); | ||
handleNode(shorthandPropertyAssignment.questionToken, context); | ||
handleNode(shorthandPropertyAssignment.equalsToken, context); | ||
handleNode(shorthandPropertyAssignment.objectAssignmentInitializer, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.SpreadAssignment: | ||
const spreadAssignment = node; | ||
handleNode(spreadAssignment.name, context); | ||
handleNode(spreadAssignment.expression, context); | ||
break; | ||
case typescript_1.default.SyntaxKind.EnumMember: | ||
case typescript_1.default.SyntaxKind.SourceFile: | ||
case typescript_1.default.SyntaxKind.Bundle: | ||
case typescript_1.default.SyntaxKind.JSDocTypeExpression: | ||
case typescript_1.default.SyntaxKind.JSDocAllType: | ||
case typescript_1.default.SyntaxKind.JSDocUnknownType: | ||
case typescript_1.default.SyntaxKind.JSDocNullableType: | ||
case typescript_1.default.SyntaxKind.JSDocNonNullableType: | ||
case typescript_1.default.SyntaxKind.JSDocOptionalType: | ||
case typescript_1.default.SyntaxKind.JSDocFunctionType: | ||
case typescript_1.default.SyntaxKind.JSDocVariadicType: | ||
case typescript_1.default.SyntaxKind.JSDocComment: | ||
case typescript_1.default.SyntaxKind.JSDocTag: | ||
case typescript_1.default.SyntaxKind.JSDocAugmentsTag: | ||
case typescript_1.default.SyntaxKind.JSDocClassTag: | ||
case typescript_1.default.SyntaxKind.JSDocParameterTag: | ||
case typescript_1.default.SyntaxKind.JSDocReturnTag: | ||
case typescript_1.default.SyntaxKind.JSDocTypeTag: | ||
case typescript_1.default.SyntaxKind.JSDocTemplateTag: | ||
case typescript_1.default.SyntaxKind.JSDocTypedefTag: | ||
case typescript_1.default.SyntaxKind.JSDocPropertyTag: | ||
case typescript_1.default.SyntaxKind.JSDocTypeLiteral: | ||
case typescript_1.default.SyntaxKind.SyntaxList: | ||
case typescript_1.default.SyntaxKind.NotEmittedStatement: | ||
case typescript_1.default.SyntaxKind.PartiallyEmittedExpression: | ||
case typescript_1.default.SyntaxKind.CommaListExpression: | ||
case typescript_1.default.SyntaxKind.MergeDeclarationMarker: | ||
case typescript_1.default.SyntaxKind.EndOfDeclarationMarker: | ||
case typescript_1.default.SyntaxKind.Count: | ||
break; | ||
default: | ||
console.log(`warning: unhandled node kind: ${node.kind}`); | ||
} | ||
} | ||
const allFiles = []; | ||
const sourceFileInfos = []; | ||
const typeCheckResult = await readCache(enableCache); | ||
const typeCheckResult = await cache_1.readCache(enableCache); | ||
for (const sourceFile of program.getSourceFiles()) { | ||
@@ -910,4 +32,4 @@ let file = sourceFile.fileName; | ||
allFiles.push(file); | ||
const hash = enableCache ? calculateHash((await readFileAsync(file)).toString()) : ''; | ||
const cache = typeCheckResult.cache.find((c) => c.file === file && c.hash === hash); | ||
const hash = await cache_1.getFileHash(file, enableCache); | ||
const cache = typeCheckResult.cache[file]; | ||
sourceFileInfos.push({ | ||
@@ -917,42 +39,11 @@ file, | ||
hash, | ||
cache | ||
cache: cache && cache.hash === hash ? cache : undefined | ||
}); | ||
} | ||
} | ||
const dependencies = []; | ||
if (enableCache) { | ||
for (const { sourceFile, file } of sourceFileInfos) { | ||
sourceFile.forEachChild(node => { | ||
let source; | ||
if (node.kind === typescript_1.default.SyntaxKind.ImportEqualsDeclaration) { | ||
source = node.name.text; | ||
} | ||
else if (node.kind === typescript_1.default.SyntaxKind.ImportDeclaration) { | ||
source = node.moduleSpecifier.text; | ||
} | ||
if (source | ||
&& (source.startsWith('.') || source.startsWith('/')) | ||
&& !source.endsWith('.json') | ||
&& !source.endsWith('.node')) { | ||
const resolveResult = resolveImport(path.relative(process.cwd(), path.resolve(path.dirname(file), source)), allFiles); | ||
dependencies.push([file, resolveResult]); | ||
} | ||
}); | ||
} | ||
} | ||
function clearCacheOfDependencies(sourceFileInfo) { | ||
for (const dependency of dependencies) { | ||
if (dependency[1] === sourceFileInfo.file) { | ||
const dependentSourceFileInfo = sourceFileInfos.find((s) => s.file === dependency[0]); | ||
if (dependentSourceFileInfo && dependentSourceFileInfo.cache) { | ||
dependentSourceFileInfo.cache = undefined; | ||
clearCacheOfDependencies(dependentSourceFileInfo); | ||
} | ||
} | ||
} | ||
} | ||
if (enableCache) { | ||
const dependencies = dependencies_1.collectDependencies(sourceFileInfos, allFiles); | ||
for (const sourceFileInfo of sourceFileInfos) { | ||
if (!sourceFileInfo.cache) { | ||
clearCacheOfDependencies(sourceFileInfo); | ||
dependencies_1.clearCacheOfDependencies(sourceFileInfo, dependencies, sourceFileInfos); | ||
} | ||
@@ -968,5 +59,6 @@ } | ||
totalCount += cache.totalCount; | ||
anys.push(...cache.anys); | ||
anys.push(...cache.anys.map((a) => ({ file, ...a }))); | ||
continue; | ||
} | ||
const ingoreMap = ignore_1.collectIgnoreMap(sourceFile, file); | ||
const context = { | ||
@@ -979,31 +71,17 @@ file, | ||
anys: [] | ||
} | ||
}, | ||
debug, | ||
detail, | ||
strict, | ||
checker, | ||
ingoreMap | ||
}; | ||
utils.forEachComment(sourceFile, (_, comment) => { | ||
const commentText = comment.kind === typescript_1.default.SyntaxKind.SingleLineCommentTrivia | ||
? sourceFile.text.substring(comment.pos + 2, comment.end).trim() | ||
: sourceFile.text.substring(comment.pos + 2, comment.end - 2).trim(); | ||
if (commentText.includes('type-coverage:ignore-next-line')) { | ||
if (!ingoreMap[file]) { | ||
ingoreMap[file] = new Set(); | ||
} | ||
const line = typescript_1.default.getLineAndCharacterOfPosition(sourceFile, comment.pos).line; | ||
ingoreMap[file].add(line + 1); | ||
} | ||
else if (commentText.includes('type-coverage:ignore-line')) { | ||
if (!ingoreMap[file]) { | ||
ingoreMap[file] = new Set(); | ||
} | ||
const line = typescript_1.default.getLineAndCharacterOfPosition(sourceFile, comment.pos).line; | ||
ingoreMap[file].add(line); | ||
} | ||
}); | ||
sourceFile.forEachChild(node => { | ||
handleNode(node, context); | ||
checker_1.checkNode(node, context); | ||
}); | ||
correctCount += context.typeCheckResult.correctCount; | ||
totalCount += context.typeCheckResult.totalCount; | ||
anys.push(...context.typeCheckResult.anys); | ||
anys.push(...context.typeCheckResult.anys.map((a) => ({ file, ...a }))); | ||
if (enableCache) { | ||
const resultCache = typeCheckResult.cache.find((c) => c.file === file); | ||
const resultCache = typeCheckResult.cache[file]; | ||
if (resultCache) { | ||
@@ -1016,7 +94,6 @@ resultCache.hash = hash; | ||
else { | ||
typeCheckResult.cache.push({ | ||
file, | ||
typeCheckResult.cache[file] = { | ||
hash, | ||
...context.typeCheckResult | ||
}); | ||
}; | ||
} | ||
@@ -1026,4 +103,3 @@ } | ||
if (enableCache) { | ||
await mkdirIfmissing(); | ||
await writeFileAsync(path.resolve(dirName, 'result.json'), JSON.stringify(typeCheckResult, null, 2)); | ||
await cache_1.saveCache(typeCheckResult); | ||
} | ||
@@ -1033,78 +109,1 @@ return { correctCount, totalCount, anys, program }; | ||
exports.lint = lint; | ||
function typeIsStrictAny(type, strict) { | ||
if (type.flags === typescript_1.default.TypeFlags.Any) { | ||
return type.intrinsicName === 'any'; | ||
} | ||
if (strict && type.flags === typescript_1.default.TypeFlags.Object) { | ||
const typeArguments = type.typeArguments; | ||
if (typeArguments) { | ||
return typeArguments.some((typeArgument) => typeIsStrictAny(typeArgument, strict)); | ||
} | ||
} | ||
return false; | ||
} | ||
function calculateHash(str) { | ||
return crypto.createHash('sha256').update(str).digest('hex'); | ||
} | ||
const dirName = '.type-coverage'; | ||
function statAsync(p) { | ||
return new Promise((resolve) => { | ||
fs.stat(p, (err, stats) => { | ||
if (err) { | ||
resolve(undefined); | ||
} | ||
else { | ||
resolve(stats); | ||
} | ||
}); | ||
}); | ||
} | ||
async function mkdirIfmissing() { | ||
const stats = await statAsync(dirName); | ||
if (!stats) { | ||
await mkdirAsync(dirName); | ||
} | ||
} | ||
async function readCache(enableCache) { | ||
if (!enableCache) { | ||
return { | ||
cache: [] | ||
}; | ||
} | ||
const filepath = path.resolve(dirName, 'result.json'); | ||
const stats = await statAsync(filepath); | ||
if (stats && stats.isFile()) { | ||
const text = (await readFileAsync(filepath)).toString(); | ||
return JSON.parse(text); | ||
} | ||
return { | ||
cache: [] | ||
}; | ||
} | ||
function resolveImport(moduleName, allFiles) { | ||
let resolveResult = moduleName + '.ts'; | ||
if (allFiles.includes(resolveResult)) { | ||
return resolveResult; | ||
} | ||
resolveResult = moduleName + '.tsx'; | ||
if (allFiles.includes(resolveResult)) { | ||
return resolveResult; | ||
} | ||
resolveResult = moduleName + '.d.ts'; | ||
if (allFiles.includes(resolveResult)) { | ||
return resolveResult; | ||
} | ||
resolveResult = path.resolve(moduleName, 'index.ts'); | ||
if (allFiles.includes(resolveResult)) { | ||
return resolveResult; | ||
} | ||
resolveResult = path.resolve(moduleName, 'index.tsx'); | ||
if (allFiles.includes(resolveResult)) { | ||
return resolveResult; | ||
} | ||
resolveResult = path.resolve(moduleName, 'index.d.ts'); | ||
if (allFiles.includes(resolveResult)) { | ||
return resolveResult; | ||
} | ||
return moduleName; | ||
} |
@@ -5,6 +5,8 @@ import ts from 'typescript'; | ||
totalCount: number; | ||
anys: AnyInfo[]; | ||
anys: FileAnyInfo[]; | ||
} | ||
export interface AnyInfo { | ||
export interface AnyInfo extends FileAnyInfo { | ||
file: string; | ||
} | ||
interface FileAnyInfo { | ||
line: number; | ||
@@ -18,9 +20,17 @@ character: number; | ||
typeCheckResult: FileTypeCheckResult; | ||
debug: boolean; | ||
detail: boolean; | ||
strict: boolean; | ||
checker: ts.TypeChecker; | ||
ingoreMap: { | ||
[file: string]: Set<number>; | ||
}; | ||
} | ||
interface TypeCheckCache extends FileTypeCheckResult { | ||
file: string; | ||
hash: string; | ||
} | ||
export interface TypeCheckResult { | ||
cache: TypeCheckCache[]; | ||
cache: { | ||
[file: string]: TypeCheckCache; | ||
}; | ||
} | ||
@@ -27,0 +37,0 @@ export interface SourceFileInfo { |
{ | ||
"name": "type-coverage", | ||
"version": "1.10.0", | ||
"version": "1.11.0", | ||
"description": "A CLI tool to check type coverage for typescript code", | ||
@@ -14,13 +14,13 @@ "main": "dist/core.js", | ||
"@types/glob": "7.1.1", | ||
"@types/jasmine": "3.3.9", | ||
"@types/jasmine": "3.3.12", | ||
"@types/minimist": "1.2.0", | ||
"@types/node": "11.9.4", | ||
"@types/node": "11.11.6", | ||
"clean-release": "2.7.0", | ||
"clean-scripts": "1.9.2", | ||
"jasmine": "3.3.1", | ||
"markdownlint-cli": "0.13.0", | ||
"markdownlint-cli": "0.14.0", | ||
"no-unused-export": "1.7.0", | ||
"rimraf": "2.6.3", | ||
"standard": "12.0.1", | ||
"tslint": "5.12.1", | ||
"tslint": "5.14.0", | ||
"tslint-config-standard": "8.0.1", | ||
@@ -27,0 +27,0 @@ "tslint-sonarts": "1.9.0" |
@@ -5,3 +5,3 @@ # type-coverage | ||
This tool will check type of all identifiers, `the code coverage` = `the count of identifiers whose type is not any` / `the total count of identifiers`, the higher, the better. | ||
This tool will check type of all identifiers, `the type coverage rate` = `the count of identifiers whose type is not any` / `the total count of identifiers`, the higher, the better. | ||
@@ -28,9 +28,19 @@ [![Dependency Status](https://david-dm.org/plantain-00/type-coverage.svg)](https://david-dm.org/plantain-00/type-coverage) | ||
--- | --- | --- | ||
-p, --project | string? | show where is the `tsconfig.json` | ||
--detail | boolean? | show detail | ||
--at-least | number? | fail if coverage rate < this value | ||
--debug | boolean? | show debug info | ||
--strict | boolean? | if the identifiers' type arguments exist and contain at least one `any`, like `any[]`, `ReadonlyArray<any>`, `Promise<any>`, `Foo<number, any>`, it will be considered as `any` too; also, future minor release may introduce stricter type check in this mode, which may lower the code coverage | ||
--cache | boolean? | save and reuse type check result of files that is unchanged and independent of changed files in `.type-coverage` directory, to improve speed | ||
`-p`, `--project` | string? | tell the CLI where is the `tsconfig.json` | ||
`--detail` | boolean? | show detail | ||
`--at-least` | number? | fail if coverage rate < this value | ||
`--debug` | boolean? | show debug info | ||
`--strict` | boolean? | [strict mode](#strict-mode) | ||
`--cache` | boolean? | [enable cache](#enable-cache) | ||
### strict mode | ||
If the identifiers' type arguments exist and contain at least one `any`, like `any[]`, `ReadonlyArray<any>`, `Promise<any>`, `Foo<number, any>`, it will be considered as `any` too | ||
Also, future minor release may introduce stricter type check in this mode, which may lower the type coverage rate | ||
### enable cache | ||
save and reuse type check result of files that is unchanged and independent of changed files in `.type-coverage` directory, to improve speed | ||
## config in package.json | ||
@@ -59,3 +69,3 @@ | ||
## add dynamic badges of type coverage | ||
## add dynamic badges of type coverage rate | ||
@@ -68,2 +78,26 @@ Use your own project url: | ||
## API | ||
```ts | ||
export function lint( | ||
project: string, | ||
detail: boolean, | ||
debug: boolean, | ||
files?: string[], | ||
oldProgram?: ts.Program, | ||
strict = false, | ||
enableCache = false | ||
): Promise<{ | ||
correctCount: number | ||
totalCount: number | ||
anys: { | ||
file: string | ||
line: number | ||
character: number | ||
text: string | ||
}[] | ||
program: ts.Program | ||
}> | ||
``` | ||
## FAQ | ||
@@ -70,0 +104,0 @@ |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
20
1396
104
70601
1