Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions gitnexus/src/core/ingestion/languages/kotlin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ import { kotlinMethodConfig } from '../method-extractors/configs/jvm.js';
import { createVariableExtractor } from '../variable-extractors/generic.js';
import { kotlinVariableConfig } from '../variable-extractors/configs/jvm.js';
import { createHeritageExtractor } from '../heritage-extractors/generic.js';
import {
emitKotlinScopeCaptures,
interpretKotlinImport,
interpretKotlinTypeBinding,
kotlinArityCompatibility,
kotlinBindingScopeFor,
kotlinImportOwningScope,
kotlinMergeBindings,
kotlinReceiverBinding,
} from './kotlin/index.js';

/** Check if a Kotlin function_declaration capture is inside a class_body (i.e., a method).
* Kotlin grammar uses function_declaration for both top-level functions and class methods.
Expand Down Expand Up @@ -166,4 +176,14 @@ export const kotlinProvider = defineLanguage({
if (isKotlinClassMethod(functionNode)) return 'Method';
return defaultLabel;
},

// ── RFC #909 Ring 3: scope-based resolution hooks ──
emitScopeCaptures: emitKotlinScopeCaptures,
interpretImport: interpretKotlinImport,
interpretTypeBinding: interpretKotlinTypeBinding,
bindingScopeFor: kotlinBindingScopeFor,
importOwningScope: kotlinImportOwningScope,
mergeBindings: (_scope, bindings) => kotlinMergeBindings(bindings),
receiverBinding: kotlinReceiverBinding,
arityCompatibility: kotlinArityCompatibility,
});
26 changes: 26 additions & 0 deletions gitnexus/src/core/ingestion/languages/kotlin/arity-metadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { SyntaxNode } from '../../utils/ast-helpers.js';
import { kotlinMethodConfig } from '../../method-extractors/configs/jvm.js';

export interface KotlinArityMetadata {
readonly parameterCount: number | undefined;
readonly requiredParameterCount: number | undefined;
readonly parameterTypes: readonly string[] | undefined;
}

export function computeKotlinArityMetadata(fnNode: SyntaxNode): KotlinArityMetadata {
const params = kotlinMethodConfig.extractParameters?.(fnNode) ?? [];
let hasVararg = false;
const parameterTypes: string[] = [];
for (const param of params) {
if (param.isVariadic) hasVararg = true;
if (param.type !== null) parameterTypes.push(param.type);
}
if (hasVararg) parameterTypes.push('vararg');

const required = params.filter((p) => !p.isOptional && !p.isVariadic).length;
return {
parameterCount: hasVararg ? undefined : params.length,
requiredParameterCount: required,
parameterTypes: parameterTypes.length > 0 ? parameterTypes : undefined,
};
}
18 changes: 18 additions & 0 deletions gitnexus/src/core/ingestion/languages/kotlin/arity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { Callsite, SymbolDefinition } from 'gitnexus-shared';

export function kotlinArityCompatibility(
def: SymbolDefinition,
callsite: Callsite,
): 'compatible' | 'unknown' | 'incompatible' {
const min = def.requiredParameterCount;
const max = def.parameterCount;
if (min === undefined && max === undefined) return 'unknown';

const argCount = callsite.arity;
if (!Number.isFinite(argCount) || argCount < 0) return 'unknown';

const hasVararg = def.parameterTypes?.some((t) => t === 'vararg') ?? false;
if (min !== undefined && argCount < min) return 'incompatible';
if (max !== undefined && argCount > max && !hasVararg) return 'incompatible';
return 'compatible';
}
19 changes: 19 additions & 0 deletions gitnexus/src/core/ingestion/languages/kotlin/cache-stats.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
let hits = 0;
let misses = 0;

export function recordKotlinCacheHit(): void {
hits += 1;
}

export function recordKotlinCacheMiss(): void {
misses += 1;
}

export function getKotlinCaptureCacheStats(): { readonly hits: number; readonly misses: number } {
return { hits, misses };
}

export function resetKotlinCaptureCacheStats(): void {
hits = 0;
misses = 0;
}
Loading
Loading