@liendev/core 0.19.5
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 +336 -0
- package/dist/config/loader.d.ts +12 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +46 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/merge.d.ts +20 -0
- package/dist/config/merge.d.ts.map +1 -0
- package/dist/config/merge.js +71 -0
- package/dist/config/merge.js.map +1 -0
- package/dist/config/migration-manager.d.ts +46 -0
- package/dist/config/migration-manager.d.ts.map +1 -0
- package/dist/config/migration-manager.js +119 -0
- package/dist/config/migration-manager.js.map +1 -0
- package/dist/config/migration.d.ts +20 -0
- package/dist/config/migration.d.ts.map +1 -0
- package/dist/config/migration.js +155 -0
- package/dist/config/migration.js.map +1 -0
- package/dist/config/schema.d.ts +101 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +58 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/service.d.ts +122 -0
- package/dist/config/service.d.ts.map +1 -0
- package/dist/config/service.js +477 -0
- package/dist/config/service.js.map +1 -0
- package/dist/constants.d.ts +20 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +43 -0
- package/dist/constants.js.map +1 -0
- package/dist/embeddings/cache.d.ts +45 -0
- package/dist/embeddings/cache.d.ts.map +1 -0
- package/dist/embeddings/cache.js +109 -0
- package/dist/embeddings/cache.js.map +1 -0
- package/dist/embeddings/local.d.ts +10 -0
- package/dist/embeddings/local.d.ts.map +1 -0
- package/dist/embeddings/local.js +63 -0
- package/dist/embeddings/local.js.map +1 -0
- package/dist/embeddings/types.d.ts +9 -0
- package/dist/embeddings/types.d.ts.map +1 -0
- package/dist/embeddings/types.js +5 -0
- package/dist/embeddings/types.js.map +1 -0
- package/dist/errors/codes.d.ts +18 -0
- package/dist/errors/codes.d.ts.map +1 -0
- package/dist/errors/codes.js +25 -0
- package/dist/errors/codes.js.map +1 -0
- package/dist/errors/index.d.ts +85 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +134 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/frameworks/detector-service.d.ts +59 -0
- package/dist/frameworks/detector-service.d.ts.map +1 -0
- package/dist/frameworks/detector-service.js +219 -0
- package/dist/frameworks/detector-service.js.map +1 -0
- package/dist/frameworks/laravel/config.d.ts +6 -0
- package/dist/frameworks/laravel/config.d.ts.map +1 -0
- package/dist/frameworks/laravel/config.js +68 -0
- package/dist/frameworks/laravel/config.js.map +1 -0
- package/dist/frameworks/laravel/detector.d.ts +6 -0
- package/dist/frameworks/laravel/detector.d.ts.map +1 -0
- package/dist/frameworks/laravel/detector.js +96 -0
- package/dist/frameworks/laravel/detector.js.map +1 -0
- package/dist/frameworks/nodejs/config.d.ts +6 -0
- package/dist/frameworks/nodejs/config.d.ts.map +1 -0
- package/dist/frameworks/nodejs/config.js +57 -0
- package/dist/frameworks/nodejs/config.js.map +1 -0
- package/dist/frameworks/nodejs/detector.d.ts +6 -0
- package/dist/frameworks/nodejs/detector.d.ts.map +1 -0
- package/dist/frameworks/nodejs/detector.js +77 -0
- package/dist/frameworks/nodejs/detector.js.map +1 -0
- package/dist/frameworks/php/config.d.ts +6 -0
- package/dist/frameworks/php/config.d.ts.map +1 -0
- package/dist/frameworks/php/config.js +53 -0
- package/dist/frameworks/php/config.js.map +1 -0
- package/dist/frameworks/php/detector.d.ts +7 -0
- package/dist/frameworks/php/detector.d.ts.map +1 -0
- package/dist/frameworks/php/detector.js +101 -0
- package/dist/frameworks/php/detector.js.map +1 -0
- package/dist/frameworks/registry.d.ts +20 -0
- package/dist/frameworks/registry.d.ts.map +1 -0
- package/dist/frameworks/registry.js +38 -0
- package/dist/frameworks/registry.js.map +1 -0
- package/dist/frameworks/shopify/config.d.ts +6 -0
- package/dist/frameworks/shopify/config.d.ts.map +1 -0
- package/dist/frameworks/shopify/config.js +50 -0
- package/dist/frameworks/shopify/config.js.map +1 -0
- package/dist/frameworks/shopify/detector.d.ts +6 -0
- package/dist/frameworks/shopify/detector.d.ts.map +1 -0
- package/dist/frameworks/shopify/detector.js +103 -0
- package/dist/frameworks/shopify/detector.js.map +1 -0
- package/dist/frameworks/types.d.ts +51 -0
- package/dist/frameworks/types.d.ts.map +1 -0
- package/dist/frameworks/types.js +21 -0
- package/dist/frameworks/types.js.map +1 -0
- package/dist/git/tracker.d.ts +56 -0
- package/dist/git/tracker.d.ts.map +1 -0
- package/dist/git/tracker.js +189 -0
- package/dist/git/tracker.js.map +1 -0
- package/dist/git/utils.d.ts +60 -0
- package/dist/git/utils.d.ts.map +1 -0
- package/dist/git/utils.js +152 -0
- package/dist/git/utils.js.map +1 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +95 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer/ast/chunker.d.ts +28 -0
- package/dist/indexer/ast/chunker.d.ts.map +1 -0
- package/dist/indexer/ast/chunker.js +268 -0
- package/dist/indexer/ast/chunker.js.map +1 -0
- package/dist/indexer/ast/complexity/cognitive.d.ts +16 -0
- package/dist/indexer/ast/complexity/cognitive.d.ts.map +1 -0
- package/dist/indexer/ast/complexity/cognitive.js +106 -0
- package/dist/indexer/ast/complexity/cognitive.js.map +1 -0
- package/dist/indexer/ast/complexity/cyclomatic.d.ts +12 -0
- package/dist/indexer/ast/complexity/cyclomatic.d.ts.map +1 -0
- package/dist/indexer/ast/complexity/cyclomatic.js +61 -0
- package/dist/indexer/ast/complexity/cyclomatic.js.map +1 -0
- package/dist/indexer/ast/complexity/halstead.d.ts +55 -0
- package/dist/indexer/ast/complexity/halstead.d.ts.map +1 -0
- package/dist/indexer/ast/complexity/halstead.js +290 -0
- package/dist/indexer/ast/complexity/halstead.js.map +1 -0
- package/dist/indexer/ast/complexity/index.d.ts +13 -0
- package/dist/indexer/ast/complexity/index.d.ts.map +1 -0
- package/dist/indexer/ast/complexity/index.js +12 -0
- package/dist/indexer/ast/complexity/index.js.map +1 -0
- package/dist/indexer/ast/parser.d.ts +27 -0
- package/dist/indexer/ast/parser.d.ts.map +1 -0
- package/dist/indexer/ast/parser.js +103 -0
- package/dist/indexer/ast/parser.js.map +1 -0
- package/dist/indexer/ast/symbols.d.ts +17 -0
- package/dist/indexer/ast/symbols.d.ts.map +1 -0
- package/dist/indexer/ast/symbols.js +265 -0
- package/dist/indexer/ast/symbols.js.map +1 -0
- package/dist/indexer/ast/traversers/index.d.ts +19 -0
- package/dist/indexer/ast/traversers/index.d.ts.map +1 -0
- package/dist/indexer/ast/traversers/index.js +42 -0
- package/dist/indexer/ast/traversers/index.js.map +1 -0
- package/dist/indexer/ast/traversers/php.d.ts +21 -0
- package/dist/indexer/ast/traversers/php.d.ts.map +1 -0
- package/dist/indexer/ast/traversers/php.js +67 -0
- package/dist/indexer/ast/traversers/php.js.map +1 -0
- package/dist/indexer/ast/traversers/python.d.ts +28 -0
- package/dist/indexer/ast/traversers/python.d.ts.map +1 -0
- package/dist/indexer/ast/traversers/python.js +67 -0
- package/dist/indexer/ast/traversers/python.js.map +1 -0
- package/dist/indexer/ast/traversers/types.d.ts +98 -0
- package/dist/indexer/ast/traversers/types.d.ts.map +1 -0
- package/dist/indexer/ast/traversers/types.js +2 -0
- package/dist/indexer/ast/traversers/types.js.map +1 -0
- package/dist/indexer/ast/traversers/typescript.d.ts +29 -0
- package/dist/indexer/ast/traversers/typescript.d.ts.map +1 -0
- package/dist/indexer/ast/traversers/typescript.js +88 -0
- package/dist/indexer/ast/traversers/typescript.js.map +1 -0
- package/dist/indexer/ast/types.d.ts +59 -0
- package/dist/indexer/ast/types.d.ts.map +1 -0
- package/dist/indexer/ast/types.js +2 -0
- package/dist/indexer/ast/types.js.map +1 -0
- package/dist/indexer/change-detector.d.ts +17 -0
- package/dist/indexer/change-detector.d.ts.map +1 -0
- package/dist/indexer/change-detector.js +207 -0
- package/dist/indexer/change-detector.js.map +1 -0
- package/dist/indexer/chunk-batch-processor.d.ts +103 -0
- package/dist/indexer/chunk-batch-processor.d.ts.map +1 -0
- package/dist/indexer/chunk-batch-processor.js +179 -0
- package/dist/indexer/chunk-batch-processor.js.map +1 -0
- package/dist/indexer/chunker.d.ts +10 -0
- package/dist/indexer/chunker.d.ts.map +1 -0
- package/dist/indexer/chunker.js +96 -0
- package/dist/indexer/chunker.js.map +1 -0
- package/dist/indexer/dependency-analyzer.d.ts +60 -0
- package/dist/indexer/dependency-analyzer.d.ts.map +1 -0
- package/dist/indexer/dependency-analyzer.js +261 -0
- package/dist/indexer/dependency-analyzer.js.map +1 -0
- package/dist/indexer/incremental.d.ts +47 -0
- package/dist/indexer/incremental.d.ts.map +1 -0
- package/dist/indexer/incremental.js +284 -0
- package/dist/indexer/incremental.js.map +1 -0
- package/dist/indexer/index.d.ts +80 -0
- package/dist/indexer/index.d.ts.map +1 -0
- package/dist/indexer/index.js +364 -0
- package/dist/indexer/index.js.map +1 -0
- package/dist/indexer/json-template-chunker.d.ts +9 -0
- package/dist/indexer/json-template-chunker.d.ts.map +1 -0
- package/dist/indexer/json-template-chunker.js +83 -0
- package/dist/indexer/json-template-chunker.js.map +1 -0
- package/dist/indexer/liquid-chunker.d.ts +13 -0
- package/dist/indexer/liquid-chunker.d.ts.map +1 -0
- package/dist/indexer/liquid-chunker.js +272 -0
- package/dist/indexer/liquid-chunker.js.map +1 -0
- package/dist/indexer/manifest.d.ts +122 -0
- package/dist/indexer/manifest.d.ts.map +1 -0
- package/dist/indexer/manifest.js +262 -0
- package/dist/indexer/manifest.js.map +1 -0
- package/dist/indexer/progress-tracker.d.ts +35 -0
- package/dist/indexer/progress-tracker.d.ts.map +1 -0
- package/dist/indexer/progress-tracker.js +33 -0
- package/dist/indexer/progress-tracker.js.map +1 -0
- package/dist/indexer/scanner.d.ts +16 -0
- package/dist/indexer/scanner.d.ts.map +1 -0
- package/dist/indexer/scanner.js +159 -0
- package/dist/indexer/scanner.js.map +1 -0
- package/dist/indexer/symbol-extractor.d.ts +18 -0
- package/dist/indexer/symbol-extractor.d.ts.map +1 -0
- package/dist/indexer/symbol-extractor.js +351 -0
- package/dist/indexer/symbol-extractor.js.map +1 -0
- package/dist/indexer/types.d.ts +34 -0
- package/dist/indexer/types.d.ts.map +1 -0
- package/dist/indexer/types.js +2 -0
- package/dist/indexer/types.js.map +1 -0
- package/dist/insights/complexity-analyzer.d.ts +82 -0
- package/dist/insights/complexity-analyzer.d.ts.map +1 -0
- package/dist/insights/complexity-analyzer.js +356 -0
- package/dist/insights/complexity-analyzer.js.map +1 -0
- package/dist/insights/formatters/index.d.ts +11 -0
- package/dist/insights/formatters/index.d.ts.map +1 -0
- package/dist/insights/formatters/index.js +20 -0
- package/dist/insights/formatters/index.js.map +1 -0
- package/dist/insights/formatters/json.d.ts +7 -0
- package/dist/insights/formatters/json.d.ts.map +1 -0
- package/dist/insights/formatters/json.js +14 -0
- package/dist/insights/formatters/json.js.map +1 -0
- package/dist/insights/formatters/sarif.d.ts +6 -0
- package/dist/insights/formatters/sarif.d.ts.map +1 -0
- package/dist/insights/formatters/sarif.js +113 -0
- package/dist/insights/formatters/sarif.js.map +1 -0
- package/dist/insights/formatters/text.d.ts +6 -0
- package/dist/insights/formatters/text.d.ts.map +1 -0
- package/dist/insights/formatters/text.js +154 -0
- package/dist/insights/formatters/text.js.map +1 -0
- package/dist/insights/types.d.ts +73 -0
- package/dist/insights/types.d.ts.map +1 -0
- package/dist/insights/types.js +9 -0
- package/dist/insights/types.js.map +1 -0
- package/dist/types/index.d.ts +14 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/path-matching.d.ts +69 -0
- package/dist/utils/path-matching.d.ts.map +1 -0
- package/dist/utils/path-matching.js +123 -0
- package/dist/utils/path-matching.js.map +1 -0
- package/dist/utils/result.d.ts +65 -0
- package/dist/utils/result.d.ts.map +1 -0
- package/dist/utils/result.js +67 -0
- package/dist/utils/result.js.map +1 -0
- package/dist/utils/version.d.ts +22 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +28 -0
- package/dist/utils/version.js.map +1 -0
- package/dist/vectordb/batch-insert.d.ts +14 -0
- package/dist/vectordb/batch-insert.d.ts.map +1 -0
- package/dist/vectordb/batch-insert.js +185 -0
- package/dist/vectordb/batch-insert.js.map +1 -0
- package/dist/vectordb/boosting/composer.d.ts +51 -0
- package/dist/vectordb/boosting/composer.d.ts.map +1 -0
- package/dist/vectordb/boosting/composer.js +65 -0
- package/dist/vectordb/boosting/composer.js.map +1 -0
- package/dist/vectordb/boosting/index.d.ts +22 -0
- package/dist/vectordb/boosting/index.d.ts.map +1 -0
- package/dist/vectordb/boosting/index.js +22 -0
- package/dist/vectordb/boosting/index.js.map +1 -0
- package/dist/vectordb/boosting/strategies.d.ts +40 -0
- package/dist/vectordb/boosting/strategies.d.ts.map +1 -0
- package/dist/vectordb/boosting/strategies.js +174 -0
- package/dist/vectordb/boosting/strategies.js.map +1 -0
- package/dist/vectordb/boosting/types.d.ts +20 -0
- package/dist/vectordb/boosting/types.d.ts.map +1 -0
- package/dist/vectordb/boosting/types.js +2 -0
- package/dist/vectordb/boosting/types.js.map +1 -0
- package/dist/vectordb/intent-classifier.d.ts +99 -0
- package/dist/vectordb/intent-classifier.d.ts.map +1 -0
- package/dist/vectordb/intent-classifier.js +193 -0
- package/dist/vectordb/intent-classifier.js.map +1 -0
- package/dist/vectordb/lancedb.d.ts +45 -0
- package/dist/vectordb/lancedb.d.ts.map +1 -0
- package/dist/vectordb/lancedb.js +203 -0
- package/dist/vectordb/lancedb.js.map +1 -0
- package/dist/vectordb/maintenance.d.ts +18 -0
- package/dist/vectordb/maintenance.d.ts.map +1 -0
- package/dist/vectordb/maintenance.js +87 -0
- package/dist/vectordb/maintenance.js.map +1 -0
- package/dist/vectordb/query.d.ts +34 -0
- package/dist/vectordb/query.d.ts.map +1 -0
- package/dist/vectordb/query.js +303 -0
- package/dist/vectordb/query.js.map +1 -0
- package/dist/vectordb/relevance.d.ts +15 -0
- package/dist/vectordb/relevance.d.ts.map +1 -0
- package/dist/vectordb/relevance.js +19 -0
- package/dist/vectordb/relevance.js.map +1 -0
- package/dist/vectordb/types.d.ts +29 -0
- package/dist/vectordb/types.d.ts.map +1 -0
- package/dist/vectordb/types.js +2 -0
- package/dist/vectordb/types.js.map +1 -0
- package/dist/vectordb/version.d.ts +16 -0
- package/dist/vectordb/version.d.ts.map +1 -0
- package/dist/vectordb/version.js +40 -0
- package/dist/vectordb/version.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { parseAST, detectLanguage, isASTSupported } from './parser.js';
|
|
2
|
+
import { extractSymbolInfo, extractImports } from './symbols.js';
|
|
3
|
+
import { calculateCognitiveComplexity, calculateHalstead } from './complexity/index.js';
|
|
4
|
+
import { getTraverser } from './traversers/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Chunk a file using AST-based semantic boundaries
|
|
7
|
+
*
|
|
8
|
+
* Uses Tree-sitter to parse code into an AST and extract semantic chunks
|
|
9
|
+
* (functions, classes, methods) that respect code structure.
|
|
10
|
+
*
|
|
11
|
+
* **Known Limitations:**
|
|
12
|
+
* - Tree-sitter may fail with "Invalid argument" error on very large files (1000+ lines)
|
|
13
|
+
* - When this occurs, Lien automatically falls back to line-based chunking
|
|
14
|
+
* - Configure fallback behavior via `chunking.astFallback` ('line-based' or 'error')
|
|
15
|
+
*
|
|
16
|
+
* @param filepath - Path to the file
|
|
17
|
+
* @param content - File content
|
|
18
|
+
* @param options - Chunking options
|
|
19
|
+
* @returns Array of AST-aware chunks
|
|
20
|
+
* @throws Error if AST parsing fails and astFallback is 'error'
|
|
21
|
+
*/
|
|
22
|
+
export function chunkByAST(filepath, content, options = {}) {
|
|
23
|
+
const { minChunkSize = 5 } = options;
|
|
24
|
+
// Check if AST is supported for this file
|
|
25
|
+
const language = detectLanguage(filepath);
|
|
26
|
+
if (!language) {
|
|
27
|
+
throw new Error(`Unsupported language for file: ${filepath}`);
|
|
28
|
+
}
|
|
29
|
+
// Parse the file
|
|
30
|
+
const parseResult = parseAST(content, language);
|
|
31
|
+
// If parsing failed, throw error (caller should fallback to line-based)
|
|
32
|
+
if (!parseResult.tree) {
|
|
33
|
+
throw new Error(`Failed to parse ${filepath}: ${parseResult.error}`);
|
|
34
|
+
}
|
|
35
|
+
const chunks = [];
|
|
36
|
+
const lines = content.split('\n');
|
|
37
|
+
const rootNode = parseResult.tree.rootNode;
|
|
38
|
+
// Get language-specific traverser
|
|
39
|
+
const traverser = getTraverser(language);
|
|
40
|
+
// Extract file-level imports once
|
|
41
|
+
const fileImports = extractImports(rootNode);
|
|
42
|
+
// Find all top-level function and class declarations
|
|
43
|
+
const topLevelNodes = findTopLevelNodes(rootNode, traverser);
|
|
44
|
+
for (const node of topLevelNodes) {
|
|
45
|
+
// For variable declarations, try to find the function inside
|
|
46
|
+
let actualNode = node;
|
|
47
|
+
if (traverser.isDeclarationWithFunction(node)) {
|
|
48
|
+
const declInfo = traverser.findFunctionInDeclaration(node);
|
|
49
|
+
if (declInfo.functionNode) {
|
|
50
|
+
actualNode = declInfo.functionNode;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// For methods, find the parent container name (e.g., class name)
|
|
54
|
+
const parentClassName = traverser.findParentContainerName(actualNode);
|
|
55
|
+
const symbolInfo = extractSymbolInfo(actualNode, content, parentClassName, language);
|
|
56
|
+
// Extract the code for this node (use original node for full declaration)
|
|
57
|
+
const nodeContent = getNodeContent(node, lines);
|
|
58
|
+
// Create a chunk for this semantic unit
|
|
59
|
+
// Note: Large functions are kept as single chunks (may exceed maxChunkSize)
|
|
60
|
+
// This preserves semantic boundaries - better than splitting mid-function
|
|
61
|
+
chunks.push(createChunk(filepath, node, nodeContent, symbolInfo, fileImports, language));
|
|
62
|
+
}
|
|
63
|
+
// Handle remaining code (imports, exports, top-level statements)
|
|
64
|
+
const coveredRanges = topLevelNodes.map(n => ({
|
|
65
|
+
start: n.startPosition.row,
|
|
66
|
+
end: n.endPosition.row,
|
|
67
|
+
}));
|
|
68
|
+
const uncoveredChunks = extractUncoveredCode(lines, coveredRanges, filepath, minChunkSize, fileImports, language);
|
|
69
|
+
chunks.push(...uncoveredChunks);
|
|
70
|
+
// Sort chunks by line number
|
|
71
|
+
chunks.sort((a, b) => a.metadata.startLine - b.metadata.startLine);
|
|
72
|
+
return chunks;
|
|
73
|
+
}
|
|
74
|
+
/** Check if node is a function-containing declaration at top level */
|
|
75
|
+
function isFunctionDeclaration(node, depth, traverser) {
|
|
76
|
+
if (depth !== 0 || !traverser.isDeclarationWithFunction(node))
|
|
77
|
+
return false;
|
|
78
|
+
return traverser.findFunctionInDeclaration(node).hasFunction;
|
|
79
|
+
}
|
|
80
|
+
/** Check if node is a target type at valid depth */
|
|
81
|
+
function isTargetNode(node, depth, traverser) {
|
|
82
|
+
return depth <= 1 && traverser.targetNodeTypes.includes(node.type);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Find all top-level nodes that should become chunks
|
|
86
|
+
*
|
|
87
|
+
* Uses a language-specific traverser to handle different AST structures.
|
|
88
|
+
* This function is now language-agnostic - all language-specific logic
|
|
89
|
+
* is delegated to the traverser.
|
|
90
|
+
*
|
|
91
|
+
* @param rootNode - Root AST node
|
|
92
|
+
* @param traverser - Language-specific traverser
|
|
93
|
+
* @returns Array of nodes to extract as chunks
|
|
94
|
+
*/
|
|
95
|
+
function findTopLevelNodes(rootNode, traverser) {
|
|
96
|
+
const nodes = [];
|
|
97
|
+
function traverse(node, depth) {
|
|
98
|
+
// Capture function declarations and target nodes
|
|
99
|
+
if (isFunctionDeclaration(node, depth, traverser) || isTargetNode(node, depth, traverser)) {
|
|
100
|
+
nodes.push(node);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
// Handle containers - traverse body at increased depth
|
|
104
|
+
if (traverser.shouldExtractChildren(node)) {
|
|
105
|
+
const body = traverser.getContainerBody(node);
|
|
106
|
+
if (body)
|
|
107
|
+
traverse(body, depth + 1);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
// Traverse children of traversable nodes
|
|
111
|
+
if (!traverser.shouldTraverseChildren(node))
|
|
112
|
+
return;
|
|
113
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
114
|
+
const child = node.namedChild(i);
|
|
115
|
+
if (child)
|
|
116
|
+
traverse(child, depth);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
traverse(rootNode, 0);
|
|
120
|
+
return nodes;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Extract content for a specific AST node
|
|
124
|
+
*/
|
|
125
|
+
function getNodeContent(node, lines) {
|
|
126
|
+
const startLine = node.startPosition.row;
|
|
127
|
+
const endLine = node.endPosition.row;
|
|
128
|
+
return lines.slice(startLine, endLine + 1).join('\n');
|
|
129
|
+
}
|
|
130
|
+
/** Maps symbol types to legacy symbol array keys */
|
|
131
|
+
const SYMBOL_TYPE_TO_ARRAY = {
|
|
132
|
+
function: 'functions',
|
|
133
|
+
method: 'functions',
|
|
134
|
+
class: 'classes',
|
|
135
|
+
interface: 'interfaces',
|
|
136
|
+
};
|
|
137
|
+
/** Symbol types that have meaningful complexity metrics */
|
|
138
|
+
const COMPLEXITY_SYMBOL_TYPES = new Set(['function', 'method']);
|
|
139
|
+
/**
|
|
140
|
+
* Build legacy symbols object for backward compatibility
|
|
141
|
+
*/
|
|
142
|
+
function buildLegacySymbols(symbolInfo) {
|
|
143
|
+
const symbols = { functions: [], classes: [], interfaces: [] };
|
|
144
|
+
if (symbolInfo?.name && symbolInfo.type) {
|
|
145
|
+
const arrayKey = SYMBOL_TYPE_TO_ARRAY[symbolInfo.type];
|
|
146
|
+
if (arrayKey)
|
|
147
|
+
symbols[arrayKey].push(symbolInfo.name);
|
|
148
|
+
}
|
|
149
|
+
return symbols;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Determine chunk type from symbol info
|
|
153
|
+
*/
|
|
154
|
+
function getChunkType(symbolInfo) {
|
|
155
|
+
if (!symbolInfo)
|
|
156
|
+
return 'block';
|
|
157
|
+
return symbolInfo.type === 'class' ? 'class' : 'function';
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Create a chunk from an AST node
|
|
161
|
+
*/
|
|
162
|
+
function createChunk(filepath, node, content, symbolInfo, imports, language) {
|
|
163
|
+
const symbols = buildLegacySymbols(symbolInfo);
|
|
164
|
+
const shouldCalcComplexity = symbolInfo?.type && COMPLEXITY_SYMBOL_TYPES.has(symbolInfo.type);
|
|
165
|
+
// Calculate complexity metrics only for functions and methods
|
|
166
|
+
const cognitiveComplexity = shouldCalcComplexity
|
|
167
|
+
? calculateCognitiveComplexity(node)
|
|
168
|
+
: undefined;
|
|
169
|
+
// Calculate Halstead metrics only for functions and methods
|
|
170
|
+
const halstead = shouldCalcComplexity
|
|
171
|
+
? calculateHalstead(node, language)
|
|
172
|
+
: undefined;
|
|
173
|
+
return {
|
|
174
|
+
content,
|
|
175
|
+
metadata: {
|
|
176
|
+
file: filepath,
|
|
177
|
+
startLine: node.startPosition.row + 1,
|
|
178
|
+
endLine: node.endPosition.row + 1,
|
|
179
|
+
type: getChunkType(symbolInfo),
|
|
180
|
+
language,
|
|
181
|
+
symbols,
|
|
182
|
+
symbolName: symbolInfo?.name,
|
|
183
|
+
symbolType: symbolInfo?.type,
|
|
184
|
+
parentClass: symbolInfo?.parentClass,
|
|
185
|
+
complexity: symbolInfo?.complexity,
|
|
186
|
+
cognitiveComplexity,
|
|
187
|
+
parameters: symbolInfo?.parameters,
|
|
188
|
+
signature: symbolInfo?.signature,
|
|
189
|
+
imports,
|
|
190
|
+
// Halstead metrics
|
|
191
|
+
halsteadVolume: halstead?.volume,
|
|
192
|
+
halsteadDifficulty: halstead?.difficulty,
|
|
193
|
+
halsteadEffort: halstead?.effort,
|
|
194
|
+
halsteadBugs: halstead?.bugs,
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Find gaps between covered ranges (uncovered code)
|
|
200
|
+
*/
|
|
201
|
+
function findUncoveredRanges(coveredRanges, totalLines) {
|
|
202
|
+
const uncoveredRanges = [];
|
|
203
|
+
let currentStart = 0;
|
|
204
|
+
// Sort covered ranges
|
|
205
|
+
const sortedRanges = [...coveredRanges].sort((a, b) => a.start - b.start);
|
|
206
|
+
for (const range of sortedRanges) {
|
|
207
|
+
if (currentStart < range.start) {
|
|
208
|
+
// There's a gap before this range
|
|
209
|
+
uncoveredRanges.push({
|
|
210
|
+
start: currentStart,
|
|
211
|
+
end: range.start - 1,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
currentStart = range.end + 1;
|
|
215
|
+
}
|
|
216
|
+
// Handle remaining code after last covered range
|
|
217
|
+
if (currentStart < totalLines) {
|
|
218
|
+
uncoveredRanges.push({
|
|
219
|
+
start: currentStart,
|
|
220
|
+
end: totalLines - 1,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
return uncoveredRanges;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Create a chunk from a line range
|
|
227
|
+
*/
|
|
228
|
+
function createChunkFromRange(range, lines, filepath, language, imports) {
|
|
229
|
+
const uncoveredLines = lines.slice(range.start, range.end + 1);
|
|
230
|
+
const content = uncoveredLines.join('\n').trim();
|
|
231
|
+
return {
|
|
232
|
+
content,
|
|
233
|
+
metadata: {
|
|
234
|
+
file: filepath,
|
|
235
|
+
startLine: range.start + 1,
|
|
236
|
+
endLine: range.end + 1,
|
|
237
|
+
type: 'block',
|
|
238
|
+
language,
|
|
239
|
+
// Empty symbols for uncovered code (imports, exports, etc.)
|
|
240
|
+
symbols: { functions: [], classes: [], interfaces: [] },
|
|
241
|
+
imports,
|
|
242
|
+
},
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Validate that a chunk meets the minimum size requirements
|
|
247
|
+
*/
|
|
248
|
+
function isValidChunk(chunk, minChunkSize) {
|
|
249
|
+
const lineCount = chunk.metadata.endLine - chunk.metadata.startLine + 1;
|
|
250
|
+
return chunk.content.length > 0 && lineCount >= minChunkSize;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Extract code that wasn't covered by function/class chunks
|
|
254
|
+
* (imports, exports, top-level statements)
|
|
255
|
+
*/
|
|
256
|
+
function extractUncoveredCode(lines, coveredRanges, filepath, minChunkSize, imports, language) {
|
|
257
|
+
const uncoveredRanges = findUncoveredRanges(coveredRanges, lines.length);
|
|
258
|
+
return uncoveredRanges
|
|
259
|
+
.map(range => createChunkFromRange(range, lines, filepath, language, imports))
|
|
260
|
+
.filter(chunk => isValidChunk(chunk, minChunkSize));
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Check if AST chunking should be used for a file
|
|
264
|
+
*/
|
|
265
|
+
export function shouldUseAST(filepath) {
|
|
266
|
+
return isASTSupported(filepath);
|
|
267
|
+
}
|
|
268
|
+
//# sourceMappingURL=chunker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunker.js","sourceRoot":"","sources":["../../../src/indexer/ast/chunker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type Parser from 'tree-sitter';
|
|
2
|
+
/**
|
|
3
|
+
* Calculate cognitive complexity of a function
|
|
4
|
+
*
|
|
5
|
+
* Based on SonarSource's Cognitive Complexity specification:
|
|
6
|
+
* - +1 for each break from linear flow (if, for, while, catch, etc.)
|
|
7
|
+
* - +1 for each nesting level when inside a control structure
|
|
8
|
+
* - +1 for each logical operator sequence break (a && b || c)
|
|
9
|
+
*
|
|
10
|
+
* @see https://www.sonarsource.com/docs/CognitiveComplexity.pdf
|
|
11
|
+
*
|
|
12
|
+
* @param node - AST node to analyze (typically a function/method)
|
|
13
|
+
* @returns Cognitive complexity score (minimum 0)
|
|
14
|
+
*/
|
|
15
|
+
export declare function calculateCognitiveComplexity(node: Parser.SyntaxNode): number;
|
|
16
|
+
//# sourceMappingURL=cognitive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cognitive.d.ts","sourceRoot":"","sources":["../../../../src/indexer/ast/complexity/cognitive.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AA+FtC;;;;;;;;;;;;GAYG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CA+B5E"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// Node types that increase complexity AND increment nesting for children
|
|
2
|
+
const NESTING_TYPES = new Set([
|
|
3
|
+
'if_statement', 'for_statement', 'while_statement', 'switch_statement',
|
|
4
|
+
'catch_clause', 'except_clause', 'do_statement', 'for_in_statement',
|
|
5
|
+
'for_of_statement', 'foreach_statement', 'match_statement',
|
|
6
|
+
]);
|
|
7
|
+
// Types that add complexity but DON'T nest (hybrid increments)
|
|
8
|
+
const NON_NESTING_TYPES = new Set([
|
|
9
|
+
'else_clause', 'elif_clause', 'ternary_expression', 'conditional_expression',
|
|
10
|
+
]);
|
|
11
|
+
// Lambda types that add complexity when nested
|
|
12
|
+
const LAMBDA_TYPES = new Set(['arrow_function', 'function_expression', 'lambda']);
|
|
13
|
+
/**
|
|
14
|
+
* Check if node is a logical operator and return normalized form
|
|
15
|
+
*/
|
|
16
|
+
function getLogicalOperator(node) {
|
|
17
|
+
if (node.type !== 'binary_expression' && node.type !== 'boolean_operator') {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const operator = node.childForFieldName('operator');
|
|
21
|
+
const opText = operator?.text;
|
|
22
|
+
if (opText === '&&' || opText === 'and')
|
|
23
|
+
return '&&';
|
|
24
|
+
if (opText === '||' || opText === 'or')
|
|
25
|
+
return '||';
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Determine nesting level for a child node based on SonarSource spec.
|
|
30
|
+
*/
|
|
31
|
+
function getChildNestingLevel(parent, child, currentLevel) {
|
|
32
|
+
const isCondition = parent.childForFieldName('condition') === child;
|
|
33
|
+
const isElseClause = NON_NESTING_TYPES.has(child.type);
|
|
34
|
+
return (!isCondition && !isElseClause) ? currentLevel + 1 : currentLevel;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get complexity increment for nested lambda (only adds if already nested)
|
|
38
|
+
*/
|
|
39
|
+
function getNestedLambdaIncrement(nodeType, nestingLevel) {
|
|
40
|
+
return (LAMBDA_TYPES.has(nodeType) && nestingLevel > 0) ? 1 : 0;
|
|
41
|
+
}
|
|
42
|
+
/** Traverse logical operator children, passing the operator type */
|
|
43
|
+
function traverseLogicalChildren(n, level, op, ctx) {
|
|
44
|
+
const operator = n.childForFieldName('operator');
|
|
45
|
+
for (let i = 0; i < n.namedChildCount; i++) {
|
|
46
|
+
const child = n.namedChild(i);
|
|
47
|
+
if (child && child !== operator)
|
|
48
|
+
ctx.traverse(child, level, op);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** Traverse nesting type children with proper nesting level adjustment */
|
|
52
|
+
function traverseNestingChildren(n, level, ctx) {
|
|
53
|
+
for (let i = 0; i < n.namedChildCount; i++) {
|
|
54
|
+
const child = n.namedChild(i);
|
|
55
|
+
if (child)
|
|
56
|
+
ctx.traverse(child, getChildNestingLevel(n, child, level), null);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Traverse all children at specified level */
|
|
60
|
+
function traverseAllChildren(n, level, ctx) {
|
|
61
|
+
for (let i = 0; i < n.namedChildCount; i++) {
|
|
62
|
+
const child = n.namedChild(i);
|
|
63
|
+
if (child)
|
|
64
|
+
ctx.traverse(child, level, null);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Calculate cognitive complexity of a function
|
|
69
|
+
*
|
|
70
|
+
* Based on SonarSource's Cognitive Complexity specification:
|
|
71
|
+
* - +1 for each break from linear flow (if, for, while, catch, etc.)
|
|
72
|
+
* - +1 for each nesting level when inside a control structure
|
|
73
|
+
* - +1 for each logical operator sequence break (a && b || c)
|
|
74
|
+
*
|
|
75
|
+
* @see https://www.sonarsource.com/docs/CognitiveComplexity.pdf
|
|
76
|
+
*
|
|
77
|
+
* @param node - AST node to analyze (typically a function/method)
|
|
78
|
+
* @returns Cognitive complexity score (minimum 0)
|
|
79
|
+
*/
|
|
80
|
+
export function calculateCognitiveComplexity(node) {
|
|
81
|
+
let complexity = 0;
|
|
82
|
+
const ctx = { traverse };
|
|
83
|
+
function traverse(n, nestingLevel, lastLogicalOp) {
|
|
84
|
+
const logicalOp = getLogicalOperator(n);
|
|
85
|
+
if (logicalOp) {
|
|
86
|
+
complexity += (lastLogicalOp !== logicalOp) ? 1 : 0;
|
|
87
|
+
traverseLogicalChildren(n, nestingLevel, logicalOp, ctx);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (NESTING_TYPES.has(n.type)) {
|
|
91
|
+
complexity += 1 + nestingLevel;
|
|
92
|
+
traverseNestingChildren(n, nestingLevel, ctx);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (NON_NESTING_TYPES.has(n.type)) {
|
|
96
|
+
complexity += 1;
|
|
97
|
+
traverseAllChildren(n, nestingLevel + 1, ctx);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
complexity += getNestedLambdaIncrement(n.type, nestingLevel);
|
|
101
|
+
traverseAllChildren(n, nestingLevel, ctx);
|
|
102
|
+
}
|
|
103
|
+
traverse(node, 0, null);
|
|
104
|
+
return complexity;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=cognitive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cognitive.js","sourceRoot":"","sources":["../../../../src/indexer/ast/complexity/cognitive.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type Parser from 'tree-sitter';
|
|
2
|
+
/**
|
|
3
|
+
* Calculate cyclomatic complexity of a function
|
|
4
|
+
*
|
|
5
|
+
* Complexity = 1 (base) + number of decision points
|
|
6
|
+
* Decision points: if, while, do...while, for, for...in, for...of, foreach, case, catch, &&, ||, ?:
|
|
7
|
+
*
|
|
8
|
+
* @param node - AST node to analyze (typically a function/method)
|
|
9
|
+
* @returns Cyclomatic complexity score (minimum 1)
|
|
10
|
+
*/
|
|
11
|
+
export declare function calculateComplexity(node: Parser.SyntaxNode): number;
|
|
12
|
+
//# sourceMappingURL=cyclomatic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cyclomatic.d.ts","sourceRoot":"","sources":["../../../../src/indexer/ast/complexity/cyclomatic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AAgCtC;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAyBnE"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decision point node types for cyclomatic complexity calculation.
|
|
3
|
+
*
|
|
4
|
+
* These AST node types represent branch points in code flow.
|
|
5
|
+
*/
|
|
6
|
+
const DECISION_POINTS = [
|
|
7
|
+
// Common across languages (TypeScript/JavaScript/Python/PHP)
|
|
8
|
+
'if_statement', // if conditions
|
|
9
|
+
'while_statement', // while loops
|
|
10
|
+
'for_statement', // for loops
|
|
11
|
+
'switch_case', // switch/case statements
|
|
12
|
+
'catch_clause', // try/catch error handling
|
|
13
|
+
'ternary_expression', // Ternary operator (a ? b : c)
|
|
14
|
+
'binary_expression', // For && and || logical operators
|
|
15
|
+
// TypeScript/JavaScript specific
|
|
16
|
+
'do_statement', // do...while loops
|
|
17
|
+
'for_in_statement', // for...in loops
|
|
18
|
+
'for_of_statement', // for...of loops
|
|
19
|
+
// PHP specific
|
|
20
|
+
'foreach_statement', // PHP foreach loops
|
|
21
|
+
// Python specific
|
|
22
|
+
'elif_clause', // Python elif (adds decision point)
|
|
23
|
+
// Note: 'else_clause' is NOT a decision point (it's the default path)
|
|
24
|
+
'except_clause', // Python except (try/except)
|
|
25
|
+
'conditional_expression', // Python ternary (x if cond else y)
|
|
26
|
+
];
|
|
27
|
+
/**
|
|
28
|
+
* Calculate cyclomatic complexity of a function
|
|
29
|
+
*
|
|
30
|
+
* Complexity = 1 (base) + number of decision points
|
|
31
|
+
* Decision points: if, while, do...while, for, for...in, for...of, foreach, case, catch, &&, ||, ?:
|
|
32
|
+
*
|
|
33
|
+
* @param node - AST node to analyze (typically a function/method)
|
|
34
|
+
* @returns Cyclomatic complexity score (minimum 1)
|
|
35
|
+
*/
|
|
36
|
+
export function calculateComplexity(node) {
|
|
37
|
+
let complexity = 1; // Base complexity
|
|
38
|
+
function traverse(n) {
|
|
39
|
+
if (DECISION_POINTS.includes(n.type)) {
|
|
40
|
+
// For binary expressions, only count && and ||
|
|
41
|
+
if (n.type === 'binary_expression') {
|
|
42
|
+
const operator = n.childForFieldName('operator');
|
|
43
|
+
if (operator && (operator.text === '&&' || operator.text === '||')) {
|
|
44
|
+
complexity++;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
complexity++;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Traverse children
|
|
52
|
+
for (let i = 0; i < n.namedChildCount; i++) {
|
|
53
|
+
const child = n.namedChild(i);
|
|
54
|
+
if (child)
|
|
55
|
+
traverse(child);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
traverse(node);
|
|
59
|
+
return complexity;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=cyclomatic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cyclomatic.js","sourceRoot":"","sources":["../../../../src/indexer/ast/complexity/cyclomatic.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,eAAe,GAAG;IACtB,6DAA6D;IAC7D,cAAc,EAAW,gBAAgB;IACzC,iBAAiB,EAAQ,cAAc;IACvC,eAAe,EAAU,YAAY;IACrC,aAAa,EAAY,yBAAyB;IAClD,cAAc,EAAW,2BAA2B;IACpD,oBAAoB,EAAK,+BAA+B;IACxD,mBAAmB,EAAM,kCAAkC;IAE3D,iCAAiC;IACjC,cAAc,EAAW,mBAAmB;IAC5C,kBAAkB,EAAO,iBAAiB;IAC1C,kBAAkB,EAAO,iBAAiB;IAE1C,eAAe;IACf,mBAAmB,EAAM,oBAAoB;IAE7C,kBAAkB;IAClB,aAAa,EAAY,oCAAoC;IAC7D,sEAAsE;IACtE,eAAe,EAAU,6BAA6B;IACtD,wBAAwB,EAAE,oCAAoC;CAC/D,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAuB;IACzD,IAAI,UAAU,GAAG,CAAC,CAAC,CAAC,kBAAkB;IAEtC,SAAS,QAAQ,CAAC,CAAoB;QACpC,IAAI,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YACrC,+CAA+C;YAC/C,IAAI,CAAC,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;gBACnC,MAAM,QAAQ,GAAG,CAAC,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;gBACjD,IAAI,QAAQ,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,IAAI,IAAI,QAAQ,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;oBACnE,UAAU,EAAE,CAAC;gBACf,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,UAAU,EAAE,CAAC;YACf,CAAC;QACH,CAAC;QAED,oBAAoB;QACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,eAAe,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAI,KAAK;gBAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,CAAC;IACf,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type Parser from 'tree-sitter';
|
|
2
|
+
/** Raw Halstead counts from AST */
|
|
3
|
+
export interface HalsteadCounts {
|
|
4
|
+
n1: number;
|
|
5
|
+
n2: number;
|
|
6
|
+
N1: number;
|
|
7
|
+
N2: number;
|
|
8
|
+
operators: Map<string, number>;
|
|
9
|
+
operands: Map<string, number>;
|
|
10
|
+
}
|
|
11
|
+
/** Calculated Halstead metrics */
|
|
12
|
+
export interface HalsteadMetrics {
|
|
13
|
+
vocabulary: number;
|
|
14
|
+
length: number;
|
|
15
|
+
volume: number;
|
|
16
|
+
difficulty: number;
|
|
17
|
+
effort: number;
|
|
18
|
+
time: number;
|
|
19
|
+
bugs: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Count operators and operands in an AST node
|
|
23
|
+
*
|
|
24
|
+
* @param node - AST node to analyze (typically a function/method)
|
|
25
|
+
* @param language - Programming language for language-specific handling
|
|
26
|
+
* @returns HalsteadCounts with raw operator/operand counts
|
|
27
|
+
*/
|
|
28
|
+
export declare function countHalstead(node: Parser.SyntaxNode, language: string): HalsteadCounts;
|
|
29
|
+
/**
|
|
30
|
+
* Calculate derived Halstead metrics from raw counts
|
|
31
|
+
*
|
|
32
|
+
* Formulas based on Maurice Halstead's "Elements of Software Science" (1977):
|
|
33
|
+
* - Vocabulary (n) = n1 + n2
|
|
34
|
+
* - Length (N) = N1 + N2
|
|
35
|
+
* - Volume (V) = N × log₂(n) - size of implementation
|
|
36
|
+
* - Difficulty (D) = (n1/2) × (N2/n2) - error-proneness
|
|
37
|
+
* - Effort (E) = D × V - mental effort required
|
|
38
|
+
* - Time (T) = E / 18 - seconds to understand (Stroud number)
|
|
39
|
+
* - Bugs (B) = V / 3000 - estimated delivered bugs
|
|
40
|
+
*
|
|
41
|
+
* @param counts - Raw Halstead counts from countHalstead()
|
|
42
|
+
* @returns Calculated HalsteadMetrics
|
|
43
|
+
*/
|
|
44
|
+
export declare function calculateHalsteadMetrics(counts: HalsteadCounts): HalsteadMetrics;
|
|
45
|
+
/**
|
|
46
|
+
* Calculate Halstead metrics for an AST node in one call
|
|
47
|
+
*
|
|
48
|
+
* Convenience function that combines countHalstead and calculateHalsteadMetrics.
|
|
49
|
+
*
|
|
50
|
+
* @param node - AST node to analyze
|
|
51
|
+
* @param language - Programming language
|
|
52
|
+
* @returns Calculated HalsteadMetrics
|
|
53
|
+
*/
|
|
54
|
+
export declare function calculateHalstead(node: Parser.SyntaxNode, language: string): HalsteadMetrics;
|
|
55
|
+
//# sourceMappingURL=halstead.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"halstead.d.ts","sourceRoot":"","sources":["../../../../src/indexer/ast/complexity/halstead.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AAEtC,mCAAmC;AACnC,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,kCAAkC;AAClC,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAiOD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,cAAc,CAiCvF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,cAAc,GAAG,eAAe,CAsBhF;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CAG5F"}
|