code-gauge 0.0.0-semantically-released
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +147 -0
- package/dist/architectureMetrics.cjs +2 -0
- package/dist/architectureMetrics.cjs.map +1 -0
- package/dist/architectureMetrics.d.ts +41 -0
- package/dist/architectureMetrics.js +2 -0
- package/dist/architectureMetrics.js.map +1 -0
- package/dist/cli.cjs +3 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +3 -0
- package/dist/cli.js.map +1 -0
- package/dist/cliConfig.cjs +2 -0
- package/dist/cliConfig.cjs.map +1 -0
- package/dist/cliConfig.d.ts +92 -0
- package/dist/cliConfig.js +2 -0
- package/dist/cliConfig.js.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/languages.cjs +2 -0
- package/dist/languages.cjs.map +1 -0
- package/dist/languages.d.ts +4 -0
- package/dist/languages.js +2 -0
- package/dist/languages.js.map +1 -0
- package/dist/metrics.cjs +2 -0
- package/dist/metrics.cjs.map +1 -0
- package/dist/metrics.d.ts +9 -0
- package/dist/metrics.js +2 -0
- package/dist/metrics.js.map +1 -0
- package/dist/types.d.ts +137 -0
- package/dist/typescriptProject.cjs +2 -0
- package/dist/typescriptProject.cjs.map +1 -0
- package/dist/typescriptProject.d.ts +24 -0
- package/dist/typescriptProject.js +2 -0
- package/dist/typescriptProject.js.map +1 -0
- package/package.json +80 -0
package/dist/metrics.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var t=require("tree-sitter"),e=require("./languages.cjs");const n=new Set(["&&","||","and","or"]),r=new Set(["+","-","*","/","%","**","=","+=","-=","*=","/=","%=","==","!=","===","!==","<","<=",">",">=","!","~","&","|","^","<<",">>","=>","return","throw","yield","await","break","continue"]),o=new Set(["identifier","property_identifier","field_identifier","type_identifier","number","integer","float","string","string_literal","template_string","character_literal","true","false","null","undefined","nil"]);class i{registry=e.createLanguageRegistry();registerLanguage(t){this.registry.set(t.name,t);for(const e of t.aliases??[])this.registry.set(e,t)}getSupportedLanguages(){return[...new Set([...this.registry.values()].map(t=>t.name))]}measure(e,n){const i=this.registry.get(n.language);if(!i)throw new Error(`Unsupported language: ${n.language}`);const a=new t;a.setLanguage(i.parserLanguage);const d=a.parse(e,void 0,{bufferSize:e.length+1}).rootNode,p=function(t,e,n){const r=e.map((t,e)=>function(t,e,n){const r=c(t,e,0,!0),o=function(t,e){const n=new Set,r=new Set(e.functionNodeTypes);let o=0;function i(t,e){if(e||!r.has(t.type)){if(A(t)){o+=1;const e=function(t){const e=t.childForFieldName("function")??t.namedChild(0);if(!e)return;return $(e)}(t);e&&n.add(e)}for(const e of t.namedChildren)i(e,!1)}}return i(t,!0),{callCount:o,callees:n}}(t,e);return{index:n,name:P(t),startLine:t.startPosition.row+1,startColumn:t.startPosition.column,endLine:t.endPosition.row+1,returnsJsx:f(t,e),cyclomaticComplexity:r.cyclomaticComplexity,cognitiveComplexity:r.cognitiveComplexity,callCount:o.callCount,parameterCount:s(t),callees:o.callees,identifiers:u(t)}}(t,n,e)),o=function(t){const e=function(t){const e=new Map;for(const n of t)n.name&&e.set(n.name,e.has(n.name)?void 0:n.index);return new Map([...e.entries()].filter(t=>void 0!==t[1]))}(t),n=new Set(e.keys()),r=new Map,o=new Map,i=new Map;let a=0,s=0;const c=new Set;for(const u of t){a+=u.callCount;for(const t of u.callees)c.add(t);const t=new Set([...u.callees].filter(t=>n.has(t))),l=new Set;for(const n of t){const t=e.get(n);void 0!==t&&l.add(t)}i.set(u.index,l),o.set(u.index,t.size),s+=t.size;for(const t of l)r.set(t,(r.get(t)??0)+1)}const u=function(t){const e=new Set;for(const n of t.keys())H(n,n,t,new Set)&&e.add(n);return e}(i);return{fanInByIndex:r,fanOutByIndex:o,recursiveIndexes:u,metrics:{callCount:a,uniqueCalleeCount:c.size,internalCallCount:s,internalEdgeCount:rt([...i.values()].map(t=>t.size)),recursiveFunctionCount:u.size,maxFanIn:nt(r),maxFanOut:nt(o),maxCallDepth:K(i)}}}(r);return{functions:r.map(t=>({name:t.name,startLine:t.startLine,startColumn:t.startColumn,endLine:t.endLine,returnsJsx:t.returnsJsx,cyclomaticComplexity:t.cyclomaticComplexity,cognitiveComplexity:t.cognitiveComplexity,callCount:t.callCount,uniqueCalleeCount:t.callees.size,fanIn:o.fanInByIndex.get(t.index)??0,fanOut:o.fanOutByIndex.get(t.index)??0,parameterCount:t.parameterCount,recursive:o.recursiveIndexes.has(t.index)})),callGraph:o.metrics,coupling:F(t,n),module:C(t,n),cohesion:S(r),syntaxFeatures:v(t),typeComplexity:N(t)}}(d,l(d,new Set(i.functionNodeTypes)),i),m=p.functions,y=c(d,i,0,!1),h=function(t,e){const n=0===t.length?[]:t.split(/\r\n|\n|\r/),r=function(t){const e=[];function n(t){if("comment"===t.type||"line_comment"===t.type||"block_comment"===t.type)for(let n=t.startPosition.row;n<=t.endPosition.row;n+=1)e.push({line:n,startColumn:n===t.startPosition.row?t.startPosition.column:0,endColumn:n===t.endPosition.row?t.endPosition.column:Number.POSITIVE_INFINITY});for(const e of t.namedChildren)n(e)}return n(t),e}(e);let o=0,i=0;for(const[t,e]of n.entries())""!==e.trim()?T(e,t,r)&&(i+=1):o+=1;return{total:n.length,code:n.length-o-i,comment:i,blank:o}}(e,d),_=function(t,e){const n=new Map,i=new Map;function a(t){if("comment"!==t.type){if(0===t.childCount){const a=e.slice(t.startIndex,t.endIndex);return void(r.has(a)||r.has(t.type)?tt(n,a||t.type):o.has(t.type)&&tt(i,a))}r.has(t.type)&&tt(n,t.type);for(const e of t.children)a(e)}}a(t);const s=n.size,c=i.size,u=rt(n.values()),l=rt(i.values()),f=s+c,d=u+l,p=0===f?0:d*Math.log2(f),m=0===c?0:s/2*(l/c),y=m*p;return{distinctOperators:s,distinctOperands:c,totalOperators:u,totalOperands:l,vocabulary:f,length:d,volume:p,difficulty:m,effort:y,time:y/18,bugs:p/3e3}}(d,e);return{language:i.name,bytes:Buffer.byteLength(e),lines:h,functions:m,classCount:l(d,new Set(i.classNodeTypes)).length,functionCount:m.length,cyclomaticComplexity:y.cyclomaticComplexity,maxCyclomaticComplexity:et(m,"cyclomaticComplexity"),cognitiveComplexity:y.cognitiveComplexity,maxCognitiveComplexity:et(m,"cognitiveComplexity"),nestingDepth:y.nestingDepth,callGraph:p.callGraph,coupling:p.coupling,module:p.module,cohesion:p.cohesion,syntaxFeatures:p.syntaxFeatures,typeComplexity:p.typeComplexity,duplication:z(d),halstead:_,maintainabilityIndex:Z(_.volume,y.cyclomaticComplexity,h.code),syntaxTree:n.includeSyntaxTree?d.toString():void 0}}}const a=new i;function s(t){const e=t.childForFieldName("parameters")??t.namedChildren.find(t=>"formal_parameters"===t.type||"parameter_list"===t.type);return e?e.namedChildren.filter(t=>"comment"!==t.type).length:0}function c(t,e,r,o){let i=1,a=0,s=r;const c=new Set(e.functionNodeTypes),u=new Set(e.decisionNodeTypes),l=new Set(e.nestingNodeTypes);function f(t,e,r){if(o&&c.has(t.type))return;const d=u.has(t.type),p=l.has(t.type);d&&(i+=1,a+=1+e),function(t){if(t.isNamed)return!1;return n.has(t.text)}(t)&&(i+=1,a+=1);const m=p?e+1:e;s=Math.max(s,m);for(const e of t.children)f(e,m)}for(const e of t.children)f(e,r);return{cyclomaticComplexity:i,cognitiveComplexity:a,nestingDepth:s}}function u(t){const e=new Set;return function t(n){"identifier"!==n.type&&"property_identifier"!==n.type&&"field_identifier"!==n.type||e.add(n.text);for(const e of n.namedChildren)t(e)}(t),e}function l(t,e){const n=[];return function t(r){e.has(r.type)&&n.push(r);for(const e of r.namedChildren)t(e)}(t),n}function f(t,e){const n=new Set(e.functionNodeTypes);return function e(r,o){if(!o&&n.has(r.type))return!1;if("return_statement"===r.type)return p(r,n)||m(r,n);if("arrow_function"===t.type&&r===d(t)&&"statement_block"!==r.type&&!n.has(r.type))return p(r,n)||m(r,n);for(const t of r.namedChildren)if(e(t,!1))return!0;return!1}(t,!0)}function d(t){return t.childForFieldName("body")??t.namedChild(t.namedChildCount-1)??void 0}function p(t,e){return y(t,e,t=>t.type.startsWith("jsx_")||function(t,e){if(!A(t)||!function(t){if(!t)return!1;const e=$(t);return"map"===e||"flatMap"===e}(t.childForFieldName("function")??t.namedChild(0)))return!1;return t.namedChildren.some(t=>h(t,e))}(t,e))}function m(t,e){return y(t,e,B)}function y(t,e,n){return function t(r,o){if(!o&&e.has(r.type))return!1;if(n(r))return!0;for(const e of r.namedChildren)if(t(e,!1))return!0;return!1}(t,!0)}function h(t,e){return e.has(t.type)?function(t,e){const n="arrow_function"===t.type?d(t):void 0;if(n&&"statement_block"!==n.type&&!e.has(n.type))return p(n,e)||m(n,e);return function(t,e,n){function r(t,o){if(!o&&e.has(t.type))return!1;if("return_statement"===t.type&&n(t))return!0;for(const e of t.namedChildren)if(r(e,!1))return!0;return!1}return r(t,!0)}(t,e,t=>p(t,e)||m(t,e))}(t,e):t.namedChildren.some(t=>h(t,e))}function C(t,e){const n=new Set;return function t(r){if(O(r))for(const t of j(r,e,{expandPythonSubmodules:!0}))n.add(t);for(const e of r.namedChildren)t(e)}(t),{declarations:_(t),importSources:[...n]}}function _(t){const e=function(t){const e=new Set;function n(t,r){if(!r&&function(t){return"export_specifier"===t.type||"namespace_export"===t.type}(t)){const n=function(t){const e=t.childForFieldName("name")??t.childForFieldName("alias")??t.namedChildren.find(w);return e&&w(e)?e.text:void 0}(t);n&&e.add(n)}const o=r||g(t)&&null!==t.childForFieldName("source");for(const e of t.namedChildren)n(e,o)}return n(t,!1),e}(t);return t.namedChildren.flatMap(t=>x(t,!1)).map(t=>e.has(t.name)?{...t,exported:!0}:t)}function x(t,e){return g(t)?t.namedChildren.flatMap(t=>x(t,!0)):function(t){return"lexical_declaration"===t.type||"variable_declaration"===t.type||"decorated_definition"===t.type||"type_declaration"===t.type||"const_declaration"===t.type||"var_declaration"===t.type||"var_spec_list"===t.type}(t)?t.namedChildren.flatMap(t=>x(t,e)):function(t,e){if(!function(t){return"function_declaration"===t.type||"function_definition"===t.type||"function_item"===t.type||"method_declaration"===t.type||"class_declaration"===t.type||"class_definition"===t.type||"interface_declaration"===t.type||"type_alias_declaration"===t.type||"type_declaration"===t.type||"type_spec"===t.type||"const_spec"===t.type||"var_spec"===t.type||"variable_declarator"===t.type}(t))return[];const n=function(t){if("method_declaration"===t.type)return function(t){const e=t.childForFieldName("name"),n=t.childForFieldName("receiver")?.namedChildren[0]?.childForFieldName("type");if(!e||!w(e)||!n)return e&&w(e)?e.text:void 0;return`${r=n.text,r.replaceAll(/\s+/gu,"").replace(/^\*+/u,"")}.${e.text}`;var r}(t);const e=t.childForFieldName("name");if(e)return w(e)?e.text:void 0;return t.namedChildren.find(w)?.text}(t);return n?[{exported:e,name:n,startLine:t.startPosition.row+1}]:[]}(t,e)}function g(t){return"export_statement"===t.type||"export_declaration"===t.type}function w(t){return"identifier"===t.type||"type_identifier"===t.type||"property_identifier"===t.type||"field_identifier"===t.type}function F(t,e){const n=new Set;let r=0,o=0;!function t(i){if((E(i)||R(i))&&(r+=1),O(i))for(const t of j(i,e,{expandPythonSubmodules:!1}))n.add(t);Y(i)&&(o+=1);for(const e of i.namedChildren)t(e)}(t);const i=[...n].filter(q).length;return{importCount:r,importSourceCount:n.size,relativeImportCount:i,externalImportCount:n.size-i,exportCount:o}}function v(t){const e={assignmentCount:0,awaitExpressionCount:0,loopStatementCount:0,mutableBindingCount:0,returnStatementCount:0,throwStatementCount:0,tryStatementCount:0};return function t(n){(function(t){return"assignment_expression"===t.type||"augmented_assignment_expression"===t.type||"assignment_statement"===t.type||"assignment"===t.type||"augmented_assignment"===t.type||"short_var_declaration"===t.type})(n)&&(e.assignmentCount+=1),function(t){return"await_expression"===t.type||"await"===t.type}(n)&&(e.awaitExpressionCount+=1),function(t){return"for_statement"===t.type||"for_in_statement"===t.type||"while_statement"===t.type||"do_statement"===t.type}(n)&&(e.loopStatementCount+=1),function(t){return"lexical_declaration"===t.type&&"let"===t.firstChild?.text||"variable_declaration"===t.type&&"var"===t.firstChild?.text||"var_declaration"===t.type}(n)&&(e.mutableBindingCount+=1),function(t){return"return_statement"===t.type}(n)&&(e.returnStatementCount+=1),function(t){return"throw_statement"===t.type||"raise_statement"===t.type}(n)&&(e.throwStatementCount+=1),function(t){return"try_statement"===t.type}(n)&&(e.tryStatementCount+=1);for(const e of n.namedChildren)t(e)}(t),e}function S(t){const e=new Set,n=new Set;let r=0,o=0;for(const n of t)for(const t of n.identifiers)e.add(t);for(let e=0;e<t.length;e+=1)for(let i=e+1;i<t.length;i+=1){const a=t[e],s=t[i];if(!a||!s)continue;const c=X(a.identifiers,s.identifiers),u=new Set([...a.identifiers,...s.identifiers]).size;for(const t of c)n.add(t);r+=0===u?0:c.size/u,o+=1}return{averageFunctionIdentifierOverlap:0===o?1:r/o,sharedIdentifierCount:n.size,uniqueIdentifierCount:e.size}}function N(t){const e={typeAnnotationCount:0,typeAliasCount:0,interfaceCount:0,genericParameterCount:0,unionTypeCount:0,intersectionTypeCount:0,conditionalTypeCount:0,typeAssertionCount:0,nonNullAssertionCount:0,satisfiesExpressionCount:0};return function t(n){switch(n.type){case"type_annotation":e.typeAnnotationCount+=1;break;case"type_alias_declaration":e.typeAliasCount+=1;break;case"interface_declaration":e.interfaceCount+=1;break;case"type_parameters":case"type_parameter":e.genericParameterCount+="type_parameter"===n.type?1:0;break;case"union_type":e.unionTypeCount+=1;break;case"intersection_type":e.intersectionTypeCount+=1;break;case"conditional_type":e.conditionalTypeCount+=1;break;case"as_expression":case"type_assertion":e.typeAssertionCount+=1;break;case"non_null_expression":e.nonNullAssertionCount+=1;break;case"satisfies_expression":e.satisfiesExpressionCount+=1}for(const e of n.namedChildren)t(e)}(t),e}const b=new Set(["statement_block","block","if_statement","for_statement","for_in_statement","while_statement","do_statement","try_statement","with_statement","switch_statement","switch_case","case_clause","match_statement","match_arm","except_clause","catch_clause","finally_clause","elif_clause","expression_statement","return_statement","jsx_element","jsx_self_closing_element"]),M=24;function z(t){const e=[],n=new Map;!function t(r){if(b.has(r.type)){const{size:t}=I(r,n);if(t>=M){const{shape:o}=I(r,n);e.push({node:r,shape:o,size:t})}}for(const e of r.namedChildren)t(e)}(t);const r=new Map;for(const t of e){const e=r.get(t.shape)??[];e.push(t),r.set(t.shape,e)}const o=[];let i=0,a=0;const s=new Map;for(const[t,e]of r)if(!(e.length<2))for(const n of e.toSorted((t,e)=>e.size-t.size))o.some(t=>k(t,n.node))||(o.push(n.node),s.set(t,(s.get(t)??0)+1),a=Math.max(a,n.size));let c=0;for(const t of s.values())t>=2&&(i+=t-1,c+=1);return{duplicateBlockCount:i,duplicateBlockGroupCount:c,maxDuplicateBlockSize:a}}function I(t,e){const n=e.get(t.id);if(n)return n;let r=t.type,o=1;if(t.namedChildCount>0){const n=[];for(const r of t.namedChildren){const t=I(r,e);n.push(t.shape),o+=t.size}r=`${t.type}(${n.join(",")})`}const i={shape:r,size:o};return e.set(t.id,i),i}function k(t,e){let n=e.parent;for(;n;){if(n.id===t.id)return!0;n=n.parent}return!1}function T(t,e,n){const r=n.filter(t=>t.line===e);if(0===r.length)return!1;const o=t.search(/\S/),i=t.trimEnd().length;return r.some(t=>t.startColumn<=o&&t.endColumn>=i)}function P(t){const e=function(t){let e=t;for(;e;){const t=e.parent,n=t?.parent;if("arguments"!==t?.type||"call_expression"!==n?.type)return;if(!L(n))return;const r=n.parent;if("variable_declarator"===r?.type)return r.childForFieldName("name")?.text;e=n}return}(t);if(e)return e;const n=t.childForFieldName("name");if(n)return n.text;const r=t.parent;if(!r)return;const o=r.childForFieldName("name");return o?.text}function L(t){const e=t.childForFieldName("function")??t.namedChild(0);return"memo"===e?.text||"React.memo"===e?.text||"forwardRef"===e?.text||"React.forwardRef"===e?.text}function A(t){return"call_expression"===t.type||"call"===t.type}function $(t){if("identifier"===t.type||"property_identifier"===t.type||"field_identifier"===t.type||"attribute"===t.type)return t.text;for(let e=t.namedChildCount-1;e>=0;e-=1){const n=t.namedChild(e);if(!n)continue;const r=$(n);if(r)return r}}function B(t){if(!A(t))return!1;const e=t.childForFieldName("function")??t.namedChild(0);return"React.createElement"===e?.text||"createElement"===e?.text}function E(t){return"import_statement"===t.type||"import_declaration"===t.type||"import_from_statement"===t.type||"import_spec"===t.type||"import_spec_list"===t.type}function O(t){return E(t)||R(t)||Y(t)&&null!==t.childForFieldName("source")}function R(t){if(!A(t))return!1;const e=t.childForFieldName("function")??t.namedChild(0);return"import"===e?.text}function j(t,e,n){if("python"===e.name){const e=function(t,e){if("import_from_statement"===t.type){const n=t.childForFieldName("module_name");if(!n)return[];const r=G(n.text),o=function(t,e){const n=[];for(let r=0;r<t.childCount;r+=1){const o=t.child(r);o&&t.fieldNameForChild(r)===e&&n.push(o)}return n}(t,"name");if(!e.expandPythonSubmodules||!r.startsWith("."))return[r];if(/^\.+$/u.test(r)&&o.length>0)return o.flatMap(D).map(t=>`${r}${t}`);const i=o.flatMap(D).map(t=>`${r}.${t}`);return i.length>0?[r,...i]:[r]}if("import_statement"!==t.type)return[];return t.namedChildren.map(t=>W(t)).filter(t=>void 0!==t)}(t,n);if(e.length>0)return e}if(R(t))return function(t){const e=t.childForFieldName("arguments"),n=e?.namedChild(0);return n&&U(n)?[V(n.text)]:[]}(t);const r=t.childForFieldName("source")??J(t);return r?[V(r.text)]:[]}function q(t){return t.startsWith(".")||t.startsWith("/")}function D(t){if("aliased_import"===t.type){const e=t.childForFieldName("name");return e?D(e):[]}return"identifier"===t.type?[t.text]:"dotted_name"===t.type?[G(t.text)]:t.namedChildren.flatMap(D)}function W(t){if("dotted_name"===t.type||"relative_import"===t.type)return G(t.text);const e=t.childForFieldName("name");if(e)return G(e.text);for(const e of t.namedChildren){const t=W(e);if(t)return t}}function G(t){return t.replaceAll(/\s+/gu,"")}function J(t){if(U(t))return t;for(const e of t.namedChildren){const t=J(e);if(t)return t}}function U(t){return"string"===t.type||"string_literal"===t.type||"interpreted_string_literal"===t.type}function V(t){return t.replaceAll(/^['"`]|['"`]$/gu,"")}function Y(t){return t.type.startsWith("export")||"public_field_definition"===t.type}function H(t,e,n,r){const o=n.get(t);if(!o)return!1;for(const t of o){if(t===e)return!0;if(!r.has(t)&&(r.add(t),H(t,e,n,r)))return!0}return!1}function K(t){let e=0;for(const n of t.keys())e=Math.max(e,Q(n,t,new Set));return e}function Q(t,e,n){const r=e.get(t);if(!r||0===r.size||n.has(t))return 0;n.add(t);let o=0;for(const t of r)o=Math.max(o,1+Q(t,e,new Set(n)));return o}function X(t,e){const n=new Set;for(const r of t)e.has(r)&&n.add(r);return n}function Z(t,e,n){if(0===n)return 100;const r=171-5.2*Math.log(Math.max(t,1))-.23*e-16.2*Math.log(n);return Math.max(0,Math.min(100,100*r/171))}function tt(t,e){t.set(e,(t.get(e)??0)+1)}function et(t,e){return 0===t.length?0:Math.max(...t.map(t=>t[e]))}function nt(t){let e=0;for(const n of t.values())e=Math.max(e,n);return e}function rt(t){let e=0;for(const n of t)e+=n;return e}exports.TreeMeasurer=i,exports.defaultMeasurer=a,exports.measureCode=function(t,e){return a.measure(t,e)};
|
|
2
|
+
//# sourceMappingURL=metrics.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.cjs","sources":["../src/metrics.ts"],"sourcesContent":["import Parser from 'tree-sitter';\nimport { createLanguageRegistry } from './languages.js';\nimport type {\n CallGraphMetrics,\n CodeMetrics,\n CohesionMetrics,\n CouplingMetrics,\n DeclarationMetrics,\n DuplicationMetrics,\n FunctionMetrics,\n HalsteadMetrics,\n LanguageDefinition,\n LanguageName,\n MeasureOptions,\n ModuleMetrics,\n SyntaxFeatureMetrics,\n TypeComplexityMetrics,\n} from './types.js';\n\nconst booleanOperators = new Set(['&&', '||', 'and', 'or']);\nconst operatorTexts = new Set([\n '+',\n '-',\n '*',\n '/',\n '%',\n '**',\n '=',\n '+=',\n '-=',\n '*=',\n '/=',\n '%=',\n '==',\n '!=',\n '===',\n '!==',\n '<',\n '<=',\n '>',\n '>=',\n '!',\n '~',\n '&',\n '|',\n '^',\n '<<',\n '>>',\n '=>',\n 'return',\n 'throw',\n 'yield',\n 'await',\n 'break',\n 'continue',\n]);\n\nconst operandNodeTypes = new Set([\n 'identifier',\n 'property_identifier',\n 'field_identifier',\n 'type_identifier',\n 'number',\n 'integer',\n 'float',\n 'string',\n 'string_literal',\n 'template_string',\n 'character_literal',\n 'true',\n 'false',\n 'null',\n 'undefined',\n 'nil',\n]);\n\ninterface ComplexityResult {\n cyclomaticComplexity: number;\n cognitiveComplexity: number;\n nestingDepth: number;\n}\n\ninterface CommentSpan {\n line: number;\n startColumn: number;\n endColumn: number;\n}\n\ninterface FunctionAnalysis {\n index: number;\n name?: string;\n startLine: number;\n startColumn: number;\n endLine: number;\n returnsJsx: boolean;\n cyclomaticComplexity: number;\n cognitiveComplexity: number;\n callCount: number;\n parameterCount: number;\n callees: Set<string>;\n identifiers: Set<string>;\n}\n\ninterface StructuralMetrics {\n callGraph: CallGraphMetrics;\n cohesion: CohesionMetrics;\n coupling: CouplingMetrics;\n functions: FunctionMetrics[];\n module: ModuleMetrics;\n syntaxFeatures: SyntaxFeatureMetrics;\n typeComplexity: TypeComplexityMetrics;\n}\n\nexport class TreeMeasurer {\n private readonly registry = createLanguageRegistry();\n\n registerLanguage(language: LanguageDefinition): void {\n this.registry.set(language.name, language);\n for (const alias of language.aliases ?? []) {\n this.registry.set(alias, language);\n }\n }\n\n getSupportedLanguages(): LanguageName[] {\n return [...new Set([...this.registry.values()].map((language) => language.name))];\n }\n\n measure(code: string, options: MeasureOptions): CodeMetrics {\n const language = this.registry.get(options.language);\n if (!language) {\n throw new Error(`Unsupported language: ${options.language}`);\n }\n\n const parser = new Parser();\n parser.setLanguage(language.parserLanguage);\n const tree = parser.parse(code, undefined, {\n bufferSize: code.length + 1,\n });\n const root = tree.rootNode;\n const functions = collectNodes(root, new Set(language.functionNodeTypes));\n const structuralMetrics = measureStructuralMetrics(root, functions, language);\n const functionMetrics = structuralMetrics.functions;\n const globalComplexity = measureComplexity(root, language, 0, false);\n const lines = measureLines(code, root);\n const halstead = measureHalstead(root, code);\n\n return {\n language: language.name,\n bytes: Buffer.byteLength(code),\n lines,\n functions: functionMetrics,\n classCount: collectNodes(root, new Set(language.classNodeTypes)).length,\n functionCount: functionMetrics.length,\n cyclomaticComplexity: globalComplexity.cyclomaticComplexity,\n maxCyclomaticComplexity: maxMetric(functionMetrics, 'cyclomaticComplexity'),\n cognitiveComplexity: globalComplexity.cognitiveComplexity,\n maxCognitiveComplexity: maxMetric(functionMetrics, 'cognitiveComplexity'),\n nestingDepth: globalComplexity.nestingDepth,\n callGraph: structuralMetrics.callGraph,\n coupling: structuralMetrics.coupling,\n module: structuralMetrics.module,\n cohesion: structuralMetrics.cohesion,\n syntaxFeatures: structuralMetrics.syntaxFeatures,\n typeComplexity: structuralMetrics.typeComplexity,\n duplication: measureDuplication(root),\n halstead,\n maintainabilityIndex: calculateMaintainabilityIndex(\n halstead.volume,\n globalComplexity.cyclomaticComplexity,\n lines.code\n ),\n syntaxTree: options.includeSyntaxTree ? root.toString() : undefined,\n };\n }\n}\n\nexport const defaultMeasurer = new TreeMeasurer();\n\nexport function measureCode(code: string, options: MeasureOptions): CodeMetrics {\n return defaultMeasurer.measure(code, options);\n}\n\nfunction measureStructuralMetrics(\n root: Parser.SyntaxNode,\n functions: Parser.SyntaxNode[],\n language: LanguageDefinition\n): StructuralMetrics {\n const analyses = functions.map((node, index) => analyzeFunction(node, language, index));\n const callGraph = measureCallGraph(analyses);\n const functionsWithGraph = analyses.map((analysis) => ({\n name: analysis.name,\n startLine: analysis.startLine,\n startColumn: analysis.startColumn,\n endLine: analysis.endLine,\n returnsJsx: analysis.returnsJsx,\n cyclomaticComplexity: analysis.cyclomaticComplexity,\n cognitiveComplexity: analysis.cognitiveComplexity,\n callCount: analysis.callCount,\n uniqueCalleeCount: analysis.callees.size,\n fanIn: callGraph.fanInByIndex.get(analysis.index) ?? 0,\n fanOut: callGraph.fanOutByIndex.get(analysis.index) ?? 0,\n parameterCount: analysis.parameterCount,\n recursive: callGraph.recursiveIndexes.has(analysis.index),\n }));\n\n return {\n functions: functionsWithGraph,\n callGraph: callGraph.metrics,\n coupling: measureCoupling(root, language),\n module: measureModule(root, language),\n cohesion: measureCohesion(analyses),\n syntaxFeatures: measureSyntaxFeatures(root),\n typeComplexity: measureTypeComplexity(root),\n };\n}\n\nfunction analyzeFunction(node: Parser.SyntaxNode, language: LanguageDefinition, index: number): FunctionAnalysis {\n const complexity = measureComplexity(node, language, 0, true);\n const calls = collectCalls(node, language);\n return {\n index,\n name: findFunctionName(node),\n startLine: node.startPosition.row + 1,\n startColumn: node.startPosition.column,\n endLine: node.endPosition.row + 1,\n returnsJsx: returnsJsx(node, language),\n cyclomaticComplexity: complexity.cyclomaticComplexity,\n cognitiveComplexity: complexity.cognitiveComplexity,\n callCount: calls.callCount,\n parameterCount: countParameters(node),\n callees: calls.callees,\n identifiers: collectIdentifiers(node),\n };\n}\n\n/** Counts declared parameters of a function/method, ignoring punctuation and comments. */\nfunction countParameters(node: Parser.SyntaxNode): number {\n const parametersNode =\n node.childForFieldName('parameters') ??\n node.namedChildren.find((child) => child.type === 'formal_parameters' || child.type === 'parameter_list');\n if (!parametersNode) {\n return 0;\n }\n\n return parametersNode.namedChildren.filter((child) => child.type !== 'comment').length;\n}\n\nfunction measureCallGraph(analyses: FunctionAnalysis[]): {\n fanInByIndex: Map<number, number>;\n fanOutByIndex: Map<number, number>;\n metrics: CallGraphMetrics;\n recursiveIndexes: Set<number>;\n} {\n const indexesByName = mapUniqueFunctionIndexesByName(analyses);\n const functionNames = new Set(indexesByName.keys());\n const fanInByIndex = new Map<number, number>();\n const fanOutByIndex = new Map<number, number>();\n const graph = new Map<number, Set<number>>();\n let callCount = 0;\n let internalCallCount = 0;\n const allCallees = new Set<string>();\n\n for (const analysis of analyses) {\n callCount += analysis.callCount;\n for (const callee of analysis.callees) {\n allCallees.add(callee);\n }\n\n const internalCalleeNames = new Set([...analysis.callees].filter((callee) => functionNames.has(callee)));\n const internalCalleeIndexes = new Set<number>();\n for (const callee of internalCalleeNames) {\n const calleeIndex = indexesByName.get(callee);\n if (calleeIndex !== undefined) {\n internalCalleeIndexes.add(calleeIndex);\n }\n }\n\n graph.set(analysis.index, internalCalleeIndexes);\n fanOutByIndex.set(analysis.index, internalCalleeNames.size);\n internalCallCount += internalCalleeNames.size;\n for (const calleeIndex of internalCalleeIndexes) {\n fanInByIndex.set(calleeIndex, (fanInByIndex.get(calleeIndex) ?? 0) + 1);\n }\n }\n\n const recursiveIndexes = findRecursiveIndexes(graph);\n\n return {\n fanInByIndex,\n fanOutByIndex,\n recursiveIndexes,\n metrics: {\n callCount,\n uniqueCalleeCount: allCallees.size,\n internalCallCount,\n internalEdgeCount: sum([...graph.values()].map((callees) => callees.size)),\n recursiveFunctionCount: recursiveIndexes.size,\n maxFanIn: maxMapValue(fanInByIndex),\n maxFanOut: maxMapValue(fanOutByIndex),\n maxCallDepth: measureMaxCallDepth(graph),\n },\n };\n}\n\nfunction mapUniqueFunctionIndexesByName(analyses: FunctionAnalysis[]): Map<string, number> {\n const indexesByName = new Map<string, number | undefined>();\n for (const analysis of analyses) {\n if (!analysis.name) {\n continue;\n }\n\n indexesByName.set(analysis.name, indexesByName.has(analysis.name) ? undefined : analysis.index);\n }\n return new Map([...indexesByName.entries()].filter((entry): entry is [string, number] => entry[1] !== undefined));\n}\n\nfunction measureComplexity(\n node: Parser.SyntaxNode,\n language: LanguageDefinition,\n nesting: number,\n stopAtNestedFunctions: boolean\n): ComplexityResult {\n let cyclomaticComplexity = 1;\n let cognitiveComplexity = 0;\n let nestingDepth = nesting;\n const functionNodes = new Set(language.functionNodeTypes);\n const decisionNodes = new Set(language.decisionNodeTypes);\n const nestingNodes = new Set(language.nestingNodeTypes);\n\n function visit(current: Parser.SyntaxNode, currentNesting: number, insideRoot: boolean): void {\n if (stopAtNestedFunctions && !insideRoot && functionNodes.has(current.type)) {\n return;\n }\n\n const isDecision = decisionNodes.has(current.type);\n const isNesting = nestingNodes.has(current.type);\n\n if (isDecision) {\n cyclomaticComplexity += 1;\n cognitiveComplexity += 1 + currentNesting;\n }\n\n if (isBooleanOperator(current)) {\n cyclomaticComplexity += 1;\n cognitiveComplexity += 1;\n }\n\n const childNesting = isNesting ? currentNesting + 1 : currentNesting;\n nestingDepth = Math.max(nestingDepth, childNesting);\n\n for (const child of current.children) {\n visit(child, childNesting, false);\n }\n }\n\n for (const child of node.children) {\n visit(child, nesting, false);\n }\n\n return { cyclomaticComplexity, cognitiveComplexity, nestingDepth };\n}\n\nfunction isBooleanOperator(node: Parser.SyntaxNode): boolean {\n if (node.isNamed) {\n return false;\n }\n\n return booleanOperators.has(node.text);\n}\n\nfunction collectCalls(\n root: Parser.SyntaxNode,\n language: LanguageDefinition\n): { callCount: number; callees: Set<string> } {\n const callees = new Set<string>();\n const functionNodeTypes = new Set(language.functionNodeTypes);\n let callCount = 0;\n\n function visit(node: Parser.SyntaxNode, insideRoot: boolean): void {\n if (!insideRoot && functionNodeTypes.has(node.type)) {\n return;\n }\n\n if (isCallNode(node)) {\n callCount += 1;\n const callee = findCalleeName(node);\n if (callee) {\n callees.add(callee);\n }\n }\n\n for (const child of node.namedChildren) {\n visit(child, false);\n }\n }\n\n visit(root, true);\n return { callCount, callees };\n}\n\nfunction collectIdentifiers(root: Parser.SyntaxNode): Set<string> {\n const identifiers = new Set<string>();\n\n function visit(node: Parser.SyntaxNode): void {\n if (node.type === 'identifier' || node.type === 'property_identifier' || node.type === 'field_identifier') {\n identifiers.add(node.text);\n }\n\n for (const child of node.namedChildren) {\n visit(child);\n }\n }\n\n visit(root);\n return identifiers;\n}\n\nfunction collectNodes(root: Parser.SyntaxNode, nodeTypes: Set<string>): Parser.SyntaxNode[] {\n const nodes: Parser.SyntaxNode[] = [];\n\n function visit(node: Parser.SyntaxNode): void {\n if (nodeTypes.has(node.type)) {\n nodes.push(node);\n }\n\n for (const child of node.namedChildren) {\n visit(child);\n }\n }\n\n visit(root);\n return nodes;\n}\n\nfunction returnsJsx(root: Parser.SyntaxNode, language: LanguageDefinition): boolean {\n const functionNodeTypes = new Set(language.functionNodeTypes);\n\n function visit(node: Parser.SyntaxNode, insideRoot: boolean): boolean {\n if (!insideRoot && functionNodeTypes.has(node.type)) {\n return false;\n }\n\n if (node.type === 'return_statement') {\n return containsJsxExpression(node, functionNodeTypes) || containsReactCreateElementCall(node, functionNodeTypes);\n }\n\n if (\n root.type === 'arrow_function' &&\n node === getArrowFunctionBody(root) &&\n node.type !== 'statement_block' &&\n !functionNodeTypes.has(node.type)\n ) {\n return containsJsxExpression(node, functionNodeTypes) || containsReactCreateElementCall(node, functionNodeTypes);\n }\n\n for (const child of node.namedChildren) {\n if (visit(child, false)) {\n return true;\n }\n }\n return false;\n }\n\n return visit(root, true);\n}\n\nfunction getArrowFunctionBody(node: Parser.SyntaxNode): Parser.SyntaxNode | undefined {\n return node.childForFieldName('body') ?? node.namedChild(node.namedChildCount - 1) ?? undefined;\n}\n\nfunction containsJsxExpression(root: Parser.SyntaxNode, functionNodeTypes: Set<string>): boolean {\n return containsNode(\n root,\n functionNodeTypes,\n (node) => node.type.startsWith('jsx_') || isJsxMappingCall(node, functionNodeTypes)\n );\n}\n\nfunction containsReactCreateElementCall(root: Parser.SyntaxNode, functionNodeTypes: Set<string>): boolean {\n return containsNode(root, functionNodeTypes, isReactCreateElementCall);\n}\n\nfunction containsNode(\n root: Parser.SyntaxNode,\n functionNodeTypes: Set<string>,\n predicate: (node: Parser.SyntaxNode) => boolean\n): boolean {\n function visit(node: Parser.SyntaxNode, insideRoot: boolean): boolean {\n if (!insideRoot && functionNodeTypes.has(node.type)) {\n return false;\n }\n\n if (predicate(node)) {\n return true;\n }\n\n for (const child of node.namedChildren) {\n if (visit(child, false)) {\n return true;\n }\n }\n return false;\n }\n\n return visit(root, true);\n}\n\nfunction isJsxMappingCall(node: Parser.SyntaxNode, functionNodeTypes: Set<string>): boolean {\n if (!isCallNode(node) || !isArrayMappingCallee(node.childForFieldName('function') ?? node.namedChild(0))) {\n return false;\n }\n\n return node.namedChildren.some((child) => containsReturnedJsxFunction(child, functionNodeTypes));\n}\n\nfunction isArrayMappingCallee(node: Parser.SyntaxNode | null): boolean {\n if (!node) {\n return false;\n }\n\n const calleeName = findRightmostIdentifier(node);\n return calleeName === 'map' || calleeName === 'flatMap';\n}\n\nfunction containsReturnedJsxFunction(root: Parser.SyntaxNode, functionNodeTypes: Set<string>): boolean {\n if (functionNodeTypes.has(root.type)) {\n return returnsJsxFromFunctionNode(root, functionNodeTypes);\n }\n\n return root.namedChildren.some((child) => containsReturnedJsxFunction(child, functionNodeTypes));\n}\n\nfunction returnsJsxFromFunctionNode(root: Parser.SyntaxNode, functionNodeTypes: Set<string>): boolean {\n const body = root.type === 'arrow_function' ? getArrowFunctionBody(root) : undefined;\n if (body && body.type !== 'statement_block' && !functionNodeTypes.has(body.type)) {\n return containsJsxExpression(body, functionNodeTypes) || containsReactCreateElementCall(body, functionNodeTypes);\n }\n\n return containsOwnReturnNode(\n root,\n functionNodeTypes,\n (node) => containsJsxExpression(node, functionNodeTypes) || containsReactCreateElementCall(node, functionNodeTypes)\n );\n}\n\nfunction containsOwnReturnNode(\n root: Parser.SyntaxNode,\n functionNodeTypes: Set<string>,\n predicate: (node: Parser.SyntaxNode) => boolean\n): boolean {\n function visit(node: Parser.SyntaxNode, insideRoot: boolean): boolean {\n if (!insideRoot && functionNodeTypes.has(node.type)) {\n return false;\n }\n\n if (node.type === 'return_statement' && predicate(node)) {\n return true;\n }\n\n for (const child of node.namedChildren) {\n if (visit(child, false)) {\n return true;\n }\n }\n return false;\n }\n\n return visit(root, true);\n}\n\nfunction measureModule(root: Parser.SyntaxNode, language: LanguageDefinition): ModuleMetrics {\n const importSources = new Set<string>();\n\n function visitImports(node: Parser.SyntaxNode): void {\n if (isImportSourceNode(node)) {\n for (const source of findImportSources(node, language, { expandPythonSubmodules: true })) {\n importSources.add(source);\n }\n }\n\n for (const child of node.namedChildren) {\n visitImports(child);\n }\n }\n\n visitImports(root);\n\n return {\n declarations: collectModuleDeclarations(root),\n importSources: [...importSources],\n };\n}\n\nfunction collectModuleDeclarations(root: Parser.SyntaxNode): DeclarationMetrics[] {\n const exportedNames = collectExportedNames(root);\n return root.namedChildren\n .flatMap((child) => collectTopLevelDeclarations(child, false))\n .map((declaration) => (exportedNames.has(declaration.name) ? { ...declaration, exported: true } : declaration));\n}\n\nfunction collectTopLevelDeclarations(node: Parser.SyntaxNode, exported: boolean): DeclarationMetrics[] {\n if (isModuleExportNode(node)) {\n return node.namedChildren.flatMap((child) => collectTopLevelDeclarations(child, true));\n }\n\n if (isDeclarationContainer(node)) {\n return node.namedChildren.flatMap((child) => collectTopLevelDeclarations(child, exported));\n }\n\n return declarationFromNode(node, exported);\n}\n\nfunction declarationFromNode(node: Parser.SyntaxNode, exported: boolean): DeclarationMetrics[] {\n if (!isTopLevelDeclarationNode(node)) {\n return [];\n }\n\n const name = findDeclarationName(node);\n return name ? [{ exported, name, startLine: node.startPosition.row + 1 }] : [];\n}\n\nfunction findDeclarationName(node: Parser.SyntaxNode): string | undefined {\n if (node.type === 'method_declaration') {\n return findGoMethodDeclarationName(node);\n }\n\n const nameNode = node.childForFieldName('name');\n if (nameNode) {\n return isDeclarationNameNode(nameNode) ? nameNode.text : undefined;\n }\n\n return node.namedChildren.find(isDeclarationNameNode)?.text;\n}\n\nfunction isModuleExportNode(node: Parser.SyntaxNode): boolean {\n return node.type === 'export_statement' || node.type === 'export_declaration';\n}\n\nfunction isDeclarationContainer(node: Parser.SyntaxNode): boolean {\n return (\n node.type === 'lexical_declaration' ||\n node.type === 'variable_declaration' ||\n node.type === 'decorated_definition' ||\n node.type === 'type_declaration' ||\n node.type === 'const_declaration' ||\n node.type === 'var_declaration' ||\n node.type === 'var_spec_list'\n );\n}\n\nfunction isTopLevelDeclarationNode(node: Parser.SyntaxNode): boolean {\n return (\n node.type === 'function_declaration' ||\n node.type === 'function_definition' ||\n node.type === 'function_item' ||\n node.type === 'method_declaration' ||\n node.type === 'class_declaration' ||\n node.type === 'class_definition' ||\n node.type === 'interface_declaration' ||\n node.type === 'type_alias_declaration' ||\n node.type === 'type_declaration' ||\n node.type === 'type_spec' ||\n node.type === 'const_spec' ||\n node.type === 'var_spec' ||\n node.type === 'variable_declarator'\n );\n}\n\nfunction isDeclarationNameNode(node: Parser.SyntaxNode): boolean {\n return (\n node.type === 'identifier' ||\n node.type === 'type_identifier' ||\n node.type === 'property_identifier' ||\n node.type === 'field_identifier'\n );\n}\n\nfunction collectExportedNames(root: Parser.SyntaxNode): Set<string> {\n const exportedNames = new Set<string>();\n\n function visit(node: Parser.SyntaxNode, insideSourcedExport: boolean): void {\n if (!insideSourcedExport && isExportSpecifierNode(node)) {\n const name = findExportedName(node);\n if (name) {\n exportedNames.add(name);\n }\n }\n\n const isSourcedExport =\n insideSourcedExport || (isModuleExportNode(node) && node.childForFieldName('source') !== null);\n for (const child of node.namedChildren) {\n visit(child, isSourcedExport);\n }\n }\n\n visit(root, false);\n return exportedNames;\n}\n\nfunction isExportSpecifierNode(node: Parser.SyntaxNode): boolean {\n return node.type === 'export_specifier' || node.type === 'namespace_export';\n}\n\nfunction findExportedName(node: Parser.SyntaxNode): string | undefined {\n const nameNode =\n node.childForFieldName('name') ?? node.childForFieldName('alias') ?? node.namedChildren.find(isDeclarationNameNode);\n return nameNode && isDeclarationNameNode(nameNode) ? nameNode.text : undefined;\n}\n\nfunction findGoMethodDeclarationName(node: Parser.SyntaxNode): string | undefined {\n const nameNode = node.childForFieldName('name');\n const receiverTypeNode = node.childForFieldName('receiver')?.namedChildren[0]?.childForFieldName('type');\n if (!nameNode || !isDeclarationNameNode(nameNode) || !receiverTypeNode) {\n return nameNode && isDeclarationNameNode(nameNode) ? nameNode.text : undefined;\n }\n\n return `${normalizeGoReceiverType(receiverTypeNode.text)}.${nameNode.text}`;\n}\n\nfunction normalizeGoReceiverType(receiverType: string): string {\n return receiverType.replaceAll(/\\s+/gu, '').replace(/^\\*+/u, '');\n}\n\nfunction measureCoupling(root: Parser.SyntaxNode, language: LanguageDefinition): CouplingMetrics {\n const importSources = new Set<string>();\n let importCount = 0;\n let exportCount = 0;\n\n function visit(node: Parser.SyntaxNode): void {\n if (isImportNode(node) || isDynamicImportNode(node)) {\n importCount += 1;\n }\n\n if (isImportSourceNode(node)) {\n for (const source of findImportSources(node, language, { expandPythonSubmodules: false })) {\n importSources.add(source);\n }\n }\n\n if (isExportNode(node)) {\n exportCount += 1;\n }\n\n for (const child of node.namedChildren) {\n visit(child);\n }\n }\n\n visit(root);\n\n const relativeImportCount = [...importSources].filter(isRelativeImportSource).length;\n\n return {\n importCount,\n importSourceCount: importSources.size,\n relativeImportCount,\n externalImportCount: importSources.size - relativeImportCount,\n exportCount,\n };\n}\n\nfunction measureSyntaxFeatures(root: Parser.SyntaxNode): SyntaxFeatureMetrics {\n const metrics: SyntaxFeatureMetrics = {\n assignmentCount: 0,\n awaitExpressionCount: 0,\n loopStatementCount: 0,\n mutableBindingCount: 0,\n returnStatementCount: 0,\n throwStatementCount: 0,\n tryStatementCount: 0,\n };\n\n function visit(node: Parser.SyntaxNode): void {\n if (isAssignmentNode(node)) {\n metrics.assignmentCount += 1;\n }\n if (isAwaitNode(node)) {\n metrics.awaitExpressionCount += 1;\n }\n if (isLoopNode(node)) {\n metrics.loopStatementCount += 1;\n }\n if (isMutableBindingNode(node)) {\n metrics.mutableBindingCount += 1;\n }\n if (isReturnNode(node)) {\n metrics.returnStatementCount += 1;\n }\n if (isThrowNode(node)) {\n metrics.throwStatementCount += 1;\n }\n if (isTryNode(node)) {\n metrics.tryStatementCount += 1;\n }\n\n for (const child of node.namedChildren) {\n visit(child);\n }\n }\n\n visit(root);\n return metrics;\n}\n\nfunction isAssignmentNode(node: Parser.SyntaxNode): boolean {\n return (\n node.type === 'assignment_expression' ||\n node.type === 'augmented_assignment_expression' ||\n node.type === 'assignment_statement' ||\n node.type === 'assignment' ||\n node.type === 'augmented_assignment' ||\n node.type === 'short_var_declaration'\n );\n}\n\nfunction isAwaitNode(node: Parser.SyntaxNode): boolean {\n return node.type === 'await_expression' || node.type === 'await';\n}\n\nfunction isLoopNode(node: Parser.SyntaxNode): boolean {\n return (\n node.type === 'for_statement' ||\n node.type === 'for_in_statement' ||\n node.type === 'while_statement' ||\n node.type === 'do_statement'\n );\n}\n\nfunction isMutableBindingNode(node: Parser.SyntaxNode): boolean {\n return (\n (node.type === 'lexical_declaration' && node.firstChild?.text === 'let') ||\n (node.type === 'variable_declaration' && node.firstChild?.text === 'var') ||\n node.type === 'var_declaration'\n );\n}\n\nfunction isReturnNode(node: Parser.SyntaxNode): boolean {\n return node.type === 'return_statement';\n}\n\nfunction isThrowNode(node: Parser.SyntaxNode): boolean {\n return node.type === 'throw_statement' || node.type === 'raise_statement';\n}\n\nfunction isTryNode(node: Parser.SyntaxNode): boolean {\n return node.type === 'try_statement';\n}\n\nfunction measureCohesion(analyses: FunctionAnalysis[]): CohesionMetrics {\n const allIdentifiers = new Set<string>();\n const sharedIdentifiers = new Set<string>();\n let overlapTotal = 0;\n let pairCount = 0;\n\n for (const analysis of analyses) {\n for (const identifier of analysis.identifiers) {\n allIdentifiers.add(identifier);\n }\n }\n\n for (let leftIndex = 0; leftIndex < analyses.length; leftIndex += 1) {\n for (let rightIndex = leftIndex + 1; rightIndex < analyses.length; rightIndex += 1) {\n const left = analyses[leftIndex];\n const right = analyses[rightIndex];\n if (!left || !right) {\n continue;\n }\n\n const intersection = intersectSets(left.identifiers, right.identifiers);\n const unionSize = new Set([...left.identifiers, ...right.identifiers]).size;\n for (const identifier of intersection) {\n sharedIdentifiers.add(identifier);\n }\n overlapTotal += unionSize === 0 ? 0 : intersection.size / unionSize;\n pairCount += 1;\n }\n }\n\n return {\n averageFunctionIdentifierOverlap: pairCount === 0 ? 1 : overlapTotal / pairCount,\n sharedIdentifierCount: sharedIdentifiers.size,\n uniqueIdentifierCount: allIdentifiers.size,\n };\n}\n\nfunction measureTypeComplexity(root: Parser.SyntaxNode): TypeComplexityMetrics {\n const metrics: TypeComplexityMetrics = {\n typeAnnotationCount: 0,\n typeAliasCount: 0,\n interfaceCount: 0,\n genericParameterCount: 0,\n unionTypeCount: 0,\n intersectionTypeCount: 0,\n conditionalTypeCount: 0,\n typeAssertionCount: 0,\n nonNullAssertionCount: 0,\n satisfiesExpressionCount: 0,\n };\n\n function visit(node: Parser.SyntaxNode): void {\n switch (node.type) {\n case 'type_annotation': {\n metrics.typeAnnotationCount += 1;\n break;\n }\n case 'type_alias_declaration': {\n metrics.typeAliasCount += 1;\n break;\n }\n case 'interface_declaration': {\n metrics.interfaceCount += 1;\n break;\n }\n case 'type_parameters':\n case 'type_parameter': {\n metrics.genericParameterCount += node.type === 'type_parameter' ? 1 : 0;\n break;\n }\n case 'union_type': {\n metrics.unionTypeCount += 1;\n break;\n }\n case 'intersection_type': {\n metrics.intersectionTypeCount += 1;\n break;\n }\n case 'conditional_type': {\n metrics.conditionalTypeCount += 1;\n break;\n }\n case 'as_expression':\n case 'type_assertion': {\n metrics.typeAssertionCount += 1;\n break;\n }\n case 'non_null_expression': {\n metrics.nonNullAssertionCount += 1;\n break;\n }\n case 'satisfies_expression': {\n metrics.satisfiesExpressionCount += 1;\n break;\n }\n }\n\n for (const child of node.namedChildren) {\n visit(child);\n }\n }\n\n visit(root);\n return metrics;\n}\n\nconst duplicateBlockTypes = new Set([\n 'statement_block',\n 'block',\n 'if_statement',\n 'for_statement',\n 'for_in_statement',\n 'while_statement',\n 'do_statement',\n 'try_statement',\n 'with_statement',\n 'switch_statement',\n 'switch_case',\n 'case_clause',\n 'match_statement',\n 'match_arm',\n 'except_clause',\n 'catch_clause',\n 'finally_clause',\n 'elif_clause',\n 'expression_statement',\n 'return_statement',\n 'jsx_element',\n 'jsx_self_closing_element',\n]);\n\n/** Minimum subtree size (node count) for a block to be considered for duplication, to skip trivial repeats. */\nconst minDuplicateBlockSize = 24;\n\ninterface DuplicateCandidate {\n node: Parser.SyntaxNode;\n shape: string;\n size: number;\n}\n\n/**\n * Detects copy-pasted code blocks within a file by grouping control-flow / block / JSX subtrees that\n * share the same syntactic shape (node types, ignoring identifiers and literals). Only maximal,\n * non-overlapping blocks are counted so nested matches are not double-counted. Literal-only structures\n * such as array or object data are excluded because their element nodes are not block types.\n */\nfunction measureDuplication(root: Parser.SyntaxNode): DuplicationMetrics {\n const candidates: DuplicateCandidate[] = [];\n const shapeCache = new Map<number, { shape: string; size: number }>();\n\n function visit(node: Parser.SyntaxNode): void {\n if (duplicateBlockTypes.has(node.type)) {\n const { size } = describeShape(node, shapeCache);\n if (size >= minDuplicateBlockSize) {\n const { shape } = describeShape(node, shapeCache);\n candidates.push({ node, shape, size });\n }\n }\n for (const child of node.namedChildren) {\n visit(child);\n }\n }\n visit(root);\n\n const byShape = new Map<string, DuplicateCandidate[]>();\n for (const candidate of candidates) {\n const group = byShape.get(candidate.shape) ?? [];\n group.push(candidate);\n byShape.set(candidate.shape, group);\n }\n\n // Count larger blocks first and skip any candidate nested inside an already-counted duplicate.\n const counted: DuplicateCandidate[] = [];\n const consumed: Parser.SyntaxNode[] = [];\n let duplicateBlockCount = 0;\n let maxDuplicateBlockSize = 0;\n const groupCounts = new Map<string, number>();\n for (const [shape, group] of byShape) {\n if (group.length < 2) {\n continue;\n }\n for (const candidate of group.toSorted((left, right) => right.size - left.size)) {\n if (consumed.some((ancestor) => isAncestor(ancestor, candidate.node))) {\n continue;\n }\n counted.push(candidate);\n consumed.push(candidate.node);\n groupCounts.set(shape, (groupCounts.get(shape) ?? 0) + 1);\n maxDuplicateBlockSize = Math.max(maxDuplicateBlockSize, candidate.size);\n }\n }\n let duplicateBlockGroupCount = 0;\n for (const count of groupCounts.values()) {\n if (count >= 2) {\n duplicateBlockCount += count - 1;\n duplicateBlockGroupCount += 1;\n }\n }\n\n return { duplicateBlockCount, duplicateBlockGroupCount, maxDuplicateBlockSize };\n}\n\n/** Serializes a subtree by node type only (ignoring identifiers and literals) and reports its node count. */\nfunction describeShape(\n node: Parser.SyntaxNode,\n cache: Map<number, { shape: string; size: number }>\n): { shape: string; size: number } {\n const cached = cache.get(node.id);\n if (cached) {\n return cached;\n }\n\n let shape = node.type;\n let size = 1;\n if (node.namedChildCount > 0) {\n const parts: string[] = [];\n for (const child of node.namedChildren) {\n const childShape = describeShape(child, cache);\n parts.push(childShape.shape);\n size += childShape.size;\n }\n shape = `${node.type}(${parts.join(',')})`;\n }\n\n const result = { shape, size };\n cache.set(node.id, result);\n return result;\n}\n\nfunction isAncestor(ancestor: Parser.SyntaxNode, node: Parser.SyntaxNode): boolean {\n let current = node.parent;\n while (current) {\n if (current.id === ancestor.id) {\n return true;\n }\n current = current.parent;\n }\n return false;\n}\n\nfunction measureLines(code: string, root: Parser.SyntaxNode): CodeMetrics['lines'] {\n const sourceLines = code.length === 0 ? [] : code.split(/\\r\\n|\\n|\\r/);\n const commentSpans = collectCommentSpans(root);\n let blank = 0;\n let comment = 0;\n\n for (const [index, line] of sourceLines.entries()) {\n if (line.trim() === '') {\n blank += 1;\n continue;\n }\n\n if (isCommentOnlyLine(line, index, commentSpans)) {\n comment += 1;\n }\n }\n\n return {\n total: sourceLines.length,\n code: sourceLines.length - blank - comment,\n comment,\n blank,\n };\n}\n\nfunction collectCommentSpans(root: Parser.SyntaxNode): CommentSpan[] {\n const spans: CommentSpan[] = [];\n\n function visit(node: Parser.SyntaxNode): void {\n if (node.type === 'comment' || node.type === 'line_comment' || node.type === 'block_comment') {\n for (let row = node.startPosition.row; row <= node.endPosition.row; row += 1) {\n spans.push({\n line: row,\n startColumn: row === node.startPosition.row ? node.startPosition.column : 0,\n endColumn: row === node.endPosition.row ? node.endPosition.column : Number.POSITIVE_INFINITY,\n });\n }\n }\n\n for (const child of node.namedChildren) {\n visit(child);\n }\n }\n\n visit(root);\n return spans;\n}\n\nfunction isCommentOnlyLine(line: string, lineIndex: number, spans: CommentSpan[]): boolean {\n const relevantSpans = spans.filter((span) => span.line === lineIndex);\n if (relevantSpans.length === 0) {\n return false;\n }\n\n const firstContentColumn = line.search(/\\S/);\n const lastContentColumn = line.trimEnd().length;\n\n return relevantSpans.some((span) => span.startColumn <= firstContentColumn && span.endColumn >= lastContentColumn);\n}\n\nfunction measureHalstead(root: Parser.SyntaxNode, code: string): HalsteadMetrics {\n const operators = new Map<string, number>();\n const operands = new Map<string, number>();\n\n function visit(node: Parser.SyntaxNode): void {\n if (node.type === 'comment') {\n return;\n }\n\n if (node.childCount === 0) {\n const text = code.slice(node.startIndex, node.endIndex);\n if (operatorTexts.has(text) || operatorTexts.has(node.type)) {\n incrementCount(operators, text || node.type);\n } else if (operandNodeTypes.has(node.type)) {\n incrementCount(operands, text);\n }\n return;\n }\n\n if (operatorTexts.has(node.type)) {\n incrementCount(operators, node.type);\n }\n\n for (const child of node.children) {\n visit(child);\n }\n }\n\n visit(root);\n\n const distinctOperators = operators.size;\n const distinctOperands = operands.size;\n const totalOperators = sum(operators.values());\n const totalOperands = sum(operands.values());\n const vocabulary = distinctOperators + distinctOperands;\n const length = totalOperators + totalOperands;\n const volume = vocabulary === 0 ? 0 : length * Math.log2(vocabulary);\n const difficulty = distinctOperands === 0 ? 0 : (distinctOperators / 2) * (totalOperands / distinctOperands);\n const effort = difficulty * volume;\n\n return {\n distinctOperators,\n distinctOperands,\n totalOperators,\n totalOperands,\n vocabulary,\n length,\n volume,\n difficulty,\n effort,\n time: effort / 18,\n bugs: volume / 3000,\n };\n}\n\nfunction findFunctionName(node: Parser.SyntaxNode): string | undefined {\n const wrappedName = findWrappedComponentName(node);\n if (wrappedName) {\n return wrappedName;\n }\n\n const nameNode = node.childForFieldName('name');\n if (nameNode) {\n return nameNode.text;\n }\n\n const parent = node.parent;\n if (!parent) {\n return undefined;\n }\n\n const parentName = parent.childForFieldName('name');\n return parentName?.text;\n}\n\nfunction findWrappedComponentName(node: Parser.SyntaxNode): string | undefined {\n let current: Parser.SyntaxNode | undefined = node;\n while (current) {\n const argumentsNode: Parser.SyntaxNode | null = current.parent;\n const callNode: Parser.SyntaxNode | null | undefined = argumentsNode?.parent;\n if (argumentsNode?.type !== 'arguments' || callNode?.type !== 'call_expression') {\n return undefined;\n }\n\n if (!isReactComponentWrapperCall(callNode)) {\n return undefined;\n }\n\n const declaratorNode = callNode.parent;\n if (declaratorNode?.type === 'variable_declarator') {\n return declaratorNode.childForFieldName('name')?.text;\n }\n\n current = callNode;\n }\n\n return undefined;\n}\n\nfunction isReactComponentWrapperCall(node: Parser.SyntaxNode): boolean {\n const calleeNode = node.childForFieldName('function') ?? node.namedChild(0);\n return (\n calleeNode?.text === 'memo' ||\n calleeNode?.text === 'React.memo' ||\n calleeNode?.text === 'forwardRef' ||\n calleeNode?.text === 'React.forwardRef'\n );\n}\n\nfunction isCallNode(node: Parser.SyntaxNode): boolean {\n return node.type === 'call_expression' || node.type === 'call';\n}\n\nfunction findCalleeName(node: Parser.SyntaxNode): string | undefined {\n const calleeNode = node.childForFieldName('function') ?? node.namedChild(0);\n if (!calleeNode) {\n return undefined;\n }\n\n return findRightmostIdentifier(calleeNode);\n}\n\nfunction findRightmostIdentifier(node: Parser.SyntaxNode): string | undefined {\n if (\n node.type === 'identifier' ||\n node.type === 'property_identifier' ||\n node.type === 'field_identifier' ||\n node.type === 'attribute'\n ) {\n return node.text;\n }\n\n for (let index = node.namedChildCount - 1; index >= 0; index -= 1) {\n const child = node.namedChild(index);\n if (!child) {\n continue;\n }\n\n const identifier = findRightmostIdentifier(child);\n if (identifier) {\n return identifier;\n }\n }\n\n return undefined;\n}\n\nfunction isReactCreateElementCall(node: Parser.SyntaxNode): boolean {\n if (!isCallNode(node)) {\n return false;\n }\n\n const calleeNode = node.childForFieldName('function') ?? node.namedChild(0);\n return calleeNode?.text === 'React.createElement' || calleeNode?.text === 'createElement';\n}\n\nfunction isImportNode(node: Parser.SyntaxNode): boolean {\n return (\n node.type === 'import_statement' ||\n node.type === 'import_declaration' ||\n node.type === 'import_from_statement' ||\n node.type === 'import_spec' ||\n node.type === 'import_spec_list'\n );\n}\n\nfunction isImportSourceNode(node: Parser.SyntaxNode): boolean {\n return (\n isImportNode(node) || isDynamicImportNode(node) || (isExportNode(node) && node.childForFieldName('source') !== null)\n );\n}\n\nfunction isDynamicImportNode(node: Parser.SyntaxNode): boolean {\n if (!isCallNode(node)) {\n return false;\n }\n\n const calleeNode = node.childForFieldName('function') ?? node.namedChild(0);\n return calleeNode?.text === 'import';\n}\n\nfunction findImportSources(\n node: Parser.SyntaxNode,\n language: LanguageDefinition,\n options: { expandPythonSubmodules: boolean }\n): string[] {\n if (language.name === 'python') {\n const pythonSources = findPythonImportSources(node, options);\n if (pythonSources.length > 0) {\n return pythonSources;\n }\n }\n\n if (isDynamicImportNode(node)) {\n return findDynamicImportSources(node);\n }\n\n const sourceNode = node.childForFieldName('source') ?? findFirstStringNode(node);\n return sourceNode ? [unquote(sourceNode.text)] : [];\n}\n\nfunction findDynamicImportSources(node: Parser.SyntaxNode): string[] {\n const argumentsNode = node.childForFieldName('arguments');\n const firstArgument = argumentsNode?.namedChild(0);\n return firstArgument && isStringNode(firstArgument) ? [unquote(firstArgument.text)] : [];\n}\n\nfunction isRelativeImportSource(source: string): boolean {\n return source.startsWith('.') || source.startsWith('/');\n}\n\nfunction findPythonImportSources(node: Parser.SyntaxNode, options: { expandPythonSubmodules: boolean }): string[] {\n if (node.type === 'import_from_statement') {\n const moduleNode = node.childForFieldName('module_name');\n if (!moduleNode) {\n return [];\n }\n\n const moduleSource = normalizeImportSource(moduleNode.text);\n const nameNodes = findChildrenByFieldName(node, 'name');\n if (!options.expandPythonSubmodules || !moduleSource.startsWith('.')) {\n return [moduleSource];\n }\n if (/^\\.+$/u.test(moduleSource) && nameNodes.length > 0) {\n return nameNodes.flatMap(findPythonImportNames).map((name) => `${moduleSource}${name}`);\n }\n const submoduleSources = nameNodes.flatMap(findPythonImportNames).map((name) => `${moduleSource}.${name}`);\n if (submoduleSources.length > 0) {\n return [moduleSource, ...submoduleSources];\n }\n return [moduleSource];\n }\n\n if (node.type !== 'import_statement') {\n return [];\n }\n\n return node.namedChildren\n .map((child) => findPythonImportedModuleName(child))\n .filter((source) => source !== undefined);\n}\n\nfunction findPythonImportNames(node: Parser.SyntaxNode): string[] {\n if (node.type === 'aliased_import') {\n const nameNode = node.childForFieldName('name');\n return nameNode ? findPythonImportNames(nameNode) : [];\n }\n\n if (node.type === 'identifier') {\n return [node.text];\n }\n\n if (node.type === 'dotted_name') {\n return [normalizeImportSource(node.text)];\n }\n\n return node.namedChildren.flatMap(findPythonImportNames);\n}\n\nfunction findChildrenByFieldName(node: Parser.SyntaxNode, fieldName: string): Parser.SyntaxNode[] {\n const children: Parser.SyntaxNode[] = [];\n for (let index = 0; index < node.childCount; index += 1) {\n const child = node.child(index);\n if (child && node.fieldNameForChild(index) === fieldName) {\n children.push(child);\n }\n }\n return children;\n}\n\nfunction findPythonImportedModuleName(node: Parser.SyntaxNode): string | undefined {\n if (node.type === 'dotted_name' || node.type === 'relative_import') {\n return normalizeImportSource(node.text);\n }\n\n const nameNode = node.childForFieldName('name');\n if (nameNode) {\n return normalizeImportSource(nameNode.text);\n }\n\n for (const child of node.namedChildren) {\n const source = findPythonImportedModuleName(child);\n if (source) {\n return source;\n }\n }\n\n return undefined;\n}\n\nfunction normalizeImportSource(source: string): string {\n return source.replaceAll(/\\s+/gu, '');\n}\n\nfunction findFirstStringNode(node: Parser.SyntaxNode): Parser.SyntaxNode | undefined {\n if (isStringNode(node)) {\n return node;\n }\n\n for (const child of node.namedChildren) {\n const stringNode = findFirstStringNode(child);\n if (stringNode) {\n return stringNode;\n }\n }\n\n return undefined;\n}\n\nfunction isStringNode(node: Parser.SyntaxNode): boolean {\n return node.type === 'string' || node.type === 'string_literal' || node.type === 'interpreted_string_literal';\n}\n\nfunction unquote(value: string): string {\n return value.replaceAll(/^['\"`]|['\"`]$/gu, '');\n}\n\nfunction isExportNode(node: Parser.SyntaxNode): boolean {\n return node.type.startsWith('export') || node.type === 'public_field_definition';\n}\n\nfunction findRecursiveIndexes(graph: Map<number, Set<number>>): Set<number> {\n const recursiveIndexes = new Set<number>();\n\n for (const index of graph.keys()) {\n if (canReach(index, index, graph, new Set())) {\n recursiveIndexes.add(index);\n }\n }\n\n return recursiveIndexes;\n}\n\nfunction canReach(start: number, target: number, graph: Map<number, Set<number>>, visited: Set<number>): boolean {\n const callees = graph.get(start);\n if (!callees) {\n return false;\n }\n\n for (const callee of callees) {\n if (callee === target) {\n return true;\n }\n\n if (!visited.has(callee)) {\n visited.add(callee);\n if (canReach(callee, target, graph, visited)) {\n return true;\n }\n }\n }\n\n return false;\n}\n\nfunction measureMaxCallDepth(graph: Map<number, Set<number>>): number {\n let maxDepth = 0;\n for (const index of graph.keys()) {\n maxDepth = Math.max(maxDepth, measureCallDepth(index, graph, new Set()));\n }\n return maxDepth;\n}\n\nfunction measureCallDepth(index: number, graph: Map<number, Set<number>>, pathIndexes: Set<number>): number {\n const callees = graph.get(index);\n if (!callees || callees.size === 0 || pathIndexes.has(index)) {\n return 0;\n }\n\n pathIndexes.add(index);\n let maxDepth = 0;\n for (const callee of callees) {\n maxDepth = Math.max(maxDepth, 1 + measureCallDepth(callee, graph, new Set(pathIndexes)));\n }\n return maxDepth;\n}\n\nfunction intersectSets(left: Set<string>, right: Set<string>): Set<string> {\n const intersection = new Set<string>();\n for (const value of left) {\n if (right.has(value)) {\n intersection.add(value);\n }\n }\n return intersection;\n}\n\nfunction calculateMaintainabilityIndex(volume: number, complexity: number, loc: number): number {\n if (loc === 0) {\n return 100;\n }\n\n const raw = 171 - 5.2 * Math.log(Math.max(volume, 1)) - 0.23 * complexity - 16.2 * Math.log(loc);\n return Math.max(0, Math.min(100, (raw * 100) / 171));\n}\n\nfunction incrementCount(map: Map<string, number>, value: string): void {\n map.set(value, (map.get(value) ?? 0) + 1);\n}\n\nfunction maxMetric(functions: FunctionMetrics[], key: 'cyclomaticComplexity' | 'cognitiveComplexity'): number {\n return functions.length === 0 ? 0 : Math.max(...functions.map((fn) => fn[key]));\n}\n\nfunction maxMapValue(map: Map<unknown, number>): number {\n let maximum = 0;\n for (const value of map.values()) {\n maximum = Math.max(maximum, value);\n }\n return maximum;\n}\n\nfunction sum(values: Iterable<number>): number {\n let total = 0;\n for (const value of values) {\n total += value;\n }\n return total;\n}\n"],"names":["booleanOperators","Set","operatorTexts","operandNodeTypes","TreeMeasurer","registry","createLanguageRegistry","registerLanguage","language","this","set","name","alias","aliases","getSupportedLanguages","values","map","measure","code","options","get","Error","parser","Parser","setLanguage","parserLanguage","root","parse","undefined","bufferSize","length","rootNode","structuralMetrics","functions","analyses","node","index","complexity","measureComplexity","calls","callees","functionNodeTypes","callCount","visit","insideRoot","has","type","isCallNode","callee","calleeNode","childForFieldName","namedChild","findRightmostIdentifier","findCalleeName","add","child","namedChildren","collectCalls","findFunctionName","startLine","startPosition","row","startColumn","column","endLine","endPosition","returnsJsx","cyclomaticComplexity","cognitiveComplexity","parameterCount","countParameters","identifiers","collectIdentifiers","analyzeFunction","callGraph","indexesByName","Map","analysis","entries","filter","entry","mapUniqueFunctionIndexesByName","functionNames","keys","fanInByIndex","fanOutByIndex","graph","internalCallCount","allCallees","internalCalleeNames","internalCalleeIndexes","calleeIndex","size","recursiveIndexes","canReach","findRecursiveIndexes","metrics","uniqueCalleeCount","internalEdgeCount","sum","recursiveFunctionCount","maxFanIn","maxMapValue","maxFanOut","maxCallDepth","measureMaxCallDepth","measureCallGraph","fanIn","fanOut","recursive","coupling","measureCoupling","module","measureModule","cohesion","measureCohesion","syntaxFeatures","measureSyntaxFeatures","typeComplexity","measureTypeComplexity","measureStructuralMetrics","collectNodes","functionMetrics","globalComplexity","lines","sourceLines","split","commentSpans","spans","push","line","endColumn","Number","POSITIVE_INFINITY","collectCommentSpans","blank","comment","trim","isCommentOnlyLine","total","measureLines","halstead","operators","operands","childCount","text","slice","startIndex","endIndex","incrementCount","children","distinctOperators","distinctOperands","totalOperators","totalOperands","vocabulary","volume","Math","log2","difficulty","effort","time","bugs","measureHalstead","bytes","Buffer","byteLength","classCount","classNodeTypes","functionCount","maxCyclomaticComplexity","maxMetric","maxCognitiveComplexity","nestingDepth","duplication","measureDuplication","maintainabilityIndex","calculateMaintainabilityIndex","syntaxTree","includeSyntaxTree","toString","defaultMeasurer","parametersNode","find","nesting","stopAtNestedFunctions","functionNodes","decisionNodes","decisionNodeTypes","nestingNodes","nestingNodeTypes","current","currentNesting","isDecision","isNesting","isNamed","isBooleanOperator","childNesting","max","nodeTypes","nodes","containsJsxExpression","containsReactCreateElementCall","getArrowFunctionBody","namedChildCount","containsNode","startsWith","calleeName","isArrayMappingCallee","some","containsReturnedJsxFunction","isJsxMappingCall","isReactCreateElementCall","predicate","body","containsOwnReturnNode","returnsJsxFromFunctionNode","importSources","visitImports","isImportSourceNode","source","findImportSources","expandPythonSubmodules","declarations","collectModuleDeclarations","exportedNames","insideSourcedExport","isExportSpecifierNode","nameNode","isDeclarationNameNode","findExportedName","isSourcedExport","isModuleExportNode","collectExportedNames","flatMap","collectTopLevelDeclarations","declaration","exported","isDeclarationContainer","isTopLevelDeclarationNode","receiverTypeNode","receiverType","replaceAll","replace","findGoMethodDeclarationName","findDeclarationName","declarationFromNode","importCount","exportCount","isImportNode","isDynamicImportNode","isExportNode","relativeImportCount","isRelativeImportSource","importSourceCount","externalImportCount","assignmentCount","awaitExpressionCount","loopStatementCount","mutableBindingCount","returnStatementCount","throwStatementCount","tryStatementCount","isAssignmentNode","isAwaitNode","isLoopNode","firstChild","isMutableBindingNode","isReturnNode","isThrowNode","isTryNode","allIdentifiers","sharedIdentifiers","overlapTotal","pairCount","identifier","leftIndex","rightIndex","left","right","intersection","intersectSets","unionSize","averageFunctionIdentifierOverlap","sharedIdentifierCount","uniqueIdentifierCount","typeAnnotationCount","typeAliasCount","interfaceCount","genericParameterCount","unionTypeCount","intersectionTypeCount","conditionalTypeCount","typeAssertionCount","nonNullAssertionCount","satisfiesExpressionCount","duplicateBlockTypes","minDuplicateBlockSize","candidates","shapeCache","describeShape","shape","byShape","candidate","group","consumed","duplicateBlockCount","maxDuplicateBlockSize","groupCounts","toSorted","ancestor","isAncestor","duplicateBlockGroupCount","count","cache","cached","id","parts","childShape","join","result","parent","lineIndex","relevantSpans","span","firstContentColumn","search","lastContentColumn","trimEnd","wrappedName","argumentsNode","callNode","isReactComponentWrapperCall","declaratorNode","findWrappedComponentName","parentName","pythonSources","moduleNode","moduleSource","normalizeImportSource","nameNodes","fieldName","fieldNameForChild","findChildrenByFieldName","test","findPythonImportNames","submoduleSources","findPythonImportedModuleName","findPythonImportSources","firstArgument","isStringNode","unquote","findDynamicImportSources","sourceNode","findFirstStringNode","stringNode","value","start","target","visited","maxDepth","measureCallDepth","pathIndexes","loc","raw","log","min","key","fn","maximum"],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CodeMetrics, LanguageDefinition, LanguageName, MeasureOptions } from './types.js';
|
|
2
|
+
export declare class TreeMeasurer {
|
|
3
|
+
private readonly registry;
|
|
4
|
+
registerLanguage(language: LanguageDefinition): void;
|
|
5
|
+
getSupportedLanguages(): LanguageName[];
|
|
6
|
+
measure(code: string, options: MeasureOptions): CodeMetrics;
|
|
7
|
+
}
|
|
8
|
+
export declare const defaultMeasurer: TreeMeasurer;
|
|
9
|
+
export declare function measureCode(code: string, options: MeasureOptions): CodeMetrics;
|
package/dist/metrics.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import t from"tree-sitter";import{createLanguageRegistry as e}from"./languages.js";const n=new Set(["&&","||","and","or"]),o=new Set(["+","-","*","/","%","**","=","+=","-=","*=","/=","%=","==","!=","===","!==","<","<=",">",">=","!","~","&","|","^","<<",">>","=>","return","throw","yield","await","break","continue"]),r=new Set(["identifier","property_identifier","field_identifier","type_identifier","number","integer","float","string","string_literal","template_string","character_literal","true","false","null","undefined","nil"]);class i{registry=e();registerLanguage(t){this.registry.set(t.name,t);for(const e of t.aliases??[])this.registry.set(e,t)}getSupportedLanguages(){return[...new Set([...this.registry.values()].map(t=>t.name))]}measure(e,n){const i=this.registry.get(n.language);if(!i)throw new Error(`Unsupported language: ${n.language}`);const a=new t;a.setLanguage(i.parserLanguage);const s=a.parse(e,void 0,{bufferSize:e.length+1}).rootNode,p=function(t,e,n){const o=e.map((t,e)=>function(t,e,n){const o=u(t,e,0,!0),r=function(t,e){const n=new Set,o=new Set(e.functionNodeTypes);let r=0;function i(t,e){if(e||!o.has(t.type)){if($(t)){r+=1;const e=function(t){const e=t.childForFieldName("function")??t.namedChild(0);if(!e)return;return B(e)}(t);e&&n.add(e)}for(const e of t.namedChildren)i(e,!1)}}return i(t,!0),{callCount:r,callees:n}}(t,e);return{index:n,name:L(t),startLine:t.startPosition.row+1,startColumn:t.startPosition.column,endLine:t.endPosition.row+1,returnsJsx:d(t,e),cyclomaticComplexity:o.cyclomaticComplexity,cognitiveComplexity:o.cognitiveComplexity,callCount:r.callCount,parameterCount:c(t),callees:r.callees,identifiers:l(t)}}(t,n,e)),r=function(t){const e=function(t){const e=new Map;for(const n of t)n.name&&e.set(n.name,e.has(n.name)?void 0:n.index);return new Map([...e.entries()].filter(t=>void 0!==t[1]))}(t),n=new Set(e.keys()),o=new Map,r=new Map,i=new Map;let a=0,s=0;const c=new Set;for(const u of t){a+=u.callCount;for(const t of u.callees)c.add(t);const t=new Set([...u.callees].filter(t=>n.has(t))),l=new Set;for(const n of t){const t=e.get(n);void 0!==t&&l.add(t)}i.set(u.index,l),r.set(u.index,t.size),s+=t.size;for(const t of l)o.set(t,(o.get(t)??0)+1)}const u=function(t){const e=new Set;for(const n of t.keys())K(n,n,t,new Set)&&e.add(n);return e}(i);return{fanInByIndex:o,fanOutByIndex:r,recursiveIndexes:u,metrics:{callCount:a,uniqueCalleeCount:c.size,internalCallCount:s,internalEdgeCount:rt([...i.values()].map(t=>t.size)),recursiveFunctionCount:u.size,maxFanIn:ot(o),maxFanOut:ot(r),maxCallDepth:Q(i)}}}(o);return{functions:o.map(t=>({name:t.name,startLine:t.startLine,startColumn:t.startColumn,endLine:t.endLine,returnsJsx:t.returnsJsx,cyclomaticComplexity:t.cyclomaticComplexity,cognitiveComplexity:t.cognitiveComplexity,callCount:t.callCount,uniqueCalleeCount:t.callees.size,fanIn:r.fanInByIndex.get(t.index)??0,fanOut:r.fanOutByIndex.get(t.index)??0,parameterCount:t.parameterCount,recursive:r.recursiveIndexes.has(t.index)})),callGraph:r.metrics,coupling:v(t,n),module:_(t,n),cohesion:N(o),syntaxFeatures:S(t),typeComplexity:b(t)}}(s,f(s,new Set(i.functionNodeTypes)),i),m=p.functions,y=u(s,i,0,!1),h=function(t,e){const n=0===t.length?[]:t.split(/\r\n|\n|\r/),o=function(t){const e=[];function n(t){if("comment"===t.type||"line_comment"===t.type||"block_comment"===t.type)for(let n=t.startPosition.row;n<=t.endPosition.row;n+=1)e.push({line:n,startColumn:n===t.startPosition.row?t.startPosition.column:0,endColumn:n===t.endPosition.row?t.endPosition.column:Number.POSITIVE_INFINITY});for(const e of t.namedChildren)n(e)}return n(t),e}(e);let r=0,i=0;for(const[t,e]of n.entries())""!==e.trim()?P(e,t,o)&&(i+=1):r+=1;return{total:n.length,code:n.length-r-i,comment:i,blank:r}}(e,s),C=function(t,e){const n=new Map,i=new Map;function a(t){if("comment"!==t.type){if(0===t.childCount){const a=e.slice(t.startIndex,t.endIndex);return void(o.has(a)||o.has(t.type)?et(n,a||t.type):r.has(t.type)&&et(i,a))}o.has(t.type)&&et(n,t.type);for(const e of t.children)a(e)}}a(t);const s=n.size,c=i.size,u=rt(n.values()),l=rt(i.values()),f=s+c,d=u+l,p=0===f?0:d*Math.log2(f),m=0===c?0:s/2*(l/c),y=m*p;return{distinctOperators:s,distinctOperands:c,totalOperators:u,totalOperands:l,vocabulary:f,length:d,volume:p,difficulty:m,effort:y,time:y/18,bugs:p/3e3}}(s,e);return{language:i.name,bytes:Buffer.byteLength(e),lines:h,functions:m,classCount:f(s,new Set(i.classNodeTypes)).length,functionCount:m.length,cyclomaticComplexity:y.cyclomaticComplexity,maxCyclomaticComplexity:nt(m,"cyclomaticComplexity"),cognitiveComplexity:y.cognitiveComplexity,maxCognitiveComplexity:nt(m,"cognitiveComplexity"),nestingDepth:y.nestingDepth,callGraph:p.callGraph,coupling:p.coupling,module:p.module,cohesion:p.cohesion,syntaxFeatures:p.syntaxFeatures,typeComplexity:p.typeComplexity,duplication:I(s),halstead:C,maintainabilityIndex:tt(C.volume,y.cyclomaticComplexity,h.code),syntaxTree:n.includeSyntaxTree?s.toString():void 0}}}const a=new i;function s(t,e){return a.measure(t,e)}function c(t){const e=t.childForFieldName("parameters")??t.namedChildren.find(t=>"formal_parameters"===t.type||"parameter_list"===t.type);return e?e.namedChildren.filter(t=>"comment"!==t.type).length:0}function u(t,e,o,r){let i=1,a=0,s=o;const c=new Set(e.functionNodeTypes),u=new Set(e.decisionNodeTypes),l=new Set(e.nestingNodeTypes);function f(t,e,o){if(r&&c.has(t.type))return;const d=u.has(t.type),p=l.has(t.type);d&&(i+=1,a+=1+e),function(t){if(t.isNamed)return!1;return n.has(t.text)}(t)&&(i+=1,a+=1);const m=p?e+1:e;s=Math.max(s,m);for(const e of t.children)f(e,m)}for(const e of t.children)f(e,o);return{cyclomaticComplexity:i,cognitiveComplexity:a,nestingDepth:s}}function l(t){const e=new Set;return function t(n){"identifier"!==n.type&&"property_identifier"!==n.type&&"field_identifier"!==n.type||e.add(n.text);for(const e of n.namedChildren)t(e)}(t),e}function f(t,e){const n=[];return function t(o){e.has(o.type)&&n.push(o);for(const e of o.namedChildren)t(e)}(t),n}function d(t,e){const n=new Set(e.functionNodeTypes);return function e(o,r){if(!r&&n.has(o.type))return!1;if("return_statement"===o.type)return m(o,n)||y(o,n);if("arrow_function"===t.type&&o===p(t)&&"statement_block"!==o.type&&!n.has(o.type))return m(o,n)||y(o,n);for(const t of o.namedChildren)if(e(t,!1))return!0;return!1}(t,!0)}function p(t){return t.childForFieldName("body")??t.namedChild(t.namedChildCount-1)??void 0}function m(t,e){return h(t,e,t=>t.type.startsWith("jsx_")||function(t,e){if(!$(t)||!function(t){if(!t)return!1;const e=B(t);return"map"===e||"flatMap"===e}(t.childForFieldName("function")??t.namedChild(0)))return!1;return t.namedChildren.some(t=>C(t,e))}(t,e))}function y(t,e){return h(t,e,E)}function h(t,e,n){return function t(o,r){if(!r&&e.has(o.type))return!1;if(n(o))return!0;for(const e of o.namedChildren)if(t(e,!1))return!0;return!1}(t,!0)}function C(t,e){return e.has(t.type)?function(t,e){const n="arrow_function"===t.type?p(t):void 0;if(n&&"statement_block"!==n.type&&!e.has(n.type))return m(n,e)||y(n,e);return function(t,e,n){function o(t,r){if(!r&&e.has(t.type))return!1;if("return_statement"===t.type&&n(t))return!0;for(const e of t.namedChildren)if(o(e,!1))return!0;return!1}return o(t,!0)}(t,e,t=>m(t,e)||y(t,e))}(t,e):t.namedChildren.some(t=>C(t,e))}function _(t,e){const n=new Set;return function t(o){if(j(o))for(const t of R(o,e,{expandPythonSubmodules:!0}))n.add(t);for(const e of o.namedChildren)t(e)}(t),{declarations:x(t),importSources:[...n]}}function x(t){const e=function(t){const e=new Set;function n(t,o){if(!o&&function(t){return"export_specifier"===t.type||"namespace_export"===t.type}(t)){const n=function(t){const e=t.childForFieldName("name")??t.childForFieldName("alias")??t.namedChildren.find(F);return e&&F(e)?e.text:void 0}(t);n&&e.add(n)}const r=o||w(t)&&null!==t.childForFieldName("source");for(const e of t.namedChildren)n(e,r)}return n(t,!1),e}(t);return t.namedChildren.flatMap(t=>g(t,!1)).map(t=>e.has(t.name)?{...t,exported:!0}:t)}function g(t,e){return w(t)?t.namedChildren.flatMap(t=>g(t,!0)):function(t){return"lexical_declaration"===t.type||"variable_declaration"===t.type||"decorated_definition"===t.type||"type_declaration"===t.type||"const_declaration"===t.type||"var_declaration"===t.type||"var_spec_list"===t.type}(t)?t.namedChildren.flatMap(t=>g(t,e)):function(t,e){if(!function(t){return"function_declaration"===t.type||"function_definition"===t.type||"function_item"===t.type||"method_declaration"===t.type||"class_declaration"===t.type||"class_definition"===t.type||"interface_declaration"===t.type||"type_alias_declaration"===t.type||"type_declaration"===t.type||"type_spec"===t.type||"const_spec"===t.type||"var_spec"===t.type||"variable_declarator"===t.type}(t))return[];const n=function(t){if("method_declaration"===t.type)return function(t){const e=t.childForFieldName("name"),n=t.childForFieldName("receiver")?.namedChildren[0]?.childForFieldName("type");if(!e||!F(e)||!n)return e&&F(e)?e.text:void 0;return`${o=n.text,o.replaceAll(/\s+/gu,"").replace(/^\*+/u,"")}.${e.text}`;var o}(t);const e=t.childForFieldName("name");if(e)return F(e)?e.text:void 0;return t.namedChildren.find(F)?.text}(t);return n?[{exported:e,name:n,startLine:t.startPosition.row+1}]:[]}(t,e)}function w(t){return"export_statement"===t.type||"export_declaration"===t.type}function F(t){return"identifier"===t.type||"type_identifier"===t.type||"property_identifier"===t.type||"field_identifier"===t.type}function v(t,e){const n=new Set;let o=0,r=0;!function t(i){if((O(i)||D(i))&&(o+=1),j(i))for(const t of R(i,e,{expandPythonSubmodules:!1}))n.add(t);H(i)&&(r+=1);for(const e of i.namedChildren)t(e)}(t);const i=[...n].filter(W).length;return{importCount:o,importSourceCount:n.size,relativeImportCount:i,externalImportCount:n.size-i,exportCount:r}}function S(t){const e={assignmentCount:0,awaitExpressionCount:0,loopStatementCount:0,mutableBindingCount:0,returnStatementCount:0,throwStatementCount:0,tryStatementCount:0};return function t(n){(function(t){return"assignment_expression"===t.type||"augmented_assignment_expression"===t.type||"assignment_statement"===t.type||"assignment"===t.type||"augmented_assignment"===t.type||"short_var_declaration"===t.type})(n)&&(e.assignmentCount+=1),function(t){return"await_expression"===t.type||"await"===t.type}(n)&&(e.awaitExpressionCount+=1),function(t){return"for_statement"===t.type||"for_in_statement"===t.type||"while_statement"===t.type||"do_statement"===t.type}(n)&&(e.loopStatementCount+=1),function(t){return"lexical_declaration"===t.type&&"let"===t.firstChild?.text||"variable_declaration"===t.type&&"var"===t.firstChild?.text||"var_declaration"===t.type}(n)&&(e.mutableBindingCount+=1),function(t){return"return_statement"===t.type}(n)&&(e.returnStatementCount+=1),function(t){return"throw_statement"===t.type||"raise_statement"===t.type}(n)&&(e.throwStatementCount+=1),function(t){return"try_statement"===t.type}(n)&&(e.tryStatementCount+=1);for(const e of n.namedChildren)t(e)}(t),e}function N(t){const e=new Set,n=new Set;let o=0,r=0;for(const n of t)for(const t of n.identifiers)e.add(t);for(let e=0;e<t.length;e+=1)for(let i=e+1;i<t.length;i+=1){const a=t[e],s=t[i];if(!a||!s)continue;const c=Z(a.identifiers,s.identifiers),u=new Set([...a.identifiers,...s.identifiers]).size;for(const t of c)n.add(t);o+=0===u?0:c.size/u,r+=1}return{averageFunctionIdentifierOverlap:0===r?1:o/r,sharedIdentifierCount:n.size,uniqueIdentifierCount:e.size}}function b(t){const e={typeAnnotationCount:0,typeAliasCount:0,interfaceCount:0,genericParameterCount:0,unionTypeCount:0,intersectionTypeCount:0,conditionalTypeCount:0,typeAssertionCount:0,nonNullAssertionCount:0,satisfiesExpressionCount:0};return function t(n){switch(n.type){case"type_annotation":e.typeAnnotationCount+=1;break;case"type_alias_declaration":e.typeAliasCount+=1;break;case"interface_declaration":e.interfaceCount+=1;break;case"type_parameters":case"type_parameter":e.genericParameterCount+="type_parameter"===n.type?1:0;break;case"union_type":e.unionTypeCount+=1;break;case"intersection_type":e.intersectionTypeCount+=1;break;case"conditional_type":e.conditionalTypeCount+=1;break;case"as_expression":case"type_assertion":e.typeAssertionCount+=1;break;case"non_null_expression":e.nonNullAssertionCount+=1;break;case"satisfies_expression":e.satisfiesExpressionCount+=1}for(const e of n.namedChildren)t(e)}(t),e}const M=new Set(["statement_block","block","if_statement","for_statement","for_in_statement","while_statement","do_statement","try_statement","with_statement","switch_statement","switch_case","case_clause","match_statement","match_arm","except_clause","catch_clause","finally_clause","elif_clause","expression_statement","return_statement","jsx_element","jsx_self_closing_element"]),z=24;function I(t){const e=[],n=new Map;!function t(o){if(M.has(o.type)){const{size:t}=k(o,n);if(t>=z){const{shape:r}=k(o,n);e.push({node:o,shape:r,size:t})}}for(const e of o.namedChildren)t(e)}(t);const o=new Map;for(const t of e){const e=o.get(t.shape)??[];e.push(t),o.set(t.shape,e)}const r=[];let i=0,a=0;const s=new Map;for(const[t,e]of o)if(!(e.length<2))for(const n of e.toSorted((t,e)=>e.size-t.size))r.some(t=>T(t,n.node))||(r.push(n.node),s.set(t,(s.get(t)??0)+1),a=Math.max(a,n.size));let c=0;for(const t of s.values())t>=2&&(i+=t-1,c+=1);return{duplicateBlockCount:i,duplicateBlockGroupCount:c,maxDuplicateBlockSize:a}}function k(t,e){const n=e.get(t.id);if(n)return n;let o=t.type,r=1;if(t.namedChildCount>0){const n=[];for(const o of t.namedChildren){const t=k(o,e);n.push(t.shape),r+=t.size}o=`${t.type}(${n.join(",")})`}const i={shape:o,size:r};return e.set(t.id,i),i}function T(t,e){let n=e.parent;for(;n;){if(n.id===t.id)return!0;n=n.parent}return!1}function P(t,e,n){const o=n.filter(t=>t.line===e);if(0===o.length)return!1;const r=t.search(/\S/),i=t.trimEnd().length;return o.some(t=>t.startColumn<=r&&t.endColumn>=i)}function L(t){const e=function(t){let e=t;for(;e;){const t=e.parent,n=t?.parent;if("arguments"!==t?.type||"call_expression"!==n?.type)return;if(!A(n))return;const o=n.parent;if("variable_declarator"===o?.type)return o.childForFieldName("name")?.text;e=n}return}(t);if(e)return e;const n=t.childForFieldName("name");if(n)return n.text;const o=t.parent;if(!o)return;const r=o.childForFieldName("name");return r?.text}function A(t){const e=t.childForFieldName("function")??t.namedChild(0);return"memo"===e?.text||"React.memo"===e?.text||"forwardRef"===e?.text||"React.forwardRef"===e?.text}function $(t){return"call_expression"===t.type||"call"===t.type}function B(t){if("identifier"===t.type||"property_identifier"===t.type||"field_identifier"===t.type||"attribute"===t.type)return t.text;for(let e=t.namedChildCount-1;e>=0;e-=1){const n=t.namedChild(e);if(!n)continue;const o=B(n);if(o)return o}}function E(t){if(!$(t))return!1;const e=t.childForFieldName("function")??t.namedChild(0);return"React.createElement"===e?.text||"createElement"===e?.text}function O(t){return"import_statement"===t.type||"import_declaration"===t.type||"import_from_statement"===t.type||"import_spec"===t.type||"import_spec_list"===t.type}function j(t){return O(t)||D(t)||H(t)&&null!==t.childForFieldName("source")}function D(t){if(!$(t))return!1;const e=t.childForFieldName("function")??t.namedChild(0);return"import"===e?.text}function R(t,e,n){if("python"===e.name){const e=function(t,e){if("import_from_statement"===t.type){const n=t.childForFieldName("module_name");if(!n)return[];const o=J(n.text),r=function(t,e){const n=[];for(let o=0;o<t.childCount;o+=1){const r=t.child(o);r&&t.fieldNameForChild(o)===e&&n.push(r)}return n}(t,"name");if(!e.expandPythonSubmodules||!o.startsWith("."))return[o];if(/^\.+$/u.test(o)&&r.length>0)return r.flatMap(G).map(t=>`${o}${t}`);const i=r.flatMap(G).map(t=>`${o}.${t}`);return i.length>0?[o,...i]:[o]}if("import_statement"!==t.type)return[];return t.namedChildren.map(t=>q(t)).filter(t=>void 0!==t)}(t,n);if(e.length>0)return e}if(D(t))return function(t){const e=t.childForFieldName("arguments"),n=e?.namedChild(0);return n&&V(n)?[Y(n.text)]:[]}(t);const o=t.childForFieldName("source")??U(t);return o?[Y(o.text)]:[]}function W(t){return t.startsWith(".")||t.startsWith("/")}function G(t){if("aliased_import"===t.type){const e=t.childForFieldName("name");return e?G(e):[]}return"identifier"===t.type?[t.text]:"dotted_name"===t.type?[J(t.text)]:t.namedChildren.flatMap(G)}function q(t){if("dotted_name"===t.type||"relative_import"===t.type)return J(t.text);const e=t.childForFieldName("name");if(e)return J(e.text);for(const e of t.namedChildren){const t=q(e);if(t)return t}}function J(t){return t.replaceAll(/\s+/gu,"")}function U(t){if(V(t))return t;for(const e of t.namedChildren){const t=U(e);if(t)return t}}function V(t){return"string"===t.type||"string_literal"===t.type||"interpreted_string_literal"===t.type}function Y(t){return t.replaceAll(/^['"`]|['"`]$/gu,"")}function H(t){return t.type.startsWith("export")||"public_field_definition"===t.type}function K(t,e,n,o){const r=n.get(t);if(!r)return!1;for(const t of r){if(t===e)return!0;if(!o.has(t)&&(o.add(t),K(t,e,n,o)))return!0}return!1}function Q(t){let e=0;for(const n of t.keys())e=Math.max(e,X(n,t,new Set));return e}function X(t,e,n){const o=e.get(t);if(!o||0===o.size||n.has(t))return 0;n.add(t);let r=0;for(const t of o)r=Math.max(r,1+X(t,e,new Set(n)));return r}function Z(t,e){const n=new Set;for(const o of t)e.has(o)&&n.add(o);return n}function tt(t,e,n){if(0===n)return 100;const o=171-5.2*Math.log(Math.max(t,1))-.23*e-16.2*Math.log(n);return Math.max(0,Math.min(100,100*o/171))}function et(t,e){t.set(e,(t.get(e)??0)+1)}function nt(t,e){return 0===t.length?0:Math.max(...t.map(t=>t[e]))}function ot(t){let e=0;for(const n of t.values())e=Math.max(e,n);return e}function rt(t){let e=0;for(const n of t)e+=n;return e}export{i as TreeMeasurer,a as defaultMeasurer,s as measureCode};
|
|
2
|
+
//# sourceMappingURL=metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.js","sources":["../src/metrics.ts"],"sourcesContent":["import Parser from 'tree-sitter';\nimport { createLanguageRegistry } from './languages.js';\nimport type {\n CallGraphMetrics,\n CodeMetrics,\n CohesionMetrics,\n CouplingMetrics,\n DeclarationMetrics,\n DuplicationMetrics,\n FunctionMetrics,\n HalsteadMetrics,\n LanguageDefinition,\n LanguageName,\n MeasureOptions,\n ModuleMetrics,\n SyntaxFeatureMetrics,\n TypeComplexityMetrics,\n} from './types.js';\n\nconst booleanOperators = new Set(['&&', '||', 'and', 'or']);\nconst operatorTexts = new Set([\n '+',\n '-',\n '*',\n '/',\n '%',\n '**',\n '=',\n '+=',\n '-=',\n '*=',\n '/=',\n '%=',\n '==',\n '!=',\n '===',\n '!==',\n '<',\n '<=',\n '>',\n '>=',\n '!',\n '~',\n '&',\n '|',\n '^',\n '<<',\n '>>',\n '=>',\n 'return',\n 'throw',\n 'yield',\n 'await',\n 'break',\n 'continue',\n]);\n\nconst operandNodeTypes = new Set([\n 'identifier',\n 'property_identifier',\n 'field_identifier',\n 'type_identifier',\n 'number',\n 'integer',\n 'float',\n 'string',\n 'string_literal',\n 'template_string',\n 'character_literal',\n 'true',\n 'false',\n 'null',\n 'undefined',\n 'nil',\n]);\n\ninterface ComplexityResult {\n cyclomaticComplexity: number;\n cognitiveComplexity: number;\n nestingDepth: number;\n}\n\ninterface CommentSpan {\n line: number;\n startColumn: number;\n endColumn: number;\n}\n\ninterface FunctionAnalysis {\n index: number;\n name?: string;\n startLine: number;\n startColumn: number;\n endLine: number;\n returnsJsx: boolean;\n cyclomaticComplexity: number;\n cognitiveComplexity: number;\n callCount: number;\n parameterCount: number;\n callees: Set<string>;\n identifiers: Set<string>;\n}\n\ninterface StructuralMetrics {\n callGraph: CallGraphMetrics;\n cohesion: CohesionMetrics;\n coupling: CouplingMetrics;\n functions: FunctionMetrics[];\n module: ModuleMetrics;\n syntaxFeatures: SyntaxFeatureMetrics;\n typeComplexity: TypeComplexityMetrics;\n}\n\nexport class TreeMeasurer {\n private readonly registry = createLanguageRegistry();\n\n registerLanguage(language: LanguageDefinition): void {\n this.registry.set(language.name, language);\n for (const alias of language.aliases ?? []) {\n this.registry.set(alias, language);\n }\n }\n\n getSupportedLanguages(): LanguageName[] {\n return [...new Set([...this.registry.values()].map((language) => language.name))];\n }\n\n measure(code: string, options: MeasureOptions): CodeMetrics {\n const language = this.registry.get(options.language);\n if (!language) {\n throw new Error(`Unsupported language: ${options.language}`);\n }\n\n const parser = new Parser();\n parser.setLanguage(language.parserLanguage);\n const tree = parser.parse(code, undefined, {\n bufferSize: code.length + 1,\n });\n const root = tree.rootNode;\n const functions = collectNodes(root, new Set(language.functionNodeTypes));\n const structuralMetrics = measureStructuralMetrics(root, functions, language);\n const functionMetrics = structuralMetrics.functions;\n const globalComplexity = measureComplexity(root, language, 0, false);\n const lines = measureLines(code, root);\n const halstead = measureHalstead(root, code);\n\n return {\n language: language.name,\n bytes: Buffer.byteLength(code),\n lines,\n functions: functionMetrics,\n classCount: collectNodes(root, new Set(language.classNodeTypes)).length,\n functionCount: functionMetrics.length,\n cyclomaticComplexity: globalComplexity.cyclomaticComplexity,\n maxCyclomaticComplexity: maxMetric(functionMetrics, 'cyclomaticComplexity'),\n cognitiveComplexity: globalComplexity.cognitiveComplexity,\n maxCognitiveComplexity: maxMetric(functionMetrics, 'cognitiveComplexity'),\n nestingDepth: globalComplexity.nestingDepth,\n callGraph: structuralMetrics.callGraph,\n coupling: structuralMetrics.coupling,\n module: structuralMetrics.module,\n cohesion: structuralMetrics.cohesion,\n syntaxFeatures: structuralMetrics.syntaxFeatures,\n typeComplexity: structuralMetrics.typeComplexity,\n duplication: measureDuplication(root),\n halstead,\n maintainabilityIndex: calculateMaintainabilityIndex(\n halstead.volume,\n globalComplexity.cyclomaticComplexity,\n lines.code\n ),\n syntaxTree: options.includeSyntaxTree ? root.toString() : undefined,\n };\n }\n}\n\nexport const defaultMeasurer = new TreeMeasurer();\n\nexport function measureCode(code: string, options: MeasureOptions): CodeMetrics {\n return defaultMeasurer.measure(code, options);\n}\n\nfunction measureStructuralMetrics(\n root: Parser.SyntaxNode,\n functions: Parser.SyntaxNode[],\n language: LanguageDefinition\n): StructuralMetrics {\n const analyses = functions.map((node, index) => analyzeFunction(node, language, index));\n const callGraph = measureCallGraph(analyses);\n const functionsWithGraph = analyses.map((analysis) => ({\n name: analysis.name,\n startLine: analysis.startLine,\n startColumn: analysis.startColumn,\n endLine: analysis.endLine,\n returnsJsx: analysis.returnsJsx,\n cyclomaticComplexity: analysis.cyclomaticComplexity,\n cognitiveComplexity: analysis.cognitiveComplexity,\n callCount: analysis.callCount,\n uniqueCalleeCount: analysis.callees.size,\n fanIn: callGraph.fanInByIndex.get(analysis.index) ?? 0,\n fanOut: callGraph.fanOutByIndex.get(analysis.index) ?? 0,\n parameterCount: analysis.parameterCount,\n recursive: callGraph.recursiveIndexes.has(analysis.index),\n }));\n\n return {\n functions: functionsWithGraph,\n callGraph: callGraph.metrics,\n coupling: measureCoupling(root, language),\n module: measureModule(root, language),\n cohesion: measureCohesion(analyses),\n syntaxFeatures: measureSyntaxFeatures(root),\n typeComplexity: measureTypeComplexity(root),\n };\n}\n\nfunction analyzeFunction(node: Parser.SyntaxNode, language: LanguageDefinition, index: number): FunctionAnalysis {\n const complexity = measureComplexity(node, language, 0, true);\n const calls = collectCalls(node, language);\n return {\n index,\n name: findFunctionName(node),\n startLine: node.startPosition.row + 1,\n startColumn: node.startPosition.column,\n endLine: node.endPosition.row + 1,\n returnsJsx: returnsJsx(node, language),\n cyclomaticComplexity: complexity.cyclomaticComplexity,\n cognitiveComplexity: complexity.cognitiveComplexity,\n callCount: calls.callCount,\n parameterCount: countParameters(node),\n callees: calls.callees,\n identifiers: collectIdentifiers(node),\n };\n}\n\n/** Counts declared parameters of a function/method, ignoring punctuation and comments. */\nfunction countParameters(node: Parser.SyntaxNode): number {\n const parametersNode =\n node.childForFieldName('parameters') ??\n node.namedChildren.find((child) => child.type === 'formal_parameters' || child.type === 'parameter_list');\n if (!parametersNode) {\n return 0;\n }\n\n return parametersNode.namedChildren.filter((child) => child.type !== 'comment').length;\n}\n\nfunction measureCallGraph(analyses: FunctionAnalysis[]): {\n fanInByIndex: Map<number, number>;\n fanOutByIndex: Map<number, number>;\n metrics: CallGraphMetrics;\n recursiveIndexes: Set<number>;\n} {\n const indexesByName = mapUniqueFunctionIndexesByName(analyses);\n const functionNames = new Set(indexesByName.keys());\n const fanInByIndex = new Map<number, number>();\n const fanOutByIndex = new Map<number, number>();\n const graph = new Map<number, Set<number>>();\n let callCount = 0;\n let internalCallCount = 0;\n const allCallees = new Set<string>();\n\n for (const analysis of analyses) {\n callCount += analysis.callCount;\n for (const callee of analysis.callees) {\n allCallees.add(callee);\n }\n\n const internalCalleeNames = new Set([...analysis.callees].filter((callee) => functionNames.has(callee)));\n const internalCalleeIndexes = new Set<number>();\n for (const callee of internalCalleeNames) {\n const calleeIndex = indexesByName.get(callee);\n if (calleeIndex !== undefined) {\n internalCalleeIndexes.add(calleeIndex);\n }\n }\n\n graph.set(analysis.index, internalCalleeIndexes);\n fanOutByIndex.set(analysis.index, internalCalleeNames.size);\n internalCallCount += internalCalleeNames.size;\n for (const calleeIndex of internalCalleeIndexes) {\n fanInByIndex.set(calleeIndex, (fanInByIndex.get(calleeIndex) ?? 0) + 1);\n }\n }\n\n const recursiveIndexes = findRecursiveIndexes(graph);\n\n return {\n fanInByIndex,\n fanOutByIndex,\n recursiveIndexes,\n metrics: {\n callCount,\n uniqueCalleeCount: allCallees.size,\n internalCallCount,\n internalEdgeCount: sum([...graph.values()].map((callees) => callees.size)),\n recursiveFunctionCount: recursiveIndexes.size,\n maxFanIn: maxMapValue(fanInByIndex),\n maxFanOut: maxMapValue(fanOutByIndex),\n maxCallDepth: measureMaxCallDepth(graph),\n },\n };\n}\n\nfunction mapUniqueFunctionIndexesByName(analyses: FunctionAnalysis[]): Map<string, number> {\n const indexesByName = new Map<string, number | undefined>();\n for (const analysis of analyses) {\n if (!analysis.name) {\n continue;\n }\n\n indexesByName.set(analysis.name, indexesByName.has(analysis.name) ? undefined : analysis.index);\n }\n return new Map([...indexesByName.entries()].filter((entry): entry is [string, number] => entry[1] !== undefined));\n}\n\nfunction measureComplexity(\n node: Parser.SyntaxNode,\n language: LanguageDefinition,\n nesting: number,\n stopAtNestedFunctions: boolean\n): ComplexityResult {\n let cyclomaticComplexity = 1;\n let cognitiveComplexity = 0;\n let nestingDepth = nesting;\n const functionNodes = new Set(language.functionNodeTypes);\n const decisionNodes = new Set(language.decisionNodeTypes);\n const nestingNodes = new Set(language.nestingNodeTypes);\n\n function visit(current: Parser.SyntaxNode, currentNesting: number, insideRoot: boolean): void {\n if (stopAtNestedFunctions && !insideRoot && functionNodes.has(current.type)) {\n return;\n }\n\n const isDecision = decisionNodes.has(current.type);\n const isNesting = nestingNodes.has(current.type);\n\n if (isDecision) {\n cyclomaticComplexity += 1;\n cognitiveComplexity += 1 + currentNesting;\n }\n\n if (isBooleanOperator(current)) {\n cyclomaticComplexity += 1;\n cognitiveComplexity += 1;\n }\n\n const childNesting = isNesting ? currentNesting + 1 : currentNesting;\n nestingDepth = Math.max(nestingDepth, childNesting);\n\n for (const child of current.children) {\n visit(child, childNesting, false);\n }\n }\n\n for (const child of node.children) {\n visit(child, nesting, false);\n }\n\n return { cyclomaticComplexity, cognitiveComplexity, nestingDepth };\n}\n\nfunction isBooleanOperator(node: Parser.SyntaxNode): boolean {\n if (node.isNamed) {\n return false;\n }\n\n return booleanOperators.has(node.text);\n}\n\nfunction collectCalls(\n root: Parser.SyntaxNode,\n language: LanguageDefinition\n): { callCount: number; callees: Set<string> } {\n const callees = new Set<string>();\n const functionNodeTypes = new Set(language.functionNodeTypes);\n let callCount = 0;\n\n function visit(node: Parser.SyntaxNode, insideRoot: boolean): void {\n if (!insideRoot && functionNodeTypes.has(node.type)) {\n return;\n }\n\n if (isCallNode(node)) {\n callCount += 1;\n const callee = findCalleeName(node);\n if (callee) {\n callees.add(callee);\n }\n }\n\n for (const child of node.namedChildren) {\n visit(child, false);\n }\n }\n\n visit(root, true);\n return { callCount, callees };\n}\n\nfunction collectIdentifiers(root: Parser.SyntaxNode): Set<string> {\n const identifiers = new Set<string>();\n\n function visit(node: Parser.SyntaxNode): void {\n if (node.type === 'identifier' || node.type === 'property_identifier' || node.type === 'field_identifier') {\n identifiers.add(node.text);\n }\n\n for (const child of node.namedChildren) {\n visit(child);\n }\n }\n\n visit(root);\n return identifiers;\n}\n\nfunction collectNodes(root: Parser.SyntaxNode, nodeTypes: Set<string>): Parser.SyntaxNode[] {\n const nodes: Parser.SyntaxNode[] = [];\n\n function visit(node: Parser.SyntaxNode): void {\n if (nodeTypes.has(node.type)) {\n nodes.push(node);\n }\n\n for (const child of node.namedChildren) {\n visit(child);\n }\n }\n\n visit(root);\n return nodes;\n}\n\nfunction returnsJsx(root: Parser.SyntaxNode, language: LanguageDefinition): boolean {\n const functionNodeTypes = new Set(language.functionNodeTypes);\n\n function visit(node: Parser.SyntaxNode, insideRoot: boolean): boolean {\n if (!insideRoot && functionNodeTypes.has(node.type)) {\n return false;\n }\n\n if (node.type === 'return_statement') {\n return containsJsxExpression(node, functionNodeTypes) || containsReactCreateElementCall(node, functionNodeTypes);\n }\n\n if (\n root.type === 'arrow_function' &&\n node === getArrowFunctionBody(root) &&\n node.type !== 'statement_block' &&\n !functionNodeTypes.has(node.type)\n ) {\n return containsJsxExpression(node, functionNodeTypes) || containsReactCreateElementCall(node, functionNodeTypes);\n }\n\n for (const child of node.namedChildren) {\n if (visit(child, false)) {\n return true;\n }\n }\n return false;\n }\n\n return visit(root, true);\n}\n\nfunction getArrowFunctionBody(node: Parser.SyntaxNode): Parser.SyntaxNode | undefined {\n return node.childForFieldName('body') ?? node.namedChild(node.namedChildCount - 1) ?? undefined;\n}\n\nfunction containsJsxExpression(root: Parser.SyntaxNode, functionNodeTypes: Set<string>): boolean {\n return containsNode(\n root,\n functionNodeTypes,\n (node) => node.type.startsWith('jsx_') || isJsxMappingCall(node, functionNodeTypes)\n );\n}\n\nfunction containsReactCreateElementCall(root: Parser.SyntaxNode, functionNodeTypes: Set<string>): boolean {\n return containsNode(root, functionNodeTypes, isReactCreateElementCall);\n}\n\nfunction containsNode(\n root: Parser.SyntaxNode,\n functionNodeTypes: Set<string>,\n predicate: (node: Parser.SyntaxNode) => boolean\n): boolean {\n function visit(node: Parser.SyntaxNode, insideRoot: boolean): boolean {\n if (!insideRoot && functionNodeTypes.has(node.type)) {\n return false;\n }\n\n if (predicate(node)) {\n return true;\n }\n\n for (const child of node.namedChildren) {\n if (visit(child, false)) {\n return true;\n }\n }\n return false;\n }\n\n return visit(root, true);\n}\n\nfunction isJsxMappingCall(node: Parser.SyntaxNode, functionNodeTypes: Set<string>): boolean {\n if (!isCallNode(node) || !isArrayMappingCallee(node.childForFieldName('function') ?? node.namedChild(0))) {\n return false;\n }\n\n return node.namedChildren.some((child) => containsReturnedJsxFunction(child, functionNodeTypes));\n}\n\nfunction isArrayMappingCallee(node: Parser.SyntaxNode | null): boolean {\n if (!node) {\n return false;\n }\n\n const calleeName = findRightmostIdentifier(node);\n return calleeName === 'map' || calleeName === 'flatMap';\n}\n\nfunction containsReturnedJsxFunction(root: Parser.SyntaxNode, functionNodeTypes: Set<string>): boolean {\n if (functionNodeTypes.has(root.type)) {\n return returnsJsxFromFunctionNode(root, functionNodeTypes);\n }\n\n return root.namedChildren.some((child) => containsReturnedJsxFunction(child, functionNodeTypes));\n}\n\nfunction returnsJsxFromFunctionNode(root: Parser.SyntaxNode, functionNodeTypes: Set<string>): boolean {\n const body = root.type === 'arrow_function' ? getArrowFunctionBody(root) : undefined;\n if (body && body.type !== 'statement_block' && !functionNodeTypes.has(body.type)) {\n return containsJsxExpression(body, functionNodeTypes) || containsReactCreateElementCall(body, functionNodeTypes);\n }\n\n return containsOwnReturnNode(\n root,\n functionNodeTypes,\n (node) => containsJsxExpression(node, functionNodeTypes) || containsReactCreateElementCall(node, functionNodeTypes)\n );\n}\n\nfunction containsOwnReturnNode(\n root: Parser.SyntaxNode,\n functionNodeTypes: Set<string>,\n predicate: (node: Parser.SyntaxNode) => boolean\n): boolean {\n function visit(node: Parser.SyntaxNode, insideRoot: boolean): boolean {\n if (!insideRoot && functionNodeTypes.has(node.type)) {\n return false;\n }\n\n if (node.type === 'return_statement' && predicate(node)) {\n return true;\n }\n\n for (const child of node.namedChildren) {\n if (visit(child, false)) {\n return true;\n }\n }\n return false;\n }\n\n return visit(root, true);\n}\n\nfunction measureModule(root: Parser.SyntaxNode, language: LanguageDefinition): ModuleMetrics {\n const importSources = new Set<string>();\n\n function visitImports(node: Parser.SyntaxNode): void {\n if (isImportSourceNode(node)) {\n for (const source of findImportSources(node, language, { expandPythonSubmodules: true })) {\n importSources.add(source);\n }\n }\n\n for (const child of node.namedChildren) {\n visitImports(child);\n }\n }\n\n visitImports(root);\n\n return {\n declarations: collectModuleDeclarations(root),\n importSources: [...importSources],\n };\n}\n\nfunction collectModuleDeclarations(root: Parser.SyntaxNode): DeclarationMetrics[] {\n const exportedNames = collectExportedNames(root);\n return root.namedChildren\n .flatMap((child) => collectTopLevelDeclarations(child, false))\n .map((declaration) => (exportedNames.has(declaration.name) ? { ...declaration, exported: true } : declaration));\n}\n\nfunction collectTopLevelDeclarations(node: Parser.SyntaxNode, exported: boolean): DeclarationMetrics[] {\n if (isModuleExportNode(node)) {\n return node.namedChildren.flatMap((child) => collectTopLevelDeclarations(child, true));\n }\n\n if (isDeclarationContainer(node)) {\n return node.namedChildren.flatMap((child) => collectTopLevelDeclarations(child, exported));\n }\n\n return declarationFromNode(node, exported);\n}\n\nfunction declarationFromNode(node: Parser.SyntaxNode, exported: boolean): DeclarationMetrics[] {\n if (!isTopLevelDeclarationNode(node)) {\n return [];\n }\n\n const name = findDeclarationName(node);\n return name ? [{ exported, name, startLine: node.startPosition.row + 1 }] : [];\n}\n\nfunction findDeclarationName(node: Parser.SyntaxNode): string | undefined {\n if (node.type === 'method_declaration') {\n return findGoMethodDeclarationName(node);\n }\n\n const nameNode = node.childForFieldName('name');\n if (nameNode) {\n return isDeclarationNameNode(nameNode) ? nameNode.text : undefined;\n }\n\n return node.namedChildren.find(isDeclarationNameNode)?.text;\n}\n\nfunction isModuleExportNode(node: Parser.SyntaxNode): boolean {\n return node.type === 'export_statement' || node.type === 'export_declaration';\n}\n\nfunction isDeclarationContainer(node: Parser.SyntaxNode): boolean {\n return (\n node.type === 'lexical_declaration' ||\n node.type === 'variable_declaration' ||\n node.type === 'decorated_definition' ||\n node.type === 'type_declaration' ||\n node.type === 'const_declaration' ||\n node.type === 'var_declaration' ||\n node.type === 'var_spec_list'\n );\n}\n\nfunction isTopLevelDeclarationNode(node: Parser.SyntaxNode): boolean {\n return (\n node.type === 'function_declaration' ||\n node.type === 'function_definition' ||\n node.type === 'function_item' ||\n node.type === 'method_declaration' ||\n node.type === 'class_declaration' ||\n node.type === 'class_definition' ||\n node.type === 'interface_declaration' ||\n node.type === 'type_alias_declaration' ||\n node.type === 'type_declaration' ||\n node.type === 'type_spec' ||\n node.type === 'const_spec' ||\n node.type === 'var_spec' ||\n node.type === 'variable_declarator'\n );\n}\n\nfunction isDeclarationNameNode(node: Parser.SyntaxNode): boolean {\n return (\n node.type === 'identifier' ||\n node.type === 'type_identifier' ||\n node.type === 'property_identifier' ||\n node.type === 'field_identifier'\n );\n}\n\nfunction collectExportedNames(root: Parser.SyntaxNode): Set<string> {\n const exportedNames = new Set<string>();\n\n function visit(node: Parser.SyntaxNode, insideSourcedExport: boolean): void {\n if (!insideSourcedExport && isExportSpecifierNode(node)) {\n const name = findExportedName(node);\n if (name) {\n exportedNames.add(name);\n }\n }\n\n const isSourcedExport =\n insideSourcedExport || (isModuleExportNode(node) && node.childForFieldName('source') !== null);\n for (const child of node.namedChildren) {\n visit(child, isSourcedExport);\n }\n }\n\n visit(root, false);\n return exportedNames;\n}\n\nfunction isExportSpecifierNode(node: Parser.SyntaxNode): boolean {\n return node.type === 'export_specifier' || node.type === 'namespace_export';\n}\n\nfunction findExportedName(node: Parser.SyntaxNode): string | undefined {\n const nameNode =\n node.childForFieldName('name') ?? node.childForFieldName('alias') ?? node.namedChildren.find(isDeclarationNameNode);\n return nameNode && isDeclarationNameNode(nameNode) ? nameNode.text : undefined;\n}\n\nfunction findGoMethodDeclarationName(node: Parser.SyntaxNode): string | undefined {\n const nameNode = node.childForFieldName('name');\n const receiverTypeNode = node.childForFieldName('receiver')?.namedChildren[0]?.childForFieldName('type');\n if (!nameNode || !isDeclarationNameNode(nameNode) || !receiverTypeNode) {\n return nameNode && isDeclarationNameNode(nameNode) ? nameNode.text : undefined;\n }\n\n return `${normalizeGoReceiverType(receiverTypeNode.text)}.${nameNode.text}`;\n}\n\nfunction normalizeGoReceiverType(receiverType: string): string {\n return receiverType.replaceAll(/\\s+/gu, '').replace(/^\\*+/u, '');\n}\n\nfunction measureCoupling(root: Parser.SyntaxNode, language: LanguageDefinition): CouplingMetrics {\n const importSources = new Set<string>();\n let importCount = 0;\n let exportCount = 0;\n\n function visit(node: Parser.SyntaxNode): void {\n if (isImportNode(node) || isDynamicImportNode(node)) {\n importCount += 1;\n }\n\n if (isImportSourceNode(node)) {\n for (const source of findImportSources(node, language, { expandPythonSubmodules: false })) {\n importSources.add(source);\n }\n }\n\n if (isExportNode(node)) {\n exportCount += 1;\n }\n\n for (const child of node.namedChildren) {\n visit(child);\n }\n }\n\n visit(root);\n\n const relativeImportCount = [...importSources].filter(isRelativeImportSource).length;\n\n return {\n importCount,\n importSourceCount: importSources.size,\n relativeImportCount,\n externalImportCount: importSources.size - relativeImportCount,\n exportCount,\n };\n}\n\nfunction measureSyntaxFeatures(root: Parser.SyntaxNode): SyntaxFeatureMetrics {\n const metrics: SyntaxFeatureMetrics = {\n assignmentCount: 0,\n awaitExpressionCount: 0,\n loopStatementCount: 0,\n mutableBindingCount: 0,\n returnStatementCount: 0,\n throwStatementCount: 0,\n tryStatementCount: 0,\n };\n\n function visit(node: Parser.SyntaxNode): void {\n if (isAssignmentNode(node)) {\n metrics.assignmentCount += 1;\n }\n if (isAwaitNode(node)) {\n metrics.awaitExpressionCount += 1;\n }\n if (isLoopNode(node)) {\n metrics.loopStatementCount += 1;\n }\n if (isMutableBindingNode(node)) {\n metrics.mutableBindingCount += 1;\n }\n if (isReturnNode(node)) {\n metrics.returnStatementCount += 1;\n }\n if (isThrowNode(node)) {\n metrics.throwStatementCount += 1;\n }\n if (isTryNode(node)) {\n metrics.tryStatementCount += 1;\n }\n\n for (const child of node.namedChildren) {\n visit(child);\n }\n }\n\n visit(root);\n return metrics;\n}\n\nfunction isAssignmentNode(node: Parser.SyntaxNode): boolean {\n return (\n node.type === 'assignment_expression' ||\n node.type === 'augmented_assignment_expression' ||\n node.type === 'assignment_statement' ||\n node.type === 'assignment' ||\n node.type === 'augmented_assignment' ||\n node.type === 'short_var_declaration'\n );\n}\n\nfunction isAwaitNode(node: Parser.SyntaxNode): boolean {\n return node.type === 'await_expression' || node.type === 'await';\n}\n\nfunction isLoopNode(node: Parser.SyntaxNode): boolean {\n return (\n node.type === 'for_statement' ||\n node.type === 'for_in_statement' ||\n node.type === 'while_statement' ||\n node.type === 'do_statement'\n );\n}\n\nfunction isMutableBindingNode(node: Parser.SyntaxNode): boolean {\n return (\n (node.type === 'lexical_declaration' && node.firstChild?.text === 'let') ||\n (node.type === 'variable_declaration' && node.firstChild?.text === 'var') ||\n node.type === 'var_declaration'\n );\n}\n\nfunction isReturnNode(node: Parser.SyntaxNode): boolean {\n return node.type === 'return_statement';\n}\n\nfunction isThrowNode(node: Parser.SyntaxNode): boolean {\n return node.type === 'throw_statement' || node.type === 'raise_statement';\n}\n\nfunction isTryNode(node: Parser.SyntaxNode): boolean {\n return node.type === 'try_statement';\n}\n\nfunction measureCohesion(analyses: FunctionAnalysis[]): CohesionMetrics {\n const allIdentifiers = new Set<string>();\n const sharedIdentifiers = new Set<string>();\n let overlapTotal = 0;\n let pairCount = 0;\n\n for (const analysis of analyses) {\n for (const identifier of analysis.identifiers) {\n allIdentifiers.add(identifier);\n }\n }\n\n for (let leftIndex = 0; leftIndex < analyses.length; leftIndex += 1) {\n for (let rightIndex = leftIndex + 1; rightIndex < analyses.length; rightIndex += 1) {\n const left = analyses[leftIndex];\n const right = analyses[rightIndex];\n if (!left || !right) {\n continue;\n }\n\n const intersection = intersectSets(left.identifiers, right.identifiers);\n const unionSize = new Set([...left.identifiers, ...right.identifiers]).size;\n for (const identifier of intersection) {\n sharedIdentifiers.add(identifier);\n }\n overlapTotal += unionSize === 0 ? 0 : intersection.size / unionSize;\n pairCount += 1;\n }\n }\n\n return {\n averageFunctionIdentifierOverlap: pairCount === 0 ? 1 : overlapTotal / pairCount,\n sharedIdentifierCount: sharedIdentifiers.size,\n uniqueIdentifierCount: allIdentifiers.size,\n };\n}\n\nfunction measureTypeComplexity(root: Parser.SyntaxNode): TypeComplexityMetrics {\n const metrics: TypeComplexityMetrics = {\n typeAnnotationCount: 0,\n typeAliasCount: 0,\n interfaceCount: 0,\n genericParameterCount: 0,\n unionTypeCount: 0,\n intersectionTypeCount: 0,\n conditionalTypeCount: 0,\n typeAssertionCount: 0,\n nonNullAssertionCount: 0,\n satisfiesExpressionCount: 0,\n };\n\n function visit(node: Parser.SyntaxNode): void {\n switch (node.type) {\n case 'type_annotation': {\n metrics.typeAnnotationCount += 1;\n break;\n }\n case 'type_alias_declaration': {\n metrics.typeAliasCount += 1;\n break;\n }\n case 'interface_declaration': {\n metrics.interfaceCount += 1;\n break;\n }\n case 'type_parameters':\n case 'type_parameter': {\n metrics.genericParameterCount += node.type === 'type_parameter' ? 1 : 0;\n break;\n }\n case 'union_type': {\n metrics.unionTypeCount += 1;\n break;\n }\n case 'intersection_type': {\n metrics.intersectionTypeCount += 1;\n break;\n }\n case 'conditional_type': {\n metrics.conditionalTypeCount += 1;\n break;\n }\n case 'as_expression':\n case 'type_assertion': {\n metrics.typeAssertionCount += 1;\n break;\n }\n case 'non_null_expression': {\n metrics.nonNullAssertionCount += 1;\n break;\n }\n case 'satisfies_expression': {\n metrics.satisfiesExpressionCount += 1;\n break;\n }\n }\n\n for (const child of node.namedChildren) {\n visit(child);\n }\n }\n\n visit(root);\n return metrics;\n}\n\nconst duplicateBlockTypes = new Set([\n 'statement_block',\n 'block',\n 'if_statement',\n 'for_statement',\n 'for_in_statement',\n 'while_statement',\n 'do_statement',\n 'try_statement',\n 'with_statement',\n 'switch_statement',\n 'switch_case',\n 'case_clause',\n 'match_statement',\n 'match_arm',\n 'except_clause',\n 'catch_clause',\n 'finally_clause',\n 'elif_clause',\n 'expression_statement',\n 'return_statement',\n 'jsx_element',\n 'jsx_self_closing_element',\n]);\n\n/** Minimum subtree size (node count) for a block to be considered for duplication, to skip trivial repeats. */\nconst minDuplicateBlockSize = 24;\n\ninterface DuplicateCandidate {\n node: Parser.SyntaxNode;\n shape: string;\n size: number;\n}\n\n/**\n * Detects copy-pasted code blocks within a file by grouping control-flow / block / JSX subtrees that\n * share the same syntactic shape (node types, ignoring identifiers and literals). Only maximal,\n * non-overlapping blocks are counted so nested matches are not double-counted. Literal-only structures\n * such as array or object data are excluded because their element nodes are not block types.\n */\nfunction measureDuplication(root: Parser.SyntaxNode): DuplicationMetrics {\n const candidates: DuplicateCandidate[] = [];\n const shapeCache = new Map<number, { shape: string; size: number }>();\n\n function visit(node: Parser.SyntaxNode): void {\n if (duplicateBlockTypes.has(node.type)) {\n const { size } = describeShape(node, shapeCache);\n if (size >= minDuplicateBlockSize) {\n const { shape } = describeShape(node, shapeCache);\n candidates.push({ node, shape, size });\n }\n }\n for (const child of node.namedChildren) {\n visit(child);\n }\n }\n visit(root);\n\n const byShape = new Map<string, DuplicateCandidate[]>();\n for (const candidate of candidates) {\n const group = byShape.get(candidate.shape) ?? [];\n group.push(candidate);\n byShape.set(candidate.shape, group);\n }\n\n // Count larger blocks first and skip any candidate nested inside an already-counted duplicate.\n const counted: DuplicateCandidate[] = [];\n const consumed: Parser.SyntaxNode[] = [];\n let duplicateBlockCount = 0;\n let maxDuplicateBlockSize = 0;\n const groupCounts = new Map<string, number>();\n for (const [shape, group] of byShape) {\n if (group.length < 2) {\n continue;\n }\n for (const candidate of group.toSorted((left, right) => right.size - left.size)) {\n if (consumed.some((ancestor) => isAncestor(ancestor, candidate.node))) {\n continue;\n }\n counted.push(candidate);\n consumed.push(candidate.node);\n groupCounts.set(shape, (groupCounts.get(shape) ?? 0) + 1);\n maxDuplicateBlockSize = Math.max(maxDuplicateBlockSize, candidate.size);\n }\n }\n let duplicateBlockGroupCount = 0;\n for (const count of groupCounts.values()) {\n if (count >= 2) {\n duplicateBlockCount += count - 1;\n duplicateBlockGroupCount += 1;\n }\n }\n\n return { duplicateBlockCount, duplicateBlockGroupCount, maxDuplicateBlockSize };\n}\n\n/** Serializes a subtree by node type only (ignoring identifiers and literals) and reports its node count. */\nfunction describeShape(\n node: Parser.SyntaxNode,\n cache: Map<number, { shape: string; size: number }>\n): { shape: string; size: number } {\n const cached = cache.get(node.id);\n if (cached) {\n return cached;\n }\n\n let shape = node.type;\n let size = 1;\n if (node.namedChildCount > 0) {\n const parts: string[] = [];\n for (const child of node.namedChildren) {\n const childShape = describeShape(child, cache);\n parts.push(childShape.shape);\n size += childShape.size;\n }\n shape = `${node.type}(${parts.join(',')})`;\n }\n\n const result = { shape, size };\n cache.set(node.id, result);\n return result;\n}\n\nfunction isAncestor(ancestor: Parser.SyntaxNode, node: Parser.SyntaxNode): boolean {\n let current = node.parent;\n while (current) {\n if (current.id === ancestor.id) {\n return true;\n }\n current = current.parent;\n }\n return false;\n}\n\nfunction measureLines(code: string, root: Parser.SyntaxNode): CodeMetrics['lines'] {\n const sourceLines = code.length === 0 ? [] : code.split(/\\r\\n|\\n|\\r/);\n const commentSpans = collectCommentSpans(root);\n let blank = 0;\n let comment = 0;\n\n for (const [index, line] of sourceLines.entries()) {\n if (line.trim() === '') {\n blank += 1;\n continue;\n }\n\n if (isCommentOnlyLine(line, index, commentSpans)) {\n comment += 1;\n }\n }\n\n return {\n total: sourceLines.length,\n code: sourceLines.length - blank - comment,\n comment,\n blank,\n };\n}\n\nfunction collectCommentSpans(root: Parser.SyntaxNode): CommentSpan[] {\n const spans: CommentSpan[] = [];\n\n function visit(node: Parser.SyntaxNode): void {\n if (node.type === 'comment' || node.type === 'line_comment' || node.type === 'block_comment') {\n for (let row = node.startPosition.row; row <= node.endPosition.row; row += 1) {\n spans.push({\n line: row,\n startColumn: row === node.startPosition.row ? node.startPosition.column : 0,\n endColumn: row === node.endPosition.row ? node.endPosition.column : Number.POSITIVE_INFINITY,\n });\n }\n }\n\n for (const child of node.namedChildren) {\n visit(child);\n }\n }\n\n visit(root);\n return spans;\n}\n\nfunction isCommentOnlyLine(line: string, lineIndex: number, spans: CommentSpan[]): boolean {\n const relevantSpans = spans.filter((span) => span.line === lineIndex);\n if (relevantSpans.length === 0) {\n return false;\n }\n\n const firstContentColumn = line.search(/\\S/);\n const lastContentColumn = line.trimEnd().length;\n\n return relevantSpans.some((span) => span.startColumn <= firstContentColumn && span.endColumn >= lastContentColumn);\n}\n\nfunction measureHalstead(root: Parser.SyntaxNode, code: string): HalsteadMetrics {\n const operators = new Map<string, number>();\n const operands = new Map<string, number>();\n\n function visit(node: Parser.SyntaxNode): void {\n if (node.type === 'comment') {\n return;\n }\n\n if (node.childCount === 0) {\n const text = code.slice(node.startIndex, node.endIndex);\n if (operatorTexts.has(text) || operatorTexts.has(node.type)) {\n incrementCount(operators, text || node.type);\n } else if (operandNodeTypes.has(node.type)) {\n incrementCount(operands, text);\n }\n return;\n }\n\n if (operatorTexts.has(node.type)) {\n incrementCount(operators, node.type);\n }\n\n for (const child of node.children) {\n visit(child);\n }\n }\n\n visit(root);\n\n const distinctOperators = operators.size;\n const distinctOperands = operands.size;\n const totalOperators = sum(operators.values());\n const totalOperands = sum(operands.values());\n const vocabulary = distinctOperators + distinctOperands;\n const length = totalOperators + totalOperands;\n const volume = vocabulary === 0 ? 0 : length * Math.log2(vocabulary);\n const difficulty = distinctOperands === 0 ? 0 : (distinctOperators / 2) * (totalOperands / distinctOperands);\n const effort = difficulty * volume;\n\n return {\n distinctOperators,\n distinctOperands,\n totalOperators,\n totalOperands,\n vocabulary,\n length,\n volume,\n difficulty,\n effort,\n time: effort / 18,\n bugs: volume / 3000,\n };\n}\n\nfunction findFunctionName(node: Parser.SyntaxNode): string | undefined {\n const wrappedName = findWrappedComponentName(node);\n if (wrappedName) {\n return wrappedName;\n }\n\n const nameNode = node.childForFieldName('name');\n if (nameNode) {\n return nameNode.text;\n }\n\n const parent = node.parent;\n if (!parent) {\n return undefined;\n }\n\n const parentName = parent.childForFieldName('name');\n return parentName?.text;\n}\n\nfunction findWrappedComponentName(node: Parser.SyntaxNode): string | undefined {\n let current: Parser.SyntaxNode | undefined = node;\n while (current) {\n const argumentsNode: Parser.SyntaxNode | null = current.parent;\n const callNode: Parser.SyntaxNode | null | undefined = argumentsNode?.parent;\n if (argumentsNode?.type !== 'arguments' || callNode?.type !== 'call_expression') {\n return undefined;\n }\n\n if (!isReactComponentWrapperCall(callNode)) {\n return undefined;\n }\n\n const declaratorNode = callNode.parent;\n if (declaratorNode?.type === 'variable_declarator') {\n return declaratorNode.childForFieldName('name')?.text;\n }\n\n current = callNode;\n }\n\n return undefined;\n}\n\nfunction isReactComponentWrapperCall(node: Parser.SyntaxNode): boolean {\n const calleeNode = node.childForFieldName('function') ?? node.namedChild(0);\n return (\n calleeNode?.text === 'memo' ||\n calleeNode?.text === 'React.memo' ||\n calleeNode?.text === 'forwardRef' ||\n calleeNode?.text === 'React.forwardRef'\n );\n}\n\nfunction isCallNode(node: Parser.SyntaxNode): boolean {\n return node.type === 'call_expression' || node.type === 'call';\n}\n\nfunction findCalleeName(node: Parser.SyntaxNode): string | undefined {\n const calleeNode = node.childForFieldName('function') ?? node.namedChild(0);\n if (!calleeNode) {\n return undefined;\n }\n\n return findRightmostIdentifier(calleeNode);\n}\n\nfunction findRightmostIdentifier(node: Parser.SyntaxNode): string | undefined {\n if (\n node.type === 'identifier' ||\n node.type === 'property_identifier' ||\n node.type === 'field_identifier' ||\n node.type === 'attribute'\n ) {\n return node.text;\n }\n\n for (let index = node.namedChildCount - 1; index >= 0; index -= 1) {\n const child = node.namedChild(index);\n if (!child) {\n continue;\n }\n\n const identifier = findRightmostIdentifier(child);\n if (identifier) {\n return identifier;\n }\n }\n\n return undefined;\n}\n\nfunction isReactCreateElementCall(node: Parser.SyntaxNode): boolean {\n if (!isCallNode(node)) {\n return false;\n }\n\n const calleeNode = node.childForFieldName('function') ?? node.namedChild(0);\n return calleeNode?.text === 'React.createElement' || calleeNode?.text === 'createElement';\n}\n\nfunction isImportNode(node: Parser.SyntaxNode): boolean {\n return (\n node.type === 'import_statement' ||\n node.type === 'import_declaration' ||\n node.type === 'import_from_statement' ||\n node.type === 'import_spec' ||\n node.type === 'import_spec_list'\n );\n}\n\nfunction isImportSourceNode(node: Parser.SyntaxNode): boolean {\n return (\n isImportNode(node) || isDynamicImportNode(node) || (isExportNode(node) && node.childForFieldName('source') !== null)\n );\n}\n\nfunction isDynamicImportNode(node: Parser.SyntaxNode): boolean {\n if (!isCallNode(node)) {\n return false;\n }\n\n const calleeNode = node.childForFieldName('function') ?? node.namedChild(0);\n return calleeNode?.text === 'import';\n}\n\nfunction findImportSources(\n node: Parser.SyntaxNode,\n language: LanguageDefinition,\n options: { expandPythonSubmodules: boolean }\n): string[] {\n if (language.name === 'python') {\n const pythonSources = findPythonImportSources(node, options);\n if (pythonSources.length > 0) {\n return pythonSources;\n }\n }\n\n if (isDynamicImportNode(node)) {\n return findDynamicImportSources(node);\n }\n\n const sourceNode = node.childForFieldName('source') ?? findFirstStringNode(node);\n return sourceNode ? [unquote(sourceNode.text)] : [];\n}\n\nfunction findDynamicImportSources(node: Parser.SyntaxNode): string[] {\n const argumentsNode = node.childForFieldName('arguments');\n const firstArgument = argumentsNode?.namedChild(0);\n return firstArgument && isStringNode(firstArgument) ? [unquote(firstArgument.text)] : [];\n}\n\nfunction isRelativeImportSource(source: string): boolean {\n return source.startsWith('.') || source.startsWith('/');\n}\n\nfunction findPythonImportSources(node: Parser.SyntaxNode, options: { expandPythonSubmodules: boolean }): string[] {\n if (node.type === 'import_from_statement') {\n const moduleNode = node.childForFieldName('module_name');\n if (!moduleNode) {\n return [];\n }\n\n const moduleSource = normalizeImportSource(moduleNode.text);\n const nameNodes = findChildrenByFieldName(node, 'name');\n if (!options.expandPythonSubmodules || !moduleSource.startsWith('.')) {\n return [moduleSource];\n }\n if (/^\\.+$/u.test(moduleSource) && nameNodes.length > 0) {\n return nameNodes.flatMap(findPythonImportNames).map((name) => `${moduleSource}${name}`);\n }\n const submoduleSources = nameNodes.flatMap(findPythonImportNames).map((name) => `${moduleSource}.${name}`);\n if (submoduleSources.length > 0) {\n return [moduleSource, ...submoduleSources];\n }\n return [moduleSource];\n }\n\n if (node.type !== 'import_statement') {\n return [];\n }\n\n return node.namedChildren\n .map((child) => findPythonImportedModuleName(child))\n .filter((source) => source !== undefined);\n}\n\nfunction findPythonImportNames(node: Parser.SyntaxNode): string[] {\n if (node.type === 'aliased_import') {\n const nameNode = node.childForFieldName('name');\n return nameNode ? findPythonImportNames(nameNode) : [];\n }\n\n if (node.type === 'identifier') {\n return [node.text];\n }\n\n if (node.type === 'dotted_name') {\n return [normalizeImportSource(node.text)];\n }\n\n return node.namedChildren.flatMap(findPythonImportNames);\n}\n\nfunction findChildrenByFieldName(node: Parser.SyntaxNode, fieldName: string): Parser.SyntaxNode[] {\n const children: Parser.SyntaxNode[] = [];\n for (let index = 0; index < node.childCount; index += 1) {\n const child = node.child(index);\n if (child && node.fieldNameForChild(index) === fieldName) {\n children.push(child);\n }\n }\n return children;\n}\n\nfunction findPythonImportedModuleName(node: Parser.SyntaxNode): string | undefined {\n if (node.type === 'dotted_name' || node.type === 'relative_import') {\n return normalizeImportSource(node.text);\n }\n\n const nameNode = node.childForFieldName('name');\n if (nameNode) {\n return normalizeImportSource(nameNode.text);\n }\n\n for (const child of node.namedChildren) {\n const source = findPythonImportedModuleName(child);\n if (source) {\n return source;\n }\n }\n\n return undefined;\n}\n\nfunction normalizeImportSource(source: string): string {\n return source.replaceAll(/\\s+/gu, '');\n}\n\nfunction findFirstStringNode(node: Parser.SyntaxNode): Parser.SyntaxNode | undefined {\n if (isStringNode(node)) {\n return node;\n }\n\n for (const child of node.namedChildren) {\n const stringNode = findFirstStringNode(child);\n if (stringNode) {\n return stringNode;\n }\n }\n\n return undefined;\n}\n\nfunction isStringNode(node: Parser.SyntaxNode): boolean {\n return node.type === 'string' || node.type === 'string_literal' || node.type === 'interpreted_string_literal';\n}\n\nfunction unquote(value: string): string {\n return value.replaceAll(/^['\"`]|['\"`]$/gu, '');\n}\n\nfunction isExportNode(node: Parser.SyntaxNode): boolean {\n return node.type.startsWith('export') || node.type === 'public_field_definition';\n}\n\nfunction findRecursiveIndexes(graph: Map<number, Set<number>>): Set<number> {\n const recursiveIndexes = new Set<number>();\n\n for (const index of graph.keys()) {\n if (canReach(index, index, graph, new Set())) {\n recursiveIndexes.add(index);\n }\n }\n\n return recursiveIndexes;\n}\n\nfunction canReach(start: number, target: number, graph: Map<number, Set<number>>, visited: Set<number>): boolean {\n const callees = graph.get(start);\n if (!callees) {\n return false;\n }\n\n for (const callee of callees) {\n if (callee === target) {\n return true;\n }\n\n if (!visited.has(callee)) {\n visited.add(callee);\n if (canReach(callee, target, graph, visited)) {\n return true;\n }\n }\n }\n\n return false;\n}\n\nfunction measureMaxCallDepth(graph: Map<number, Set<number>>): number {\n let maxDepth = 0;\n for (const index of graph.keys()) {\n maxDepth = Math.max(maxDepth, measureCallDepth(index, graph, new Set()));\n }\n return maxDepth;\n}\n\nfunction measureCallDepth(index: number, graph: Map<number, Set<number>>, pathIndexes: Set<number>): number {\n const callees = graph.get(index);\n if (!callees || callees.size === 0 || pathIndexes.has(index)) {\n return 0;\n }\n\n pathIndexes.add(index);\n let maxDepth = 0;\n for (const callee of callees) {\n maxDepth = Math.max(maxDepth, 1 + measureCallDepth(callee, graph, new Set(pathIndexes)));\n }\n return maxDepth;\n}\n\nfunction intersectSets(left: Set<string>, right: Set<string>): Set<string> {\n const intersection = new Set<string>();\n for (const value of left) {\n if (right.has(value)) {\n intersection.add(value);\n }\n }\n return intersection;\n}\n\nfunction calculateMaintainabilityIndex(volume: number, complexity: number, loc: number): number {\n if (loc === 0) {\n return 100;\n }\n\n const raw = 171 - 5.2 * Math.log(Math.max(volume, 1)) - 0.23 * complexity - 16.2 * Math.log(loc);\n return Math.max(0, Math.min(100, (raw * 100) / 171));\n}\n\nfunction incrementCount(map: Map<string, number>, value: string): void {\n map.set(value, (map.get(value) ?? 0) + 1);\n}\n\nfunction maxMetric(functions: FunctionMetrics[], key: 'cyclomaticComplexity' | 'cognitiveComplexity'): number {\n return functions.length === 0 ? 0 : Math.max(...functions.map((fn) => fn[key]));\n}\n\nfunction maxMapValue(map: Map<unknown, number>): number {\n let maximum = 0;\n for (const value of map.values()) {\n maximum = Math.max(maximum, value);\n }\n return maximum;\n}\n\nfunction sum(values: Iterable<number>): number {\n let total = 0;\n for (const value of values) {\n total += value;\n }\n return total;\n}\n"],"names":["booleanOperators","Set","operatorTexts","operandNodeTypes","TreeMeasurer","registry","createLanguageRegistry","registerLanguage","language","this","set","name","alias","aliases","getSupportedLanguages","values","map","measure","code","options","get","Error","parser","Parser","setLanguage","parserLanguage","root","parse","undefined","bufferSize","length","rootNode","structuralMetrics","functions","analyses","node","index","complexity","measureComplexity","calls","callees","functionNodeTypes","callCount","visit","insideRoot","has","type","isCallNode","callee","calleeNode","childForFieldName","namedChild","findRightmostIdentifier","findCalleeName","add","child","namedChildren","collectCalls","findFunctionName","startLine","startPosition","row","startColumn","column","endLine","endPosition","returnsJsx","cyclomaticComplexity","cognitiveComplexity","parameterCount","countParameters","identifiers","collectIdentifiers","analyzeFunction","callGraph","indexesByName","Map","analysis","entries","filter","entry","mapUniqueFunctionIndexesByName","functionNames","keys","fanInByIndex","fanOutByIndex","graph","internalCallCount","allCallees","internalCalleeNames","internalCalleeIndexes","calleeIndex","size","recursiveIndexes","canReach","findRecursiveIndexes","metrics","uniqueCalleeCount","internalEdgeCount","sum","recursiveFunctionCount","maxFanIn","maxMapValue","maxFanOut","maxCallDepth","measureMaxCallDepth","measureCallGraph","fanIn","fanOut","recursive","coupling","measureCoupling","module","measureModule","cohesion","measureCohesion","syntaxFeatures","measureSyntaxFeatures","typeComplexity","measureTypeComplexity","measureStructuralMetrics","collectNodes","functionMetrics","globalComplexity","lines","sourceLines","split","commentSpans","spans","push","line","endColumn","Number","POSITIVE_INFINITY","collectCommentSpans","blank","comment","trim","isCommentOnlyLine","total","measureLines","halstead","operators","operands","childCount","text","slice","startIndex","endIndex","incrementCount","children","distinctOperators","distinctOperands","totalOperators","totalOperands","vocabulary","volume","Math","log2","difficulty","effort","time","bugs","measureHalstead","bytes","Buffer","byteLength","classCount","classNodeTypes","functionCount","maxCyclomaticComplexity","maxMetric","maxCognitiveComplexity","nestingDepth","duplication","measureDuplication","maintainabilityIndex","calculateMaintainabilityIndex","syntaxTree","includeSyntaxTree","toString","defaultMeasurer","measureCode","parametersNode","find","nesting","stopAtNestedFunctions","functionNodes","decisionNodes","decisionNodeTypes","nestingNodes","nestingNodeTypes","current","currentNesting","isDecision","isNesting","isNamed","isBooleanOperator","childNesting","max","nodeTypes","nodes","containsJsxExpression","containsReactCreateElementCall","getArrowFunctionBody","namedChildCount","containsNode","startsWith","calleeName","isArrayMappingCallee","some","containsReturnedJsxFunction","isJsxMappingCall","isReactCreateElementCall","predicate","body","containsOwnReturnNode","returnsJsxFromFunctionNode","importSources","visitImports","isImportSourceNode","source","findImportSources","expandPythonSubmodules","declarations","collectModuleDeclarations","exportedNames","insideSourcedExport","isExportSpecifierNode","nameNode","isDeclarationNameNode","findExportedName","isSourcedExport","isModuleExportNode","collectExportedNames","flatMap","collectTopLevelDeclarations","declaration","exported","isDeclarationContainer","isTopLevelDeclarationNode","receiverTypeNode","receiverType","replaceAll","replace","findGoMethodDeclarationName","findDeclarationName","declarationFromNode","importCount","exportCount","isImportNode","isDynamicImportNode","isExportNode","relativeImportCount","isRelativeImportSource","importSourceCount","externalImportCount","assignmentCount","awaitExpressionCount","loopStatementCount","mutableBindingCount","returnStatementCount","throwStatementCount","tryStatementCount","isAssignmentNode","isAwaitNode","isLoopNode","firstChild","isMutableBindingNode","isReturnNode","isThrowNode","isTryNode","allIdentifiers","sharedIdentifiers","overlapTotal","pairCount","identifier","leftIndex","rightIndex","left","right","intersection","intersectSets","unionSize","averageFunctionIdentifierOverlap","sharedIdentifierCount","uniqueIdentifierCount","typeAnnotationCount","typeAliasCount","interfaceCount","genericParameterCount","unionTypeCount","intersectionTypeCount","conditionalTypeCount","typeAssertionCount","nonNullAssertionCount","satisfiesExpressionCount","duplicateBlockTypes","minDuplicateBlockSize","candidates","shapeCache","describeShape","shape","byShape","candidate","group","consumed","duplicateBlockCount","maxDuplicateBlockSize","groupCounts","toSorted","ancestor","isAncestor","duplicateBlockGroupCount","count","cache","cached","id","parts","childShape","join","result","parent","lineIndex","relevantSpans","span","firstContentColumn","search","lastContentColumn","trimEnd","wrappedName","argumentsNode","callNode","isReactComponentWrapperCall","declaratorNode","findWrappedComponentName","parentName","pythonSources","moduleNode","moduleSource","normalizeImportSource","nameNodes","fieldName","fieldNameForChild","findChildrenByFieldName","test","findPythonImportNames","submoduleSources","findPythonImportedModuleName","findPythonImportSources","firstArgument","isStringNode","unquote","findDynamicImportSources","sourceNode","findFirstStringNode","stringNode","value","start","target","visited","maxDepth","measureCallDepth","pathIndexes","loc","raw","log","min","key","fn","maximum"],"mappings":"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"}
|