code-gauge 3.0.0 → 4.0.0
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/README.md +83 -21
- package/dist/cli.cjs +3 -3
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +3 -3
- package/dist/cli.js.map +1 -1
- package/dist/cliConfig.cjs +1 -1
- package/dist/cliConfig.cjs.map +1 -1
- package/dist/cliConfig.d.ts +11 -0
- package/dist/cliConfig.js +1 -1
- package/dist/cliConfig.js.map +1 -1
- package/dist/crossFileDuplication.cjs +1 -1
- package/dist/crossFileDuplication.cjs.map +1 -1
- package/dist/crossFileDuplication.js +1 -1
- package/dist/crossFileDuplication.js.map +1 -1
- package/dist/diffCommand.cjs +5 -0
- package/dist/diffCommand.cjs.map +1 -0
- package/dist/diffCommand.d.ts +17 -0
- package/dist/diffCommand.js +5 -0
- package/dist/diffCommand.js.map +1 -0
- package/dist/duplication.cjs +1 -1
- package/dist/duplication.cjs.map +1 -1
- package/dist/duplication.d.ts +20 -24
- package/dist/duplication.js +1 -1
- package/dist/duplication.js.map +1 -1
- package/dist/git.cjs +2 -0
- package/dist/git.cjs.map +1 -0
- package/dist/git.d.ts +27 -0
- package/dist/git.js +2 -0
- package/dist/git.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1 -1
- package/dist/languages.cjs +1 -1
- package/dist/languages.cjs.map +1 -1
- package/dist/languages.d.ts +5 -0
- package/dist/languages.js +1 -1
- package/dist/languages.js.map +1 -1
- package/dist/metrics.cjs +1 -1
- package/dist/metrics.cjs.map +1 -1
- package/dist/metrics.d.ts +18 -5
- package/dist/metrics.js +1 -1
- package/dist/metrics.js.map +1 -1
- package/dist/nativeMetrics.cjs +3 -1
- package/dist/nativeMetrics.cjs.map +1 -1
- package/dist/nativeMetrics.d.ts +29 -10
- package/dist/nativeMetrics.js +3 -1
- package/dist/nativeMetrics.js.map +1 -1
- package/dist/regressionGate.cjs +2 -0
- package/dist/regressionGate.cjs.map +1 -0
- package/dist/regressionGate.d.ts +106 -0
- package/dist/regressionGate.js +2 -0
- package/dist/regressionGate.js.map +1 -0
- package/dist/scan.cjs +2 -0
- package/dist/scan.cjs.map +1 -0
- package/dist/scan.d.ts +55 -0
- package/dist/scan.js +2 -0
- package/dist/scan.js.map +1 -0
- package/dist/types.d.ts +18 -13
- package/native/Cargo.lock +523 -0
- package/native/Cargo.toml +45 -0
- package/native/build.rs +3 -0
- package/native/src/complexity.rs +627 -0
- package/native/src/dep_degree.rs +253 -0
- package/native/src/duplication.rs +2007 -0
- package/native/src/functions.rs +345 -0
- package/native/src/languages.rs +647 -0
- package/native/src/lib.rs +101 -0
- package/native/src/measure.rs +590 -0
- package/native/src/ncss.rs +263 -0
- package/native/src/types.rs +135 -0
- package/native/src/util.rs +139 -0
- package/package.json +16 -19
- package/scripts/buildNative.mjs +25 -0
- package/scripts/installNative.mjs +96 -0
- package/dist/ncss.cjs +0 -2
- package/dist/ncss.cjs.map +0 -1
- package/dist/ncss.d.ts +0 -17
- package/dist/ncss.js +0 -2
- package/dist/ncss.js.map +0 -1
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Postinstall hook ensuring the native Rust addon is available: a prebuilt platform package or an
|
|
3
|
+
// already-built native/code-gauge.node is kept when it serves the payload version this checkout
|
|
4
|
+
// expects (a stale addon surviving a `git pull` must not be kept — the runtime loader would
|
|
5
|
+
// reject it), otherwise the addon is built from the bundled sources when a Rust toolchain is
|
|
6
|
+
// available. Never fails the install — the whole body is guarded and the process always exits 0
|
|
7
|
+
// (npm runs lifecycle scripts through cmd.exe on Windows, where a `|| true` suffix would not
|
|
8
|
+
// work) — and the runtime loader raises a descriptive error on first use if no addon could be
|
|
9
|
+
// provided.
|
|
10
|
+
|
|
11
|
+
import { execFileSync } from 'node:child_process';
|
|
12
|
+
import { existsSync, readFileSync, rmSync } from 'node:fs';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
import { fileURLToPath } from 'node:url';
|
|
15
|
+
|
|
16
|
+
const packageRoot = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
17
|
+
|
|
18
|
+
// No explicit process.exit: nothing here keeps the event loop alive, so the process ends with
|
|
19
|
+
// code 0 on its own once the synchronous work returns — and exit() could truncate the warning's
|
|
20
|
+
// asynchronous stderr write (stderr is a pipe under npm, which is asynchronous on Windows).
|
|
21
|
+
try {
|
|
22
|
+
installNativeAddon();
|
|
23
|
+
} catch (error) {
|
|
24
|
+
warnBuildFailure(error);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function installNativeAddon() {
|
|
28
|
+
// The authoritative payload version lives in the bundled Rust source; a parse failure yields
|
|
29
|
+
// undefined, which no addon reports, so validation then always falls through to a fresh build.
|
|
30
|
+
const expectedPayloadVersion = /pub fn payload_version\(\) -> u32 \{\s*(\d+)/.exec(
|
|
31
|
+
readFileSync(path.join(packageRoot, 'native', 'src', 'lib.rs'), 'utf8')
|
|
32
|
+
)?.[1];
|
|
33
|
+
|
|
34
|
+
if (
|
|
35
|
+
servesExpectedPayload(`code-gauge-${platformTriplet()}`, expectedPayloadVersion) ||
|
|
36
|
+
servesExpectedPayload(path.join(packageRoot, 'native', 'code-gauge.node'), expectedPayloadVersion)
|
|
37
|
+
) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
execFileSync(process.execPath, [path.join(packageRoot, 'scripts', 'buildNative.mjs')], { stdio: 'inherit' });
|
|
43
|
+
} catch (error) {
|
|
44
|
+
warnBuildFailure(error);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// In an installed package the cargo build tree (hundreds of MB) buys nothing once the addon is
|
|
48
|
+
// copied out; a repository checkout (recognized by its sources) keeps it as the build cache.
|
|
49
|
+
// Guarded separately: a cleanup failure (e.g. a held Windows file handle) leaves a usable addon
|
|
50
|
+
// behind and must not be reported as a build failure.
|
|
51
|
+
if (!existsSync(path.join(packageRoot, 'src'))) {
|
|
52
|
+
try {
|
|
53
|
+
rmSync(path.join(packageRoot, 'native', 'target'), { recursive: true, force: true });
|
|
54
|
+
} catch {
|
|
55
|
+
// The leftover build tree only costs disk space.
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// The platform-package suffix in the napi-rs naming convention: Linux is qualified by libc ABI
|
|
61
|
+
// (a glibc-linked addon cannot load on Alpine/musl) and Windows by toolchain ABI. Must match
|
|
62
|
+
// platformTriplet in src/nativeMetrics.ts.
|
|
63
|
+
function platformTriplet() {
|
|
64
|
+
const base = `${process.platform}-${process.arch}`;
|
|
65
|
+
if (process.platform === 'win32') {
|
|
66
|
+
return `${base}-msvc`;
|
|
67
|
+
}
|
|
68
|
+
if (process.platform !== 'linux') {
|
|
69
|
+
return base;
|
|
70
|
+
}
|
|
71
|
+
return process.report?.getReport()?.header?.glibcVersionRuntime ? `${base}-gnu` : `${base}-musl`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Probed in a child process: loading the addon here would keep its library mapped for this
|
|
75
|
+
// process's lifetime, and overwriting a mapped DLL is refused on Windows — exactly what the
|
|
76
|
+
// stale-addon rebuild below must be able to do.
|
|
77
|
+
function servesExpectedPayload(specifier, expectedPayloadVersion) {
|
|
78
|
+
try {
|
|
79
|
+
const reported = execFileSync(
|
|
80
|
+
process.execPath,
|
|
81
|
+
['-p', `String(require(${JSON.stringify(specifier)}).payloadVersion?.())`],
|
|
82
|
+
// stderr is discarded: a missing platform package is the normal case, not a diagnostic.
|
|
83
|
+
{ cwd: packageRoot, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }
|
|
84
|
+
).trim();
|
|
85
|
+
return expectedPayloadVersion !== undefined && reported === expectedPayloadVersion;
|
|
86
|
+
} catch {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function warnBuildFailure(error) {
|
|
92
|
+
console.warn(
|
|
93
|
+
`code-gauge: could not build the native addon (${error instanceof Error ? error.message : String(error)}). ` +
|
|
94
|
+
'Install a Rust toolchain and run `node scripts/buildNative.mjs` in the package directory to enable it.'
|
|
95
|
+
);
|
|
96
|
+
}
|
package/dist/ncss.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";const e=new Set([`comment`,`line_comment`,`block_comment`]),t=new Set([`attribute_item`,`inner_attribute_item`,`empty_statement`,`heredoc_body`,`parenthesized_statements`]),n=new Set([`property_signature`,`method_signature`,`index_signature`,`construct_signature`,`call_signature`]),r=new Set([`else_clause`,`elif_clause`,`else`,`elsif`]),i=new Set([`if_statement`,`if_expression`]),a=new Set([`struct_specifier`,`enum_specifier`,`union_specifier`,`class_specifier`]),o=new WeakMap;function s(e){o.delete(e)}function c(e){let t=o.get(e);return t||(t={countable:new Set(e.ncssNodeTypes),containers:new Set(e.ncssContainerNodeTypes)},o.set(e,t)),t}function l(e,t){let{countable:n,containers:r}=c(t),i=0;function a(e){i+=u(e,n,r);for(let t of e.children)a(t)}return a(e),i}function u(n,r,a){if(!n.isNamed||e.has(n.type)||h(n))return 0;let o=0,s=f(n,a)&&!a.has(n.type)&&!t.has(n.type);return(d(n,r)||s||g(n))&&!p(n,r)&&(o+=1),i.has(n.type)&&(o+=y(n).length),o}function d(e,t){return t.has(e.type)?a.has(e.type)?e.childForFieldName(`body`)!==null:e.type!==`resource`||e.childForFieldName(`name`)!==null:!1}function f(e,t){let n=e.parent;for(;n&&n.type===`parenthesized_statements`;)n=n.parent;return n!==null&&t.has(n.type)}function p(e,t){if(e.type!==`export_statement`)return!1;let n=e.childForFieldName(`declaration`);return n!==null&&(t.has(n.type)||n.type===`internal_module`||n.type===`ambient_declaration`)}const m=new Set([`init`,`initializer`,`condition`,`update`,`increment`]);function h(e){let t=e.parent;if(!t)return!1;if(t.type===`init_statement`&&t.parent?.type===`for_range_loop`)return!0;if(t.type!==`for_statement`&&t.type!==`for_clause`&&t.type!==`for_range_loop`)return!1;for(let n=0;n<t.childCount;n+=1)if(t.child(n)?.id===e.id)return m.has(t.fieldNameForChild(n)??``);return!1}function g(e){let t=e.parent?.type;return e.type===`block`&&t===`class_body`||n.has(e.type)&&t===`interface_body`||t===`match_arm`&&e.type!==`block`&&v(e,`value`)||e.type===`method_signature`&&t===`class_body`||e.type===`internal_module`&&t!==`expression_statement`||(t===`method`||t===`singleton_method`)&&e.type!==`body_statement`&&v(e,`body`)?!0:e.type===`friend_declaration`?!e.namedChildren.some(e=>e.type===`declaration`||e.type===`function_definition`):e.type===`macro_invocation`&&(t===`source_file`||t===`declaration_list`)?!0:e.type===`field_declaration`&&t===`field_declaration_list`?_(e.parent?.parent,`struct_type`):e.type===`method_elem`||e.type===`method_spec`||e.type===`type_elem`?_(e.parent,`interface_type`):!1}function _(e,t){return e?.type===t?e.parent?.type===`type_spec`||e.parent?.type===`type_alias`:!1}function v(e,t){let n=e.parent;if(!n)return!1;for(let r=0;r<n.childCount;r+=1)if(n.child(r)?.id===e.id)return n.fieldNameForChild(r)===t;return!1}function y(e){let t=[];for(let n=0;n<e.childCount;n+=1){let i=e.child(n);i&&e.fieldNameForChild(n)===`alternative`&&!r.has(i.type)&&t.push(i)}return t}exports.commentNodeTypes=e,exports.countNcss=l,exports.getNcssSets=c,exports.invalidateNcssSetsCache=s,exports.ncssContribution=u;
|
|
2
|
-
//# sourceMappingURL=ncss.cjs.map
|
package/dist/ncss.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ncss.cjs","names":[],"sources":["../src/ncss.ts"],"sourcesContent":["import type Parser from 'tree-sitter';\nimport type { LanguageDefinition } from './types.js';\n\nexport const commentNodeTypes = new Set(['comment', 'line_comment', 'block_comment']);\n\n// Nodes never counted positionally inside NCSS containers: metadata, empty statements, Ruby\n// heredoc bodies (tree-sitter emits them as siblings of the statement that opened the heredoc),\n// and Ruby statement parentheses (transparent wrappers whose children count instead).\nconst positionalExclusionTypes = new Set([\n 'attribute_item',\n 'inner_attribute_item',\n 'empty_statement',\n 'heredoc_body',\n 'parenthesized_statements',\n]);\n\n// TypeScript interface members count like Java interface members, but the same node types appear\n// inside object-type annotations (`let x: { a: number }`), which are part of one declaration, so\n// they only count directly under an interface body.\nconst interfaceMemberNodeTypes = new Set([\n 'property_signature',\n 'method_signature',\n 'index_signature',\n 'construct_signature',\n 'call_signature',\n]);\n\n// An if-branch wrapped in one of these already counts through ncssNodeTypes; a bare `alternative`\n// (Java/Go put the else branch directly in the field) needs the extra `else` count instead.\nconst elseClauseNodeTypes = new Set(['else_clause', 'elif_clause', 'else', 'elsif']);\n\nconst ifNodeTypes = new Set(['if_statement', 'if_expression']);\n\n// C/C++ type specifiers only declare something when they carry a body (`struct S { ... }`);\n// without one they are mere type references inside other declarations.\nconst bodylessNcssSpecifierTypes = new Set([\n 'struct_specifier',\n 'enum_specifier',\n 'union_specifier',\n 'class_specifier',\n]);\n\n/**\n * Counts non-commenting source statements (NCSS) in the subtree, PMD-style: one per declaration,\n * statement, and clause (`else`, `case`/`default` label, `catch`, `finally`, try-with-resources\n * resource); `try` itself, braces, blank lines, and comments count 0.\n */\nexport interface NcssSets {\n countable: Set<string>;\n containers: Set<string>;\n}\n\n// Cached per language: countNcss runs once per function plus once per file, so per-call Set\n// construction would add a measurable constant factor on large files.\nconst ncssSetsCache = new WeakMap<LanguageDefinition, NcssSets>();\n\n/** Drops the cached sets so a re-registered (possibly mutated) definition rebuilds them. */\nexport function invalidateNcssSetsCache(language: LanguageDefinition): void {\n ncssSetsCache.delete(language);\n}\n\nexport function getNcssSets(language: LanguageDefinition): NcssSets {\n let sets = ncssSetsCache.get(language);\n if (!sets) {\n sets = { countable: new Set(language.ncssNodeTypes), containers: new Set(language.ncssContainerNodeTypes) };\n ncssSetsCache.set(language, sets);\n }\n return sets;\n}\n\nexport function countNcss(node: Parser.SyntaxNode, language: LanguageDefinition): number {\n const { countable, containers } = getNcssSets(language);\n let count = 0;\n\n function visit(current: Parser.SyntaxNode): void {\n count += ncssContribution(current, countable, containers);\n for (const child of current.children) {\n visit(child);\n }\n }\n\n visit(node);\n return count;\n}\n\nexport function ncssContribution(node: Parser.SyntaxNode, countable: Set<string>, containers: Set<string>): number {\n if (!node.isNamed || commentNodeTypes.has(node.type) || isForHeaderNode(node)) {\n return 0;\n }\n\n let contribution = 0;\n const positional =\n isInContainerPosition(node, containers) && !containers.has(node.type) && !positionalExclusionTypes.has(node.type);\n if (\n (countsThroughNodeType(node, countable) || positional || countsContextually(node)) &&\n !isDeclarationWrapper(node, countable)\n ) {\n contribution += 1;\n }\n\n // A bare else branch (Java/Go `alternative:` without an else-clause wrapper) counts 1 like the\n // `else` keyword does in PMD; an `else if` chain charges the nested if separately on top.\n if (ifNodeTypes.has(node.type)) {\n contribution += findBareAlternatives(node).length;\n }\n\n return contribution;\n}\n\nfunction countsThroughNodeType(node: Parser.SyntaxNode, countable: Set<string>): boolean {\n if (!countable.has(node.type)) {\n return false;\n }\n if (bodylessNcssSpecifierTypes.has(node.type)) {\n return node.childForFieldName('body') !== null;\n }\n // A try-with-resources `resource` counts only when it declares a variable; `try (r)` reuses an\n // existing one and adds no statement (matching PMD).\n if (node.type === 'resource') {\n return node.childForFieldName('name') !== null;\n }\n return true;\n}\n\n/**\n * Direct container children count positionally; Ruby's `(foo; bar)` statement parentheses are\n * transparent (through arbitrary nesting), so their children count when the parentheses\n * themselves sit in a container.\n */\nfunction isInContainerPosition(node: Parser.SyntaxNode, containers: Set<string>): boolean {\n let ancestor = node.parent;\n while (ancestor && ancestor.type === 'parenthesized_statements') {\n ancestor = ancestor.parent;\n }\n return ancestor !== null && containers.has(ancestor.type);\n}\n\n/**\n * `export const x = 1` nests a countable declaration inside `export_statement`; only the inner\n * declaration counts, mirroring how PMD counts one statement per declared entity. The nested\n * declaration may also count contextually (`export namespace N {}` → internal_module) or sit one\n * level deeper (`export declare function f(): void;` → ambient_declaration > function_signature).\n */\nfunction isDeclarationWrapper(node: Parser.SyntaxNode, countable: Set<string>): boolean {\n if (node.type !== 'export_statement') {\n return false;\n }\n const declaration = node.childForFieldName('declaration');\n return (\n declaration !== null &&\n (countable.has(declaration.type) ||\n declaration.type === 'internal_module' ||\n declaration.type === 'ambient_declaration')\n );\n}\n\nconst forHeaderFieldNames = new Set(['init', 'initializer', 'condition', 'update', 'increment']);\n\n/**\n * Statement-shaped nodes in a `for` header (`for (int i = 0; i < n; i++)`) are part of the loop\n * statement, which already counts; PMD does not count them separately. JavaScript parses the\n * condition as an `expression_statement` and Go parses the update as an `inc_statement`, so all\n * header fields must be excluded, not just the initializer.\n */\nfunction isForHeaderNode(node: Parser.SyntaxNode): boolean {\n const parent = node.parent;\n if (!parent) {\n return false;\n }\n // C++20 range-for initializers nest one level deeper: for_range_loop > init_statement > node.\n if (parent.type === 'init_statement' && parent.parent?.type === 'for_range_loop') {\n return true;\n }\n if (parent.type !== 'for_statement' && parent.type !== 'for_clause' && parent.type !== 'for_range_loop') {\n return false;\n }\n for (let index = 0; index < parent.childCount; index += 1) {\n if (parent.child(index)?.id === node.id) {\n return forHeaderFieldNames.has(parent.fieldNameForChild(index) ?? '');\n }\n }\n return false;\n}\n\n/** Statements only countable by their position: constructs without a dedicated statement node. */\nfunction countsContextually(node: Parser.SyntaxNode): boolean {\n const parentType = node.parent?.type;\n // A Java instance initializer is a bare `block` in the class body; PMD counts it like the\n // `static_initializer` declaration it parallels.\n if (node.type === 'block' && parentType === 'class_body') {\n return true;\n }\n // TypeScript interface members (see interfaceMemberNodeTypes).\n if (interfaceMemberNodeTypes.has(node.type) && parentType === 'interface_body') {\n return true;\n }\n // A braceless Rust match-arm body (`1 => foo()`) has no expression_statement wrapper; count the\n // value expression so braced and unbraced arms measure alike.\n if (parentType === 'match_arm' && node.type !== 'block' && isFieldOfParent(node, 'value')) {\n return true;\n }\n // A TypeScript class-body method overload signature declares a member like its interface twin.\n if (node.type === 'method_signature' && parentType === 'class_body') {\n return true;\n }\n // An ambient `declare namespace M { ... }` is a bare `internal_module`; the non-ambient\n // `namespace N { ... }` is wrapped in an `expression_statement`, which already counts.\n if (node.type === 'internal_module' && parentType !== 'expression_statement') {\n return true;\n }\n // A Ruby endless method (`def f(x) = expr`) stores its single-statement body directly in the\n // `body` field instead of a positional `body_statement` container.\n if (\n (parentType === 'method' || parentType === 'singleton_method') &&\n node.type !== 'body_statement' &&\n isFieldOfParent(node, 'body')\n ) {\n return true;\n }\n // C++ `friend class X;` declares on its own; `friend void g() { ... }` merely wraps a counted\n // definition.\n if (node.type === 'friend_declaration') {\n return !node.namedChildren.some((child) => child.type === 'declaration' || child.type === 'function_definition');\n }\n // A Rust item-position macro invocation (`foo! {}` at module level) has no expression_statement\n // wrapper; the semicolon form does and already counts through it.\n if (node.type === 'macro_invocation' && (parentType === 'source_file' || parentType === 'declaration_list')) {\n return true;\n }\n // Go struct fields and interface members count like other languages' member declarations, but\n // only inside a named type declaration; inline anonymous types (`var x struct{ ... }`,\n // `func f(h interface{ ... })`) are part of one declaration.\n if (node.type === 'field_declaration' && parentType === 'field_declaration_list') {\n return isGoDeclaredTypeBody(node.parent?.parent, 'struct_type');\n }\n if (node.type === 'method_elem' || node.type === 'method_spec' || node.type === 'type_elem') {\n return isGoDeclaredTypeBody(node.parent, 'interface_type');\n }\n return false;\n}\n\nfunction isGoDeclaredTypeBody(typeNode: Parser.SyntaxNode | null | undefined, expectedType: string): boolean {\n if (typeNode?.type !== expectedType) {\n return false;\n }\n return typeNode.parent?.type === 'type_spec' || typeNode.parent?.type === 'type_alias';\n}\n\nfunction isFieldOfParent(node: Parser.SyntaxNode, fieldName: string): boolean {\n const parent = node.parent;\n if (!parent) {\n return false;\n }\n for (let index = 0; index < parent.childCount; index += 1) {\n if (parent.child(index)?.id === node.id) {\n return parent.fieldNameForChild(index) === fieldName;\n }\n }\n return false;\n}\n\nfunction findBareAlternatives(node: Parser.SyntaxNode): Parser.SyntaxNode[] {\n const alternatives: Parser.SyntaxNode[] = [];\n for (let index = 0; index < node.childCount; index += 1) {\n const child = node.child(index);\n if (child && node.fieldNameForChild(index) === 'alternative' && !elseClauseNodeTypes.has(child.type)) {\n alternatives.push(child);\n }\n }\n return alternatives;\n}\n"],"mappings":"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"}
|
package/dist/ncss.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type Parser from 'tree-sitter';
|
|
2
|
-
import type { LanguageDefinition } from './types.js';
|
|
3
|
-
export declare const commentNodeTypes: Set<string>;
|
|
4
|
-
/**
|
|
5
|
-
* Counts non-commenting source statements (NCSS) in the subtree, PMD-style: one per declaration,
|
|
6
|
-
* statement, and clause (`else`, `case`/`default` label, `catch`, `finally`, try-with-resources
|
|
7
|
-
* resource); `try` itself, braces, blank lines, and comments count 0.
|
|
8
|
-
*/
|
|
9
|
-
export interface NcssSets {
|
|
10
|
-
countable: Set<string>;
|
|
11
|
-
containers: Set<string>;
|
|
12
|
-
}
|
|
13
|
-
/** Drops the cached sets so a re-registered (possibly mutated) definition rebuilds them. */
|
|
14
|
-
export declare function invalidateNcssSetsCache(language: LanguageDefinition): void;
|
|
15
|
-
export declare function getNcssSets(language: LanguageDefinition): NcssSets;
|
|
16
|
-
export declare function countNcss(node: Parser.SyntaxNode, language: LanguageDefinition): number;
|
|
17
|
-
export declare function ncssContribution(node: Parser.SyntaxNode, countable: Set<string>, containers: Set<string>): number;
|
package/dist/ncss.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=new Set([`comment`,`line_comment`,`block_comment`]),t=new Set([`attribute_item`,`inner_attribute_item`,`empty_statement`,`heredoc_body`,`parenthesized_statements`]),n=new Set([`property_signature`,`method_signature`,`index_signature`,`construct_signature`,`call_signature`]),r=new Set([`else_clause`,`elif_clause`,`else`,`elsif`]),i=new Set([`if_statement`,`if_expression`]),a=new Set([`struct_specifier`,`enum_specifier`,`union_specifier`,`class_specifier`]),o=new WeakMap;function s(e){o.delete(e)}function c(e){let t=o.get(e);return t||(t={countable:new Set(e.ncssNodeTypes),containers:new Set(e.ncssContainerNodeTypes)},o.set(e,t)),t}function l(e,t){let{countable:n,containers:r}=c(t),i=0;function a(e){i+=u(e,n,r);for(let t of e.children)a(t)}return a(e),i}function u(n,r,a){if(!n.isNamed||e.has(n.type)||h(n))return 0;let o=0,s=f(n,a)&&!a.has(n.type)&&!t.has(n.type);return(d(n,r)||s||g(n))&&!p(n,r)&&(o+=1),i.has(n.type)&&(o+=y(n).length),o}function d(e,t){return t.has(e.type)?a.has(e.type)?e.childForFieldName(`body`)!==null:e.type!==`resource`||e.childForFieldName(`name`)!==null:!1}function f(e,t){let n=e.parent;for(;n&&n.type===`parenthesized_statements`;)n=n.parent;return n!==null&&t.has(n.type)}function p(e,t){if(e.type!==`export_statement`)return!1;let n=e.childForFieldName(`declaration`);return n!==null&&(t.has(n.type)||n.type===`internal_module`||n.type===`ambient_declaration`)}const m=new Set([`init`,`initializer`,`condition`,`update`,`increment`]);function h(e){let t=e.parent;if(!t)return!1;if(t.type===`init_statement`&&t.parent?.type===`for_range_loop`)return!0;if(t.type!==`for_statement`&&t.type!==`for_clause`&&t.type!==`for_range_loop`)return!1;for(let n=0;n<t.childCount;n+=1)if(t.child(n)?.id===e.id)return m.has(t.fieldNameForChild(n)??``);return!1}function g(e){let t=e.parent?.type;return e.type===`block`&&t===`class_body`||n.has(e.type)&&t===`interface_body`||t===`match_arm`&&e.type!==`block`&&v(e,`value`)||e.type===`method_signature`&&t===`class_body`||e.type===`internal_module`&&t!==`expression_statement`||(t===`method`||t===`singleton_method`)&&e.type!==`body_statement`&&v(e,`body`)?!0:e.type===`friend_declaration`?!e.namedChildren.some(e=>e.type===`declaration`||e.type===`function_definition`):e.type===`macro_invocation`&&(t===`source_file`||t===`declaration_list`)?!0:e.type===`field_declaration`&&t===`field_declaration_list`?_(e.parent?.parent,`struct_type`):e.type===`method_elem`||e.type===`method_spec`||e.type===`type_elem`?_(e.parent,`interface_type`):!1}function _(e,t){return e?.type===t?e.parent?.type===`type_spec`||e.parent?.type===`type_alias`:!1}function v(e,t){let n=e.parent;if(!n)return!1;for(let r=0;r<n.childCount;r+=1)if(n.child(r)?.id===e.id)return n.fieldNameForChild(r)===t;return!1}function y(e){let t=[];for(let n=0;n<e.childCount;n+=1){let i=e.child(n);i&&e.fieldNameForChild(n)===`alternative`&&!r.has(i.type)&&t.push(i)}return t}export{e as commentNodeTypes,l as countNcss,c as getNcssSets,s as invalidateNcssSetsCache,u as ncssContribution};
|
|
2
|
-
//# sourceMappingURL=ncss.js.map
|
package/dist/ncss.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ncss.js","names":[],"sources":["../src/ncss.ts"],"sourcesContent":["import type Parser from 'tree-sitter';\nimport type { LanguageDefinition } from './types.js';\n\nexport const commentNodeTypes = new Set(['comment', 'line_comment', 'block_comment']);\n\n// Nodes never counted positionally inside NCSS containers: metadata, empty statements, Ruby\n// heredoc bodies (tree-sitter emits them as siblings of the statement that opened the heredoc),\n// and Ruby statement parentheses (transparent wrappers whose children count instead).\nconst positionalExclusionTypes = new Set([\n 'attribute_item',\n 'inner_attribute_item',\n 'empty_statement',\n 'heredoc_body',\n 'parenthesized_statements',\n]);\n\n// TypeScript interface members count like Java interface members, but the same node types appear\n// inside object-type annotations (`let x: { a: number }`), which are part of one declaration, so\n// they only count directly under an interface body.\nconst interfaceMemberNodeTypes = new Set([\n 'property_signature',\n 'method_signature',\n 'index_signature',\n 'construct_signature',\n 'call_signature',\n]);\n\n// An if-branch wrapped in one of these already counts through ncssNodeTypes; a bare `alternative`\n// (Java/Go put the else branch directly in the field) needs the extra `else` count instead.\nconst elseClauseNodeTypes = new Set(['else_clause', 'elif_clause', 'else', 'elsif']);\n\nconst ifNodeTypes = new Set(['if_statement', 'if_expression']);\n\n// C/C++ type specifiers only declare something when they carry a body (`struct S { ... }`);\n// without one they are mere type references inside other declarations.\nconst bodylessNcssSpecifierTypes = new Set([\n 'struct_specifier',\n 'enum_specifier',\n 'union_specifier',\n 'class_specifier',\n]);\n\n/**\n * Counts non-commenting source statements (NCSS) in the subtree, PMD-style: one per declaration,\n * statement, and clause (`else`, `case`/`default` label, `catch`, `finally`, try-with-resources\n * resource); `try` itself, braces, blank lines, and comments count 0.\n */\nexport interface NcssSets {\n countable: Set<string>;\n containers: Set<string>;\n}\n\n// Cached per language: countNcss runs once per function plus once per file, so per-call Set\n// construction would add a measurable constant factor on large files.\nconst ncssSetsCache = new WeakMap<LanguageDefinition, NcssSets>();\n\n/** Drops the cached sets so a re-registered (possibly mutated) definition rebuilds them. */\nexport function invalidateNcssSetsCache(language: LanguageDefinition): void {\n ncssSetsCache.delete(language);\n}\n\nexport function getNcssSets(language: LanguageDefinition): NcssSets {\n let sets = ncssSetsCache.get(language);\n if (!sets) {\n sets = { countable: new Set(language.ncssNodeTypes), containers: new Set(language.ncssContainerNodeTypes) };\n ncssSetsCache.set(language, sets);\n }\n return sets;\n}\n\nexport function countNcss(node: Parser.SyntaxNode, language: LanguageDefinition): number {\n const { countable, containers } = getNcssSets(language);\n let count = 0;\n\n function visit(current: Parser.SyntaxNode): void {\n count += ncssContribution(current, countable, containers);\n for (const child of current.children) {\n visit(child);\n }\n }\n\n visit(node);\n return count;\n}\n\nexport function ncssContribution(node: Parser.SyntaxNode, countable: Set<string>, containers: Set<string>): number {\n if (!node.isNamed || commentNodeTypes.has(node.type) || isForHeaderNode(node)) {\n return 0;\n }\n\n let contribution = 0;\n const positional =\n isInContainerPosition(node, containers) && !containers.has(node.type) && !positionalExclusionTypes.has(node.type);\n if (\n (countsThroughNodeType(node, countable) || positional || countsContextually(node)) &&\n !isDeclarationWrapper(node, countable)\n ) {\n contribution += 1;\n }\n\n // A bare else branch (Java/Go `alternative:` without an else-clause wrapper) counts 1 like the\n // `else` keyword does in PMD; an `else if` chain charges the nested if separately on top.\n if (ifNodeTypes.has(node.type)) {\n contribution += findBareAlternatives(node).length;\n }\n\n return contribution;\n}\n\nfunction countsThroughNodeType(node: Parser.SyntaxNode, countable: Set<string>): boolean {\n if (!countable.has(node.type)) {\n return false;\n }\n if (bodylessNcssSpecifierTypes.has(node.type)) {\n return node.childForFieldName('body') !== null;\n }\n // A try-with-resources `resource` counts only when it declares a variable; `try (r)` reuses an\n // existing one and adds no statement (matching PMD).\n if (node.type === 'resource') {\n return node.childForFieldName('name') !== null;\n }\n return true;\n}\n\n/**\n * Direct container children count positionally; Ruby's `(foo; bar)` statement parentheses are\n * transparent (through arbitrary nesting), so their children count when the parentheses\n * themselves sit in a container.\n */\nfunction isInContainerPosition(node: Parser.SyntaxNode, containers: Set<string>): boolean {\n let ancestor = node.parent;\n while (ancestor && ancestor.type === 'parenthesized_statements') {\n ancestor = ancestor.parent;\n }\n return ancestor !== null && containers.has(ancestor.type);\n}\n\n/**\n * `export const x = 1` nests a countable declaration inside `export_statement`; only the inner\n * declaration counts, mirroring how PMD counts one statement per declared entity. The nested\n * declaration may also count contextually (`export namespace N {}` → internal_module) or sit one\n * level deeper (`export declare function f(): void;` → ambient_declaration > function_signature).\n */\nfunction isDeclarationWrapper(node: Parser.SyntaxNode, countable: Set<string>): boolean {\n if (node.type !== 'export_statement') {\n return false;\n }\n const declaration = node.childForFieldName('declaration');\n return (\n declaration !== null &&\n (countable.has(declaration.type) ||\n declaration.type === 'internal_module' ||\n declaration.type === 'ambient_declaration')\n );\n}\n\nconst forHeaderFieldNames = new Set(['init', 'initializer', 'condition', 'update', 'increment']);\n\n/**\n * Statement-shaped nodes in a `for` header (`for (int i = 0; i < n; i++)`) are part of the loop\n * statement, which already counts; PMD does not count them separately. JavaScript parses the\n * condition as an `expression_statement` and Go parses the update as an `inc_statement`, so all\n * header fields must be excluded, not just the initializer.\n */\nfunction isForHeaderNode(node: Parser.SyntaxNode): boolean {\n const parent = node.parent;\n if (!parent) {\n return false;\n }\n // C++20 range-for initializers nest one level deeper: for_range_loop > init_statement > node.\n if (parent.type === 'init_statement' && parent.parent?.type === 'for_range_loop') {\n return true;\n }\n if (parent.type !== 'for_statement' && parent.type !== 'for_clause' && parent.type !== 'for_range_loop') {\n return false;\n }\n for (let index = 0; index < parent.childCount; index += 1) {\n if (parent.child(index)?.id === node.id) {\n return forHeaderFieldNames.has(parent.fieldNameForChild(index) ?? '');\n }\n }\n return false;\n}\n\n/** Statements only countable by their position: constructs without a dedicated statement node. */\nfunction countsContextually(node: Parser.SyntaxNode): boolean {\n const parentType = node.parent?.type;\n // A Java instance initializer is a bare `block` in the class body; PMD counts it like the\n // `static_initializer` declaration it parallels.\n if (node.type === 'block' && parentType === 'class_body') {\n return true;\n }\n // TypeScript interface members (see interfaceMemberNodeTypes).\n if (interfaceMemberNodeTypes.has(node.type) && parentType === 'interface_body') {\n return true;\n }\n // A braceless Rust match-arm body (`1 => foo()`) has no expression_statement wrapper; count the\n // value expression so braced and unbraced arms measure alike.\n if (parentType === 'match_arm' && node.type !== 'block' && isFieldOfParent(node, 'value')) {\n return true;\n }\n // A TypeScript class-body method overload signature declares a member like its interface twin.\n if (node.type === 'method_signature' && parentType === 'class_body') {\n return true;\n }\n // An ambient `declare namespace M { ... }` is a bare `internal_module`; the non-ambient\n // `namespace N { ... }` is wrapped in an `expression_statement`, which already counts.\n if (node.type === 'internal_module' && parentType !== 'expression_statement') {\n return true;\n }\n // A Ruby endless method (`def f(x) = expr`) stores its single-statement body directly in the\n // `body` field instead of a positional `body_statement` container.\n if (\n (parentType === 'method' || parentType === 'singleton_method') &&\n node.type !== 'body_statement' &&\n isFieldOfParent(node, 'body')\n ) {\n return true;\n }\n // C++ `friend class X;` declares on its own; `friend void g() { ... }` merely wraps a counted\n // definition.\n if (node.type === 'friend_declaration') {\n return !node.namedChildren.some((child) => child.type === 'declaration' || child.type === 'function_definition');\n }\n // A Rust item-position macro invocation (`foo! {}` at module level) has no expression_statement\n // wrapper; the semicolon form does and already counts through it.\n if (node.type === 'macro_invocation' && (parentType === 'source_file' || parentType === 'declaration_list')) {\n return true;\n }\n // Go struct fields and interface members count like other languages' member declarations, but\n // only inside a named type declaration; inline anonymous types (`var x struct{ ... }`,\n // `func f(h interface{ ... })`) are part of one declaration.\n if (node.type === 'field_declaration' && parentType === 'field_declaration_list') {\n return isGoDeclaredTypeBody(node.parent?.parent, 'struct_type');\n }\n if (node.type === 'method_elem' || node.type === 'method_spec' || node.type === 'type_elem') {\n return isGoDeclaredTypeBody(node.parent, 'interface_type');\n }\n return false;\n}\n\nfunction isGoDeclaredTypeBody(typeNode: Parser.SyntaxNode | null | undefined, expectedType: string): boolean {\n if (typeNode?.type !== expectedType) {\n return false;\n }\n return typeNode.parent?.type === 'type_spec' || typeNode.parent?.type === 'type_alias';\n}\n\nfunction isFieldOfParent(node: Parser.SyntaxNode, fieldName: string): boolean {\n const parent = node.parent;\n if (!parent) {\n return false;\n }\n for (let index = 0; index < parent.childCount; index += 1) {\n if (parent.child(index)?.id === node.id) {\n return parent.fieldNameForChild(index) === fieldName;\n }\n }\n return false;\n}\n\nfunction findBareAlternatives(node: Parser.SyntaxNode): Parser.SyntaxNode[] {\n const alternatives: Parser.SyntaxNode[] = [];\n for (let index = 0; index < node.childCount; index += 1) {\n const child = node.child(index);\n if (child && node.fieldNameForChild(index) === 'alternative' && !elseClauseNodeTypes.has(child.type)) {\n alternatives.push(child);\n }\n }\n return alternatives;\n}\n"],"mappings":"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"}
|