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.
145 lines • 5.87 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 (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.report = exports.passThroughNameBeingAssigned = exports.isSyntaxList = exports.isSequenceOfDifferentBooleanOperations = exports.isFunctionNode = exports.isForLikeStatement = exports.isContainer = exports.isBreakOrContinueToLabel = exports.isBinaryTypeOperator = exports.getTextWithoutBrackets = exports.getFirstNonParenthesizedAncestor = exports.getIdentifier = exports.getColumnAndLine = void 0;
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,
};
}
exports.getColumnAndLine = getColumnAndLine;
function getIdentifier(node) {
for (const child of node.getChildren()) {
if (ts.isMemberName(child) || ts.isComputedPropertyName(child)) {
return child.getText();
}
}
return undefined;
}
exports.getIdentifier = getIdentifier;
function getFirstNonParenthesizedAncestor(node) {
let firstNonParenthesisAncestor = node.parent;
while (ts.isParenthesizedExpression(firstNonParenthesisAncestor)) {
firstNonParenthesisAncestor = firstNonParenthesisAncestor.parent;
}
return firstNonParenthesisAncestor;
}
exports.getFirstNonParenthesizedAncestor = getFirstNonParenthesizedAncestor;
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();
}
exports.getTextWithoutBrackets = getTextWithoutBrackets;
function isBinaryTypeOperator(node) {
return ts.isUnionTypeNode(node) || ts.isIntersectionTypeNode(node);
}
exports.isBinaryTypeOperator = isBinaryTypeOperator;
function isBreakOrContinueToLabel(node) {
if (ts.isBreakOrContinueStatement(node)) {
for (const child of node.getChildren()) {
if (ts.isMemberName(child)) {
return true;
}
}
}
return false;
}
exports.isBreakOrContinueToLabel = isBreakOrContinueToLabel;
function isContainer(node) {
return isFunctionNode(node)
|| ts.isClassDeclaration(node)
|| ts.isConstructorDeclaration(node)
|| ts.isInterfaceDeclaration(node)
|| ts.isModuleDeclaration(node)
|| ts.isTypeAliasDeclaration(node)
|| ts.isSourceFile(node)
|| ts.isSourceFile(node.parent);
}
exports.isContainer = isContainer;
function isForLikeStatement(node) {
return ts.isForInStatement(node)
|| ts.isForOfStatement(node)
|| ts.isForStatement(node);
}
exports.isForLikeStatement = isForLikeStatement;
function isFunctionNode(node) {
return ts.isArrowFunction(node)
|| ts.isFunctionDeclaration(node)
|| ts.isFunctionExpression(node)
|| ts.isMethodDeclaration(node)
|| ts.isAccessor(node);
}
exports.isFunctionNode = isFunctionNode;
function isSequenceOfDifferentBooleanOperations(node) {
var _a;
if (!ts.isBinaryExpression(node)) {
return false;
}
const operatorToken = node.getChildAt(1);
if (!ts.isToken(operatorToken)) {
return false;
}
const operatorIsBoolean = operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken
|| operatorToken.kind === ts.SyntaxKind.BarBarToken
|| operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken;
const firstNonParenthesisAncestor = getFirstNonParenthesizedAncestor(node);
if (operatorIsBoolean) {
// True if the parent does not use the same operator as this node.
// Presumably true if the parent is not a binary expression.
// Child number 1 is the operator token.
return ((_a = firstNonParenthesisAncestor.getChildAt(1)) === null || _a === void 0 ? void 0 : _a.kind) != operatorToken.kind;
}
return false;
}
exports.isSequenceOfDifferentBooleanOperations = isSequenceOfDifferentBooleanOperations;
function isSyntaxList(node) {
return node.kind === ts.SyntaxKind.SyntaxList;
}
exports.isSyntaxList = isSyntaxList;
function passThroughNameBeingAssigned(node) {
return isSyntaxList(node)
|| ts.isObjectLiteralExpression(node)
|| ts.isParenthesizedExpression(node);
}
exports.passThroughNameBeingAssigned = passThroughNameBeingAssigned;
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);
}
}
exports.report = report;
//# sourceMappingURL=node-inspection.js.map