diff --git a/gitnexus/package-lock.json b/gitnexus/package-lock.json index a229f0564..cb71624ad 100644 --- a/gitnexus/package-lock.json +++ b/gitnexus/package-lock.json @@ -1,13 +1,12 @@ { "name": "gitnexus", - "version": "1.3.5", + "version": "1.3.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gitnexus", - "version": "1.3.5", - "hasInstallScript": true, + "version": "1.3.6", "license": "PolyForm-Noncommercial-1.0.0", "dependencies": { "@huggingface/transformers": "^3.0.0", @@ -31,11 +30,9 @@ "tree-sitter-go": "^0.21.0", "tree-sitter-java": "^0.21.0", "tree-sitter-javascript": "^0.21.0", - "tree-sitter-kotlin": "^0.3.8", "tree-sitter-php": "^0.23.12", "tree-sitter-python": "^0.21.0", "tree-sitter-rust": "^0.21.0", - "tree-sitter-swift": "^0.6.0", "tree-sitter-typescript": "^0.21.0", "typescript": "^5.4.5", "uuid": "^13.0.0" @@ -4270,19 +4267,6 @@ "node": "^18 || ^20 || >= 21" } }, - "node_modules/tree-sitter-cli": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.23.2.tgz", - "integrity": "sha512-kPPXprOqREX+C/FgUp2Qpt9jd0vSwn+hOgjzVv/7hapdoWpa+VeWId53rf4oNNd29ikheF12BYtGD/W90feMbA==", - "hasInstallScript": true, - "license": "MIT", - "bin": { - "tree-sitter": "cli.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/tree-sitter-cpp": { "version": "0.22.3", "resolved": "https://registry.npmjs.org/tree-sitter-cpp/-/tree-sitter-cpp-0.22.3.tgz", @@ -4395,31 +4379,6 @@ "node": "^18 || ^20 || >= 21" } }, - "node_modules/tree-sitter-kotlin": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/tree-sitter-kotlin/-/tree-sitter-kotlin-0.3.8.tgz", - "integrity": "sha512-A4obq6bjzmYrA+F0JLLoheFPcofFkctNaZSpnDd+GPn1SfVZLY4/GG4C0cYVBTOShuPBGGAOPLM1JWLZQV4m1g==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "node-addon-api": "^7.1.0", - "node-gyp-build": "^4.8.0" - }, - "peerDependencies": { - "tree-sitter": "^0.21.0" - }, - "peerDependenciesMeta": { - "tree_sitter": { - "optional": true - } - } - }, - "node_modules/tree-sitter-kotlin/node_modules/node-addon-api": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "license": "MIT" - }, "node_modules/tree-sitter-php": { "version": "0.23.12", "resolved": "https://registry.npmjs.org/tree-sitter-php/-/tree-sitter-php-0.23.12.tgz", @@ -4498,36 +4457,6 @@ "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", "license": "MIT" }, - "node_modules/tree-sitter-swift": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tree-sitter-swift/-/tree-sitter-swift-0.6.0.tgz", - "integrity": "sha512-9vOJZes4/UFjBr4COHtp6ZHVuZYwfChSQbpneXQog04dAstfx5px3ybVX2cN+ylvLqsvVpmXLpidxxgF2rDQ7A==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "node-addon-api": "^8.0.0", - "node-gyp-build": "^4.8.0", - "tree-sitter-cli": "^0.23", - "which": "2.0.2" - }, - "peerDependencies": { - "tree-sitter": "^0.21.1" - }, - "peerDependenciesMeta": { - "tree_sitter": { - "optional": true - } - } - }, - "node_modules/tree-sitter-swift/node_modules/node-addon-api": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.6.0.tgz", - "integrity": "sha512-gBVjCaqDlRUk0EwoPNKzIr9KkS9041G/q31IBShPs1Xz6UTA+EXdZADbzqAJQrpDRq71CIMnOP5VMut3SL0z5Q==", - "license": "MIT", - "engines": { - "node": "^18 || ^20 || >= 21" - } - }, "node_modules/tree-sitter-typescript": { "version": "0.21.2", "resolved": "https://registry.npmjs.org/tree-sitter-typescript/-/tree-sitter-typescript-0.21.2.tgz", diff --git a/gitnexus/package.json b/gitnexus/package.json index 5b11308ae..5cdb1d33e 100644 --- a/gitnexus/package.json +++ b/gitnexus/package.json @@ -1,6 +1,6 @@ { "name": "gitnexus", - "version": "1.3.5", + "version": "1.3.6", "description": "Graph-powered code intelligence for AI agents. Index any codebase, query via MCP or CLI.", "author": "Abhigyan Patwari", "license": "PolyForm-Noncommercial-1.0.0", @@ -66,13 +66,15 @@ "tree-sitter-javascript": "^0.21.0", "tree-sitter-kotlin": "^0.3.8", "tree-sitter-php": "^0.23.12", - "tree-sitter-swift": "^0.6.0", "tree-sitter-python": "^0.21.0", "tree-sitter-rust": "^0.21.0", "tree-sitter-typescript": "^0.21.0", "typescript": "^5.4.5", "uuid": "^13.0.0" }, + "optionalDependencies": { + "tree-sitter-swift": "^0.6.0" + }, "devDependencies": { "@types/cli-progress": "^3.11.6", "@types/cors": "^2.8.17", diff --git a/gitnexus/src/core/ingestion/call-processor.ts b/gitnexus/src/core/ingestion/call-processor.ts index c5fc3f8df..7ab36ad46 100644 --- a/gitnexus/src/core/ingestion/call-processor.ts +++ b/gitnexus/src/core/ingestion/call-processor.ts @@ -40,6 +40,7 @@ const FUNCTION_NODE_TYPES = new Set([ // Kotlin (function_declaration already included above via JS/TS) 'anonymous_function', 'lambda_literal', + // PHP — no additional node types needed // Swift 'init_declaration', 'deinit_declaration', @@ -327,6 +328,22 @@ const BUILT_IN_NAMES = new Set([ 'open', 'read', 'write', 'close', 'append', 'extend', 'update', 'super', 'type', 'isinstance', 'issubclass', 'getattr', 'setattr', 'hasattr', 'enumerate', 'zip', 'sorted', 'reversed', 'min', 'max', 'sum', 'abs', + // Kotlin stdlib (IMPORTANT: keep in sync with parse-worker.ts BUILT_IN_NAMES) + 'println', 'print', 'readLine', 'require', 'requireNotNull', 'check', 'assert', 'lazy', 'error', + 'listOf', 'mapOf', 'setOf', 'mutableListOf', 'mutableMapOf', 'mutableSetOf', + 'arrayOf', 'sequenceOf', 'also', 'apply', 'run', 'with', 'takeIf', 'takeUnless', + 'TODO', 'buildString', 'buildList', 'buildMap', 'buildSet', + 'repeat', 'synchronized', + // Kotlin coroutine builders & scope functions + 'launch', 'async', 'runBlocking', 'withContext', 'coroutineScope', + 'supervisorScope', 'delay', + // Kotlin Flow operators + 'flow', 'flowOf', 'collect', 'emit', 'onEach', 'catch', + 'buffer', 'conflate', 'distinctUntilChanged', + 'flatMapLatest', 'flatMapMerge', 'combine', + 'stateIn', 'shareIn', 'launchIn', + // Kotlin infix stdlib functions + 'to', 'until', 'downTo', 'step', // C/C++ standard library and common kernel helpers 'printf', 'fprintf', 'sprintf', 'snprintf', 'vprintf', 'vfprintf', 'vsprintf', 'vsnprintf', 'scanf', 'fscanf', 'sscanf', @@ -348,22 +365,6 @@ const BUILT_IN_NAMES = new Set([ 'mutex_lock', 'mutex_unlock', 'mutex_init', 'kfree', 'kmalloc', 'kzalloc', 'kcalloc', 'krealloc', 'kvmalloc', 'kvfree', 'get', 'put', - // Kotlin stdlib (IMPORTANT: keep in sync with parse-worker.ts BUILT_IN_NAMES) - 'println', 'print', 'readLine', 'require', 'requireNotNull', 'check', 'assert', 'lazy', 'error', - 'listOf', 'mapOf', 'setOf', 'mutableListOf', 'mutableMapOf', 'mutableSetOf', - 'arrayOf', 'sequenceOf', 'also', 'apply', 'run', 'with', 'takeIf', 'takeUnless', - 'TODO', 'buildString', 'buildList', 'buildMap', 'buildSet', - 'repeat', 'synchronized', - // Kotlin coroutine builders & scope functions - 'launch', 'async', 'runBlocking', 'withContext', 'coroutineScope', - 'supervisorScope', 'delay', - // Kotlin Flow operators - 'flow', 'flowOf', 'collect', 'emit', 'onEach', 'catch', - 'buffer', 'conflate', 'distinctUntilChanged', - 'flatMapLatest', 'flatMapMerge', 'combine', - 'stateIn', 'shareIn', 'launchIn', - // Kotlin infix stdlib functions - 'to', 'until', 'downTo', 'step', // Swift/iOS built-ins and standard library 'print', 'debugPrint', 'dump', 'fatalError', 'precondition', 'preconditionFailure', 'assert', 'assertionFailure', 'NSLog', diff --git a/gitnexus/src/core/ingestion/parsing-processor.ts b/gitnexus/src/core/ingestion/parsing-processor.ts index 8c60802c2..7a68becc4 100644 --- a/gitnexus/src/core/ingestion/parsing-processor.ts +++ b/gitnexus/src/core/ingestion/parsing-processor.ts @@ -141,12 +141,6 @@ const isNodeExported = (node: any, name: string, language: string): boolean => { } return false; - // C/C++: No native export concept at language level - // Entry points will be detected via name patterns (main, etc.) - case 'c': - case 'cpp': - return false; - // Kotlin: Default visibility is public (unlike Java) // visibility_modifier is inside modifiers, a sibling of the name node within the declaration case 'kotlin': @@ -164,6 +158,12 @@ const isNodeExported = (node: any, name: string, language: string): boolean => { // No visibility modifier = public (Kotlin default) return true; + // C/C++: No native export concept at language level + // Entry points will be detected via name patterns (main, etc.) + case 'c': + case 'cpp': + return false; + // Swift: Check for 'public' or 'open' access modifiers case 'swift': while (current) { diff --git a/gitnexus/src/core/ingestion/workers/parse-worker.ts b/gitnexus/src/core/ingestion/workers/parse-worker.ts index d31c980fe..e7d9d1931 100644 --- a/gitnexus/src/core/ingestion/workers/parse-worker.ts +++ b/gitnexus/src/core/ingestion/workers/parse-worker.ts @@ -9,11 +9,16 @@ import CPP from 'tree-sitter-cpp'; import CSharp from 'tree-sitter-c-sharp'; import Go from 'tree-sitter-go'; import Rust from 'tree-sitter-rust'; -import PHP from 'tree-sitter-php'; import Kotlin from 'tree-sitter-kotlin'; -import Swift from 'tree-sitter-swift'; +import PHP from 'tree-sitter-php'; +import { createRequire } from 'node:module'; import { SupportedLanguages } from '../../../config/supported-languages.js'; import { LANGUAGE_QUERIES } from '../tree-sitter-queries.js'; + +// tree-sitter-swift is an optionalDependency — may not be installed +const _require = createRequire(import.meta.url); +let Swift: any = null; +try { Swift = _require('tree-sitter-swift'); } catch {} import { findSiblingChild, getLanguageFromFilename } from '../utils.js'; import { detectFrameworkFromAST } from '../framework-detection.js'; import { generateId } from '../../../lib/utils.js'; @@ -107,9 +112,9 @@ const languageMap: Record = { [SupportedLanguages.CSharp]: CSharp, [SupportedLanguages.Go]: Go, [SupportedLanguages.Rust]: Rust, - [SupportedLanguages.PHP]: PHP.php_only, [SupportedLanguages.Kotlin]: Kotlin, - [SupportedLanguages.Swift]: Swift, + [SupportedLanguages.PHP]: PHP.php_only, + ...(Swift ? { [SupportedLanguages.Swift]: Swift } : {}), }; const setLanguage = (language: SupportedLanguages, filePath: string): void => { @@ -191,18 +196,25 @@ const isNodeExported = (node: any, name: string, language: string): boolean => { } return false; - case 'c': - case 'cpp': - return false; - - case 'swift': + // Kotlin: Default visibility is public (unlike Java) + // visibility_modifier is inside modifiers, a sibling of the name node within the declaration + case 'kotlin': while (current) { - if (current.type === 'modifiers' || current.type === 'visibility_modifier') { - const text = current.text || ''; - if (text.includes('public') || text.includes('open')) return true; + if (current.parent) { + const visMod = findSiblingChild(current.parent, 'modifiers', 'visibility_modifier'); + if (visMod) { + const text = visMod.text; + if (text === 'private' || text === 'internal' || text === 'protected') return false; + if (text === 'public') return true; + } } current = current.parent; } + // No visibility modifier = public (Kotlin default) + return true; + + case 'c': + case 'cpp': return false; case 'php': @@ -223,22 +235,15 @@ const isNodeExported = (node: any, name: string, language: string): boolean => { // Top-level functions (no parent class) are globally accessible return true; - // Kotlin: Default visibility is public (unlike Java) - // visibility_modifier is inside modifiers, a sibling of the name node within the declaration - case 'kotlin': + case 'swift': while (current) { - if (current.parent) { - const visMod = findSiblingChild(current.parent, 'modifiers', 'visibility_modifier'); - if (visMod) { - const text = visMod.text; - if (text === 'private' || text === 'internal' || text === 'protected') return false; - if (text === 'public') return true; - } + if (current.type === 'modifiers' || current.type === 'visibility_modifier') { + const text = current.text || ''; + if (text.includes('public') || text.includes('open')) return true; } current = current.parent; } - // No visibility modifier = public (Kotlin default) - return true; + return false; default: return false; @@ -255,10 +260,12 @@ const FUNCTION_NODE_TYPES = new Set([ 'function_definition', 'async_function_declaration', 'async_arrow_function', 'method_declaration', 'constructor_declaration', 'local_function_statement', 'function_item', 'impl_item', - 'anonymous_function_creation_expression', // PHP anonymous functions // Kotlin (function_declaration already included above via JS/TS) 'anonymous_function', 'lambda_literal', - 'init_declaration', 'deinit_declaration', // Swift initializers/deinitializers + // PHP + 'anonymous_function_creation_expression', + // Swift initializers/deinitializers + 'init_declaration', 'deinit_declaration', ]); /** Walk up AST to find enclosing function, return its generateId or null for top-level */ @@ -341,6 +348,22 @@ const BUILT_INS = new Set([ 'open', 'read', 'write', 'close', 'append', 'extend', 'update', 'super', 'type', 'isinstance', 'issubclass', 'getattr', 'setattr', 'hasattr', 'enumerate', 'zip', 'sorted', 'reversed', 'min', 'max', 'sum', 'abs', + // Kotlin stdlib (IMPORTANT: keep in sync with call-processor.ts BUILT_IN_NAMES) + 'println', 'print', 'readLine', 'require', 'requireNotNull', 'check', 'assert', 'lazy', 'error', + 'listOf', 'mapOf', 'setOf', 'mutableListOf', 'mutableMapOf', 'mutableSetOf', + 'arrayOf', 'sequenceOf', 'also', 'apply', 'run', 'with', 'takeIf', 'takeUnless', + 'TODO', 'buildString', 'buildList', 'buildMap', 'buildSet', + 'repeat', 'synchronized', + // Kotlin coroutine builders & scope functions + 'launch', 'async', 'runBlocking', 'withContext', 'coroutineScope', + 'supervisorScope', 'delay', + // Kotlin Flow operators + 'flow', 'flowOf', 'collect', 'emit', 'onEach', 'catch', + 'buffer', 'conflate', 'distinctUntilChanged', + 'flatMapLatest', 'flatMapMerge', 'combine', + 'stateIn', 'shareIn', 'launchIn', + // Kotlin infix stdlib functions + 'to', 'until', 'downTo', 'step', // C/C++ standard library 'printf', 'fprintf', 'sprintf', 'snprintf', 'vprintf', 'vfprintf', 'vsprintf', 'vsnprintf', 'scanf', 'fscanf', 'sscanf', @@ -379,22 +402,6 @@ const BUILT_INS = new Set([ 'preg_match', 'preg_match_all', 'preg_replace', 'preg_split', 'header', 'session_start', 'session_destroy', 'ob_start', 'ob_end_clean', 'ob_get_clean', 'dd', 'dump', - // Kotlin stdlib (IMPORTANT: keep in sync with call-processor.ts BUILT_IN_NAMES) - 'println', 'print', 'readLine', 'require', 'requireNotNull', 'check', 'assert', 'lazy', 'error', - 'listOf', 'mapOf', 'setOf', 'mutableListOf', 'mutableMapOf', 'mutableSetOf', - 'arrayOf', 'sequenceOf', 'also', 'apply', 'run', 'with', 'takeIf', 'takeUnless', - 'TODO', 'buildString', 'buildList', 'buildMap', 'buildSet', - 'repeat', 'synchronized', - // Kotlin coroutine builders & scope functions - 'launch', 'async', 'runBlocking', 'withContext', 'coroutineScope', - 'supervisorScope', 'delay', - // Kotlin Flow operators - 'flow', 'flowOf', 'collect', 'emit', 'onEach', 'catch', - 'buffer', 'conflate', 'distinctUntilChanged', - 'flatMapLatest', 'flatMapMerge', 'combine', - 'stateIn', 'shareIn', 'launchIn', - // Kotlin infix stdlib functions - 'to', 'until', 'downTo', 'step', // Swift/iOS built-ins and standard library 'print', 'debugPrint', 'dump', 'fatalError', 'precondition', 'preconditionFailure', 'assert', 'assertionFailure', 'NSLog', diff --git a/gitnexus/src/core/tree-sitter/parser-loader.ts b/gitnexus/src/core/tree-sitter/parser-loader.ts index f0133e5e2..3cc9fc025 100644 --- a/gitnexus/src/core/tree-sitter/parser-loader.ts +++ b/gitnexus/src/core/tree-sitter/parser-loader.ts @@ -8,11 +8,16 @@ import CPP from 'tree-sitter-cpp'; import CSharp from 'tree-sitter-c-sharp'; import Go from 'tree-sitter-go'; import Rust from 'tree-sitter-rust'; -import PHP from 'tree-sitter-php'; import Kotlin from 'tree-sitter-kotlin'; -import Swift from 'tree-sitter-swift'; +import PHP from 'tree-sitter-php'; +import { createRequire } from 'node:module'; import { SupportedLanguages } from '../../config/supported-languages.js'; +// tree-sitter-swift is an optionalDependency — may not be installed +const _require = createRequire(import.meta.url); +let Swift: any = null; +try { Swift = _require('tree-sitter-swift'); } catch {} + let parser: Parser | null = null; const languageMap: Record = { @@ -26,9 +31,9 @@ const languageMap: Record = { [SupportedLanguages.CSharp]: CSharp, [SupportedLanguages.Go]: Go, [SupportedLanguages.Rust]: Rust, - [SupportedLanguages.PHP]: PHP.php_only, [SupportedLanguages.Kotlin]: Kotlin, - [SupportedLanguages.Swift]: Swift, + [SupportedLanguages.PHP]: PHP.php_only, + ...(Swift ? { [SupportedLanguages.Swift]: Swift } : {}), }; export const loadParser = async (): Promise => {