cognitive-complexity-ts
Version:
This program analyses TypeScript and JavaScript code according to the [Cognitive Complexity metric](https://www.sonarsource.com/docs/CognitiveComplexity.pdf). It produces a JSON summary and a GUI for exploring the complexity of your codebase.
212 lines • 8.32 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.getColumnAndLine = getColumnAndLine;
exports.getIdentifier = getIdentifier;
exports.getFirstNonParenthesizedAncestor = getFirstNonParenthesizedAncestor;
exports.getNodeKind = getNodeKind;
exports.getTextWithoutBrackets = getTextWithoutBrackets;
exports.isBreakOrContinueToLabel = isBreakOrContinueToLabel;
exports.isContainer = isContainer;
exports.isForLikeStatement = isForLikeStatement;
exports.isFunctionNode = isFunctionNode;
exports.isSyntaxList = isSyntaxList;
exports.isNewSequenceOfBinaryOperators = isNewSequenceOfBinaryOperators;
exports.isNewSequenceOfBinaryTypeOperators = isNewSequenceOfBinaryTypeOperators;
exports.isChainableBinaryOperator = isChainableBinaryOperator;
exports.isChainableBinaryTypeOperator = isChainableBinaryTypeOperator;
exports.breaksASequenceOfBinaryOperators = breaksASequenceOfBinaryOperators;
exports.pausesASequenceOfBinaryOperators = pausesASequenceOfBinaryOperators;
exports.pausesASequenceOfBinaryTypeOperators = pausesASequenceOfBinaryTypeOperators;
exports.passThroughNameBeingAssigned = passThroughNameBeingAssigned;
exports.report = report;
const ts = __importStar(require("typescript"));
const util_1 = require("../util/util");
function getColumnAndLine(node) {
const lineAndCol = node.getSourceFile()
.getLineAndCharacterOfPosition(node.getStart());
return {
column: lineAndCol.character + 1,
line: lineAndCol.line + 1,
};
}
function getIdentifier(node) {
for (const child of node.getChildren()) {
if (ts.isMemberName(child) || ts.isComputedPropertyName(child)) {
return child.getText();
}
}
return undefined;
}
function getFirstNonParenthesizedAncestor(node) {
let firstNonParenthesisAncestor = node.parent;
while (ts.isParenthesizedExpression(firstNonParenthesisAncestor)) {
firstNonParenthesisAncestor = firstNonParenthesisAncestor.parent;
}
return firstNonParenthesisAncestor;
}
function getNodeKind(node) {
if (isFunctionNode(node)) {
return "function";
}
if (ts.isClassDeclaration(node) || ts.isClassExpression(node)) {
return "class";
}
if (ts.isTypeAliasDeclaration(node) || ts.isInterfaceDeclaration(node)) {
return "type";
}
if (ts.isModuleDeclaration(node)) {
return "module";
}
return undefined;
}
function getTextWithoutBrackets(node) {
if (ts.isParenthesizedExpression(node)) {
return node.getChildren()
.slice(1, -1) // ignore the bracket at each end
.map(getTextWithoutBrackets)
.join("");
}
return node.getText();
}
function isBreakOrContinueToLabel(node) {
if (ts.isBreakOrContinueStatement(node)) {
for (const child of node.getChildren()) {
if (ts.isMemberName(child)) {
return true;
}
}
}
return false;
}
function isContainer(node) {
return isFunctionNode(node)
|| ts.isClassDeclaration(node)
|| ts.isInterfaceDeclaration(node)
|| ts.isModuleDeclaration(node)
|| ts.isTypeAliasDeclaration(node)
|| ts.isSourceFile(node)
|| ts.isSourceFile(node.parent);
}
function isForLikeStatement(node) {
return ts.isForInStatement(node)
|| ts.isForOfStatement(node)
|| ts.isForStatement(node);
}
function isFunctionNode(node) {
return ts.isArrowFunction(node)
|| ts.isFunctionDeclaration(node)
|| ts.isFunctionExpression(node)
|| ts.isMethodDeclaration(node)
|| ts.isConstructorDeclaration(node)
|| ts.isAccessor(node);
}
function isSyntaxList(node) {
return node.kind === ts.SyntaxKind.SyntaxList;
}
function isNewSequenceOfBinaryOperators(node, precedingOperator) {
if (!isChainableBinaryOperator(node)
&& node.kind !== ts.SyntaxKind.AmpersandAmpersandEqualsToken
&& node.kind !== ts.SyntaxKind.BarBarEqualsToken
&& node.kind !== ts.SyntaxKind.QuestionQuestionEqualsToken) {
return false;
}
// is now an operator, or is different to previous operator
return precedingOperator === undefined || node.kind !== precedingOperator;
}
function isNewSequenceOfBinaryTypeOperators(node, precedingTypeOperator) {
if (!isChainableBinaryTypeOperator(node)) {
return false;
}
return precedingTypeOperator !== node.kind;
}
function isChainableBinaryOperator(node) {
return node.kind === ts.SyntaxKind.AmpersandAmpersandToken
|| node.kind === ts.SyntaxKind.BarBarToken
|| node.kind === ts.SyntaxKind.QuestionQuestionToken;
}
function isChainableBinaryTypeOperator(node) {
const isPartOfTypeExpression = (node === null || node === void 0 ? void 0 : node.parent) !== undefined // this is actually undefined-able
&& (ts.isUnionTypeNode(node.parent) || ts.isIntersectionTypeNode(node.parent)); // doing .parent skips the syntax list for some reason
return isPartOfTypeExpression
&& (node.kind === ts.SyntaxKind.AmpersandToken || node.kind === ts.SyntaxKind.BarToken);
}
/**
* A node that causes an end to a sequence of binary operators
* (i.e. A && B { C && D }, the curly braces end the prior sequence;
* C will not be interpreted as part of the last sequence.
*/
function breaksASequenceOfBinaryOperators(node) {
return ts.isStatement(node)
|| ts.isBlock(node)
|| isFunctionNode(node)
|| ts.isParameter(node)
|| ts.isTypeParameterDeclaration(node)
|| ts.isPropertyDeclaration(node)
|| (node.kind === ts.SyntaxKind.ColonToken && isFunctionNode(node.parent))
|| node.kind === ts.SyntaxKind.FirstAssignment; // separates extends expression from parameter default
}
/**
* A node that doesn't cause an end to a sequence of binary operators
* (i.e. A && Node && B, the 2 && are in the same sequence)
* but the node's children don't form part of that sequence
* (i.e. A && Node(B && C) && D, this is two sequences, one inside Node(), the other outside)
*/
function pausesASequenceOfBinaryOperators(node) {
return ts.isCallLikeExpression(node)
|| ts.isPrefixUnaryExpression(node)
|| ts.isElementAccessExpression(node);
}
/**
* @see {pausesASequenceOfBinaryOperators} but for type operators
*/
function pausesASequenceOfBinaryTypeOperators(node) {
return ts.isParenthesizedExpression(node)
|| ts.isTypeReferenceNode(node)
|| ts.isAsExpression(node);
}
function passThroughNameBeingAssigned(node) {
return isSyntaxList(node)
|| ts.isObjectLiteralExpression(node)
|| ts.isParenthesizedExpression(node);
}
function report(node, depth = 0) {
const toLog = [(0, util_1.repeat)("\t", depth), ts.SyntaxKind[node.kind], node.kind];
console.error(...toLog);
for (const child of node.getChildren()) {
report(child, depth + 1);
}
}
//# sourceMappingURL=node-inspection.js.map