mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-09 03:17:54 +00:00
feat(ingestion): add heritage extractor config+factory pattern with per-language configs
- Create heritage-types.ts with HeritageExtractionConfig, HeritageExtractor, HeritageInfo interfaces - Create heritage-extractors/generic.ts with createHeritageExtractor() factory - Create 11 per-language config files in heritage-extractors/configs/ - Add heritageExtractor field to LanguageProviderConfig interface - Wire createHeritageExtractor() in all 16 language providers - Replace inline heritage capture handling in parse-worker with provider.heritageExtractor - Add extractFromCall support for Ruby call-based heritage (include/extend/prepend) - Replace inline heritage logic in heritage-processor extractExtractedHeritageFromFiles - Ruby heritage config absorbs mixin routing logic from CallRouter Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/b55df80d-758a-48cd-96de-a7657bdc2acb Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>
This commit is contained in:
parent
541e4f7ce6
commit
835e69c53e
29 changed files with 534 additions and 54 deletions
|
|
@ -0,0 +1,25 @@
|
|||
// gitnexus/src/core/ingestion/heritage-extractors/configs/c-cpp.ts
|
||||
|
||||
import { SupportedLanguages } from 'gitnexus-shared';
|
||||
import type { HeritageExtractionConfig } from '../../heritage-types.js';
|
||||
|
||||
/**
|
||||
* C heritage extraction config.
|
||||
*
|
||||
* C has no class inheritance — no heritage captures expected.
|
||||
* Config exists for completeness in the provider wiring.
|
||||
*/
|
||||
export const cHeritageConfig: HeritageExtractionConfig = {
|
||||
language: SupportedLanguages.C,
|
||||
};
|
||||
|
||||
/**
|
||||
* C++ heritage extraction config.
|
||||
*
|
||||
* C++ has standard extends heritage through tree-sitter captures
|
||||
* (class A : public B). Multiple inheritance uses leftmost-base MRO
|
||||
* at the resolution layer. No special extraction hooks needed.
|
||||
*/
|
||||
export const cppHeritageConfig: HeritageExtractionConfig = {
|
||||
language: SupportedLanguages.CPlusPlus,
|
||||
};
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// gitnexus/src/core/ingestion/heritage-extractors/configs/csharp.ts
|
||||
|
||||
import { SupportedLanguages } from 'gitnexus-shared';
|
||||
import type { HeritageExtractionConfig } from '../../heritage-types.js';
|
||||
|
||||
/**
|
||||
* C# heritage extraction config.
|
||||
*
|
||||
* C# has standard extends/implements heritage through tree-sitter
|
||||
* captures. Interface detection uses I-prefix convention (handled
|
||||
* by heritage resolution strategy, not here).
|
||||
*/
|
||||
export const csharpHeritageConfig: HeritageExtractionConfig = {
|
||||
language: SupportedLanguages.CSharp,
|
||||
};
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// gitnexus/src/core/ingestion/heritage-extractors/configs/dart.ts
|
||||
|
||||
import { SupportedLanguages } from 'gitnexus-shared';
|
||||
import type { HeritageExtractionConfig } from '../../heritage-types.js';
|
||||
|
||||
/**
|
||||
* Dart heritage extraction config.
|
||||
*
|
||||
* Dart has standard extends/implements/with heritage through tree-sitter
|
||||
* captures. No special extraction hooks needed.
|
||||
*/
|
||||
export const dartHeritageConfig: HeritageExtractionConfig = {
|
||||
language: SupportedLanguages.Dart,
|
||||
};
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// gitnexus/src/core/ingestion/heritage-extractors/configs/go.ts
|
||||
|
||||
import { SupportedLanguages } from 'gitnexus-shared';
|
||||
import type { HeritageExtractionConfig } from '../../heritage-types.js';
|
||||
|
||||
/**
|
||||
* Go heritage extraction config.
|
||||
*
|
||||
* Go struct embedding: the tree-sitter query matches ALL field_declarations
|
||||
* with type_identifier, but only anonymous fields (no name) are embedded.
|
||||
* Named fields like `Breed string` also match — skip them.
|
||||
*
|
||||
* The shouldSkipExtends hook checks if the extends node's parent is a
|
||||
* field_declaration with a named field child, indicating a regular
|
||||
* (non-embedded) field that should not produce a heritage record.
|
||||
*/
|
||||
export const goHeritageConfig: HeritageExtractionConfig = {
|
||||
language: SupportedLanguages.Go,
|
||||
|
||||
shouldSkipExtends(extendsNode) {
|
||||
const fieldDecl = extendsNode.parent;
|
||||
return (
|
||||
fieldDecl?.type === 'field_declaration' &&
|
||||
fieldDecl.childForFieldName?.('name') != null
|
||||
);
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// gitnexus/src/core/ingestion/heritage-extractors/configs/jvm.ts
|
||||
|
||||
import { SupportedLanguages } from 'gitnexus-shared';
|
||||
import type { HeritageExtractionConfig } from '../../heritage-types.js';
|
||||
|
||||
/**
|
||||
* Java heritage extraction config.
|
||||
*
|
||||
* Java has standard extends/implements heritage through tree-sitter
|
||||
* captures. No special extraction hooks needed.
|
||||
*/
|
||||
export const javaHeritageConfig: HeritageExtractionConfig = {
|
||||
language: SupportedLanguages.Java,
|
||||
};
|
||||
|
||||
/**
|
||||
* Kotlin heritage extraction config.
|
||||
*
|
||||
* Kotlin uses ':' for both extends and implements (delegation markers
|
||||
* are tree-sitter captures). No special extraction hooks needed.
|
||||
*/
|
||||
export const kotlinHeritageConfig: HeritageExtractionConfig = {
|
||||
language: SupportedLanguages.Kotlin,
|
||||
};
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// gitnexus/src/core/ingestion/heritage-extractors/configs/php.ts
|
||||
|
||||
import { SupportedLanguages } from 'gitnexus-shared';
|
||||
import type { HeritageExtractionConfig } from '../../heritage-types.js';
|
||||
|
||||
/**
|
||||
* PHP heritage extraction config.
|
||||
*
|
||||
* PHP has standard extends/implements heritage through tree-sitter
|
||||
* captures. No special extraction hooks needed.
|
||||
*/
|
||||
export const phpHeritageConfig: HeritageExtractionConfig = {
|
||||
language: SupportedLanguages.PHP,
|
||||
};
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// gitnexus/src/core/ingestion/heritage-extractors/configs/python.ts
|
||||
|
||||
import { SupportedLanguages } from 'gitnexus-shared';
|
||||
import type { HeritageExtractionConfig } from '../../heritage-types.js';
|
||||
|
||||
/**
|
||||
* Python heritage extraction config.
|
||||
*
|
||||
* Python has standard extends heritage through tree-sitter captures
|
||||
* (class A(B, C)). Multiple inheritance is handled by C3 MRO at
|
||||
* the resolution layer. No special extraction hooks needed.
|
||||
*/
|
||||
export const pythonHeritageConfig: HeritageExtractionConfig = {
|
||||
language: SupportedLanguages.Python,
|
||||
};
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
// gitnexus/src/core/ingestion/heritage-extractors/configs/ruby.ts
|
||||
|
||||
import { SupportedLanguages } from 'gitnexus-shared';
|
||||
import type { HeritageExtractionConfig, HeritageInfo } from '../../heritage-types.js';
|
||||
import type { SyntaxNode } from '../../utils/ast-helpers.js';
|
||||
|
||||
/**
|
||||
* Maximum parent depth for enclosing class/module walk.
|
||||
* Prevents runaway walks on malformed/deeply-nested ASTs.
|
||||
*/
|
||||
const MAX_PARENT_DEPTH = 50;
|
||||
|
||||
/**
|
||||
* Walk up the AST from a call node to find the enclosing class or module name.
|
||||
* Ruby include/extend/prepend calls must be inside a class or module body.
|
||||
*/
|
||||
function findEnclosingClassName(callNode: SyntaxNode): string | null {
|
||||
let current = callNode.parent;
|
||||
let depth = 0;
|
||||
while (current && ++depth <= MAX_PARENT_DEPTH) {
|
||||
if (current.type === 'class' || current.type === 'module') {
|
||||
const nameNode = current.childForFieldName?.('name');
|
||||
if (nameNode) return nameNode.text;
|
||||
}
|
||||
current = current.parent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Ruby heritage call names that express mixin inclusion. */
|
||||
const RUBY_HERITAGE_CALL_NAMES: ReadonlySet<string> = new Set([
|
||||
'include',
|
||||
'extend',
|
||||
'prepend',
|
||||
]);
|
||||
|
||||
/**
|
||||
* Ruby heritage extraction config.
|
||||
*
|
||||
* Ruby has no tree-sitter heritage captures — inheritance is expressed
|
||||
* through the class definition syntax (`class A < B`) which produces
|
||||
* standard @heritage.extends captures, and through method calls
|
||||
* (include/extend/prepend) which are call-based heritage.
|
||||
*
|
||||
* The callBasedHeritage hook absorbs the mixin routing logic that was
|
||||
* previously in call-routing.ts (routeRubyCall).
|
||||
*/
|
||||
export const rubyHeritageConfig: HeritageExtractionConfig = {
|
||||
language: SupportedLanguages.Ruby,
|
||||
|
||||
callBasedHeritage: {
|
||||
callNames: RUBY_HERITAGE_CALL_NAMES,
|
||||
|
||||
extract(calledName, callNode, _filePath): HeritageInfo[] {
|
||||
const enclosingClass = findEnclosingClassName(callNode);
|
||||
if (!enclosingClass) return [];
|
||||
|
||||
const results: HeritageInfo[] = [];
|
||||
const argList = callNode.childForFieldName?.('arguments');
|
||||
for (const arg of argList?.children ?? []) {
|
||||
if (arg.type === 'constant' || arg.type === 'scope_resolution') {
|
||||
results.push({
|
||||
className: enclosingClass,
|
||||
parentName: arg.text,
|
||||
kind: calledName, // 'include' | 'extend' | 'prepend'
|
||||
});
|
||||
}
|
||||
}
|
||||
return results;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// gitnexus/src/core/ingestion/heritage-extractors/configs/rust.ts
|
||||
|
||||
import { SupportedLanguages } from 'gitnexus-shared';
|
||||
import type { HeritageExtractionConfig } from '../../heritage-types.js';
|
||||
|
||||
/**
|
||||
* Rust heritage extraction config.
|
||||
*
|
||||
* Rust uses impl Trait for Struct syntax. Heritage captures include
|
||||
* heritage.trait for trait implementations. No special extraction
|
||||
* hooks needed beyond the standard capture handling.
|
||||
*/
|
||||
export const rustHeritageConfig: HeritageExtractionConfig = {
|
||||
language: SupportedLanguages.Rust,
|
||||
};
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// gitnexus/src/core/ingestion/heritage-extractors/configs/swift.ts
|
||||
|
||||
import { SupportedLanguages } from 'gitnexus-shared';
|
||||
import type { HeritageExtractionConfig } from '../../heritage-types.js';
|
||||
|
||||
/**
|
||||
* Swift heritage extraction config.
|
||||
*
|
||||
* Swift uses ':' for protocol conformance and class inheritance.
|
||||
* The heritageDefaultEdge ('IMPLEMENTS') and resolution strategy
|
||||
* are handled at the provider/resolution layer. No special
|
||||
* extraction hooks needed.
|
||||
*/
|
||||
export const swiftHeritageConfig: HeritageExtractionConfig = {
|
||||
language: SupportedLanguages.Swift,
|
||||
};
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// gitnexus/src/core/ingestion/heritage-extractors/configs/typescript-javascript.ts
|
||||
|
||||
import { SupportedLanguages } from 'gitnexus-shared';
|
||||
import type { HeritageExtractionConfig } from '../../heritage-types.js';
|
||||
|
||||
/**
|
||||
* TypeScript heritage extraction config.
|
||||
*
|
||||
* TypeScript has standard extends/implements heritage through tree-sitter
|
||||
* captures. No special extraction hooks needed.
|
||||
*/
|
||||
export const typescriptHeritageConfig: HeritageExtractionConfig = {
|
||||
language: SupportedLanguages.TypeScript,
|
||||
};
|
||||
|
||||
/**
|
||||
* JavaScript heritage extraction config.
|
||||
*
|
||||
* JavaScript has extends heritage (class A extends B). No implements
|
||||
* keyword in plain JS. No special extraction hooks needed.
|
||||
*/
|
||||
export const javascriptHeritageConfig: HeritageExtractionConfig = {
|
||||
language: SupportedLanguages.JavaScript,
|
||||
};
|
||||
73
gitnexus/src/core/ingestion/heritage-extractors/generic.ts
Normal file
73
gitnexus/src/core/ingestion/heritage-extractors/generic.ts
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
// gitnexus/src/core/ingestion/heritage-extractors/generic.ts
|
||||
|
||||
/**
|
||||
* Generic table-driven heritage extractor factory.
|
||||
*
|
||||
* Follows the same config+factory pattern as method-extractors/generic.ts,
|
||||
* field-extractors/generic.ts, call-extractors/generic.ts, and
|
||||
* variable-extractors/generic.ts.
|
||||
*
|
||||
* Define a HeritageExtractionConfig per language and generate extractors
|
||||
* from configs. The factory creates a HeritageExtractor whose behaviour
|
||||
* is entirely driven by HeritageExtractionConfig.
|
||||
*/
|
||||
|
||||
import type { CaptureMap } from '../language-provider.js';
|
||||
import type {
|
||||
HeritageExtractionConfig,
|
||||
HeritageExtractor,
|
||||
HeritageExtractorContext,
|
||||
HeritageInfo,
|
||||
} from '../heritage-types.js';
|
||||
import type { SyntaxNode } from '../utils/ast-helpers.js';
|
||||
|
||||
/**
|
||||
* Create a HeritageExtractor from a declarative config.
|
||||
*/
|
||||
export function createHeritageExtractor(config: HeritageExtractionConfig): HeritageExtractor {
|
||||
const callNameSet = config.callBasedHeritage?.callNames;
|
||||
|
||||
return {
|
||||
language: config.language,
|
||||
|
||||
extract(captureMap: CaptureMap, context: HeritageExtractorContext): HeritageInfo[] {
|
||||
const classNode = captureMap['heritage.class'];
|
||||
if (!classNode) return [];
|
||||
|
||||
const className = classNode.text;
|
||||
const results: HeritageInfo[] = [];
|
||||
|
||||
const extendsNode = captureMap['heritage.extends'];
|
||||
if (extendsNode) {
|
||||
if (!config.shouldSkipExtends?.(extendsNode)) {
|
||||
results.push({ className, parentName: extendsNode.text, kind: 'extends' });
|
||||
}
|
||||
}
|
||||
|
||||
const implementsNode = captureMap['heritage.implements'];
|
||||
if (implementsNode) {
|
||||
results.push({ className, parentName: implementsNode.text, kind: 'implements' });
|
||||
}
|
||||
|
||||
const traitNode = captureMap['heritage.trait'];
|
||||
if (traitNode) {
|
||||
results.push({ className, parentName: traitNode.text, kind: 'trait-impl' });
|
||||
}
|
||||
|
||||
return results;
|
||||
},
|
||||
|
||||
...(callNameSet
|
||||
? {
|
||||
extractFromCall(
|
||||
calledName: string,
|
||||
callNode: SyntaxNode,
|
||||
context: HeritageExtractorContext,
|
||||
): HeritageInfo[] | null {
|
||||
if (!callNameSet.has(calledName)) return null;
|
||||
return config.callBasedHeritage!.extract(calledName, callNode, context.filePath);
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
|
|
@ -407,36 +407,20 @@ export async function extractExtractedHeritageFromFiles(
|
|||
});
|
||||
|
||||
if (captureMap['heritage.class']) {
|
||||
if (captureMap['heritage.extends']) {
|
||||
const extendsNode = captureMap['heritage.extends'];
|
||||
const fieldDecl = extendsNode.parent;
|
||||
const isNamedField =
|
||||
fieldDecl?.type === 'field_declaration' && fieldDecl.childForFieldName('name');
|
||||
if (!isNamedField) {
|
||||
if (provider.heritageExtractor) {
|
||||
const heritageItems = provider.heritageExtractor.extract(captureMap, {
|
||||
filePath: file.path,
|
||||
language,
|
||||
});
|
||||
for (const item of heritageItems) {
|
||||
out.push({
|
||||
filePath: file.path,
|
||||
className: captureMap['heritage.class'].text,
|
||||
parentName: captureMap['heritage.extends'].text,
|
||||
kind: 'extends',
|
||||
className: item.className,
|
||||
parentName: item.parentName,
|
||||
kind: item.kind,
|
||||
});
|
||||
}
|
||||
}
|
||||
if (captureMap['heritage.implements']) {
|
||||
out.push({
|
||||
filePath: file.path,
|
||||
className: captureMap['heritage.class'].text,
|
||||
parentName: captureMap['heritage.implements'].text,
|
||||
kind: 'implements',
|
||||
});
|
||||
}
|
||||
if (captureMap['heritage.trait']) {
|
||||
out.push({
|
||||
filePath: file.path,
|
||||
className: captureMap['heritage.class'].text,
|
||||
parentName: captureMap['heritage.trait'].text,
|
||||
kind: 'trait-impl',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
108
gitnexus/src/core/ingestion/heritage-types.ts
Normal file
108
gitnexus/src/core/ingestion/heritage-types.ts
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
// gitnexus/src/core/ingestion/heritage-types.ts
|
||||
|
||||
/**
|
||||
* Types for the language-agnostic heritage extraction pipeline.
|
||||
*
|
||||
* Follows the same pattern as call-types.ts, variable-types.ts, and
|
||||
* method-types.ts: defines the domain interfaces consumed by
|
||||
* createHeritageExtractor() and the per-language configs.
|
||||
*
|
||||
* Heritage extraction handles extends/implements/trait-impl captures from
|
||||
* tree-sitter queries, plus call-based heritage for languages like Ruby
|
||||
* (include/extend/prepend expressed as method calls).
|
||||
*/
|
||||
|
||||
import type { SupportedLanguages } from 'gitnexus-shared';
|
||||
import type { SyntaxNode } from './utils/ast-helpers.js';
|
||||
import type { CaptureMap } from './language-provider.js';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Extracted result
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Per-match heritage extraction result. The parse worker adds filePath to
|
||||
* produce the final {@link ExtractedHeritage} that enters the resolution
|
||||
* pipeline (heritage-processor.ts / heritage-map.ts).
|
||||
*/
|
||||
export interface HeritageInfo {
|
||||
className: string;
|
||||
parentName: string;
|
||||
/** 'extends' | 'implements' | 'trait-impl' | 'include' | 'extend' | 'prepend' */
|
||||
kind: string;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Context
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface HeritageExtractorContext {
|
||||
filePath: string;
|
||||
language: SupportedLanguages;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Extractor interface (produced by createHeritageExtractor)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface HeritageExtractor {
|
||||
readonly language: SupportedLanguages;
|
||||
|
||||
/**
|
||||
* Extract heritage records from tree-sitter @heritage.* captures.
|
||||
*
|
||||
* @param captureMap The capture map from a single tree-sitter match
|
||||
* @param context File path and language context
|
||||
* @returns Array of heritage records (may be empty if captures don't match)
|
||||
*/
|
||||
extract(captureMap: CaptureMap, context: HeritageExtractorContext): HeritageInfo[];
|
||||
|
||||
/**
|
||||
* Extract heritage from a call node (for languages where heritage is
|
||||
* expressed as method calls, e.g., Ruby include/extend/prepend).
|
||||
*
|
||||
* @param calledName The method name (e.g. 'include', 'extend', 'prepend')
|
||||
* @param callNode The tree-sitter call AST node
|
||||
* @param context File path and language context
|
||||
* @returns Heritage records if the call is heritage-related, or null to
|
||||
* fall through to the call router / normal call handling.
|
||||
*/
|
||||
extractFromCall?(
|
||||
calledName: string,
|
||||
callNode: SyntaxNode,
|
||||
context: HeritageExtractorContext,
|
||||
): HeritageInfo[] | null;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Config interface (one per language / language group)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface HeritageExtractionConfig {
|
||||
language: SupportedLanguages;
|
||||
|
||||
/**
|
||||
* Called for heritage.extends captures. Return true to skip this extends
|
||||
* capture. Used by Go to skip named struct fields that match the
|
||||
* field_declaration pattern but are not anonymous embeddings.
|
||||
*
|
||||
* Default: never skip (all extends captures are valid).
|
||||
*/
|
||||
shouldSkipExtends?: (extendsNode: SyntaxNode) => boolean;
|
||||
|
||||
/**
|
||||
* Call-based heritage extraction for languages where heritage is expressed
|
||||
* as method calls (e.g., Ruby include/extend/prepend).
|
||||
*
|
||||
* callNames: set of method names that trigger heritage extraction.
|
||||
* extract: extract heritage items from the call node + method name.
|
||||
*/
|
||||
callBasedHeritage?: {
|
||||
readonly callNames: ReadonlySet<string>;
|
||||
extract(
|
||||
calledName: string,
|
||||
callNode: SyntaxNode,
|
||||
filePath: string,
|
||||
): HeritageInfo[];
|
||||
};
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ import type { CallExtractor } from './call-types.js';
|
|||
import type { ClassExtractor } from './class-types.js';
|
||||
import type { ExportChecker } from './export-detection.js';
|
||||
import type { FieldExtractor } from './field-extractor.js';
|
||||
import type { HeritageExtractor } from './heritage-types.js';
|
||||
import type { MethodExtractor } from './method-types.js';
|
||||
import type { VariableExtractor } from './variable-types.js';
|
||||
import type { ImportResolverFn } from './import-resolvers/types.js';
|
||||
|
|
@ -179,6 +180,11 @@ interface LanguageProviderConfig {
|
|||
* Uses the same provider-driven strategy pattern as method/field extraction so
|
||||
* namespace/package/module rules stay language-specific. */
|
||||
readonly classExtractor?: ClassExtractor;
|
||||
/** Heritage extractor for extracting extends/implements/trait-impl relationships
|
||||
* from tree-sitter @heritage.* captures and call-based heritage (e.g., Ruby
|
||||
* include/extend/prepend). Produced by createHeritageExtractor() with a
|
||||
* per-language HeritageExtractionConfig. Default: undefined (inline fallback). */
|
||||
readonly heritageExtractor?: HeritageExtractor;
|
||||
/** Extract a semantic description for a definition node (e.g., PHP Eloquent
|
||||
* property arrays, relation method descriptions).
|
||||
* Default: undefined (no description extraction). */
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ import { createVariableExtractor } from '../variable-extractors/generic.js';
|
|||
import { cVariableConfig, cppVariableConfig } from '../variable-extractors/configs/c-cpp.js';
|
||||
import { createCallExtractor } from '../call-extractors/generic.js';
|
||||
import { cCallConfig, cppCallConfig } from '../call-extractors/configs/c-cpp.js';
|
||||
import { createHeritageExtractor } from '../heritage-extractors/generic.js';
|
||||
import { cHeritageConfig, cppHeritageConfig } from '../heritage-extractors/configs/c-cpp.js';
|
||||
|
||||
const C_BUILT_INS: ReadonlySet<string> = new Set([
|
||||
'printf',
|
||||
|
|
@ -329,6 +331,7 @@ export const cProvider = defineLanguage({
|
|||
}),
|
||||
variableExtractor: createVariableExtractor(cVariableConfig),
|
||||
classExtractor: cClassExtractor,
|
||||
heritageExtractor: createHeritageExtractor(cHeritageConfig),
|
||||
labelOverride: cppLabelOverride,
|
||||
builtInNames: C_BUILT_INS,
|
||||
});
|
||||
|
|
@ -350,6 +353,7 @@ export const cppProvider = defineLanguage({
|
|||
}),
|
||||
variableExtractor: createVariableExtractor(cppVariableConfig),
|
||||
classExtractor: cppClassExtractor,
|
||||
heritageExtractor: createHeritageExtractor(cppHeritageConfig),
|
||||
labelOverride: cppLabelOverride,
|
||||
builtInNames: C_BUILT_INS,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ import { createMethodExtractor } from '../method-extractors/generic.js';
|
|||
import { csharpMethodConfig } from '../method-extractors/configs/csharp.js';
|
||||
import { createVariableExtractor } from '../variable-extractors/generic.js';
|
||||
import { csharpVariableConfig } from '../variable-extractors/configs/csharp.js';
|
||||
import { createHeritageExtractor } from '../heritage-extractors/generic.js';
|
||||
import { csharpHeritageConfig } from '../heritage-extractors/configs/csharp.js';
|
||||
|
||||
const BUILT_INS: ReadonlySet<string> = new Set([
|
||||
'Console',
|
||||
|
|
@ -135,5 +137,6 @@ export const csharpProvider = defineLanguage({
|
|||
methodExtractor: createMethodExtractor(csharpMethodConfig),
|
||||
variableExtractor: createVariableExtractor(csharpVariableConfig),
|
||||
classExtractor: createClassExtractor(csharpClassConfig),
|
||||
heritageExtractor: createHeritageExtractor(csharpHeritageConfig),
|
||||
builtInNames: BUILT_INS,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ import { createVariableExtractor } from '../variable-extractors/generic.js';
|
|||
import { dartVariableConfig } from '../variable-extractors/configs/dart.js';
|
||||
import { createCallExtractor } from '../call-extractors/generic.js';
|
||||
import { dartCallConfig } from '../call-extractors/configs/dart.js';
|
||||
import { createHeritageExtractor } from '../heritage-extractors/generic.js';
|
||||
import { dartHeritageConfig } from '../heritage-extractors/configs/dart.js';
|
||||
|
||||
/**
|
||||
* Resolve the enclosing function from a `function_body` node by looking at its
|
||||
|
|
@ -102,6 +104,7 @@ export const dartProvider = defineLanguage({
|
|||
methodExtractor: createMethodExtractor(dartMethodConfig),
|
||||
variableExtractor: createVariableExtractor(dartVariableConfig),
|
||||
classExtractor: createClassExtractor(dartClassConfig),
|
||||
heritageExtractor: createHeritageExtractor(dartHeritageConfig),
|
||||
enclosingFunctionFinder: dartEnclosingFunctionFinder,
|
||||
builtInNames: BUILT_INS,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ import { createVariableExtractor } from '../variable-extractors/generic.js';
|
|||
import { goVariableConfig } from '../variable-extractors/configs/go.js';
|
||||
import { createCallExtractor } from '../call-extractors/generic.js';
|
||||
import { goCallConfig } from '../call-extractors/configs/go.js';
|
||||
import { createHeritageExtractor } from '../heritage-extractors/generic.js';
|
||||
import { goHeritageConfig } from '../heritage-extractors/configs/go.js';
|
||||
|
||||
export const goProvider = defineLanguage({
|
||||
id: SupportedLanguages.Go,
|
||||
|
|
@ -40,4 +42,5 @@ export const goProvider = defineLanguage({
|
|||
methodExtractor: createMethodExtractor(goMethodConfig),
|
||||
variableExtractor: createVariableExtractor(goVariableConfig),
|
||||
classExtractor: createClassExtractor(goClassConfig),
|
||||
heritageExtractor: createHeritageExtractor(goHeritageConfig),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ import { createMethodExtractor } from '../method-extractors/generic.js';
|
|||
import { javaMethodConfig } from '../method-extractors/configs/jvm.js';
|
||||
import { createVariableExtractor } from '../variable-extractors/generic.js';
|
||||
import { javaVariableConfig } from '../variable-extractors/configs/jvm.js';
|
||||
import { createHeritageExtractor } from '../heritage-extractors/generic.js';
|
||||
import { javaHeritageConfig } from '../heritage-extractors/configs/jvm.js';
|
||||
|
||||
export const javaProvider = defineLanguage({
|
||||
id: SupportedLanguages.Java,
|
||||
|
|
@ -41,4 +43,5 @@ export const javaProvider = defineLanguage({
|
|||
methodExtractor: createMethodExtractor(javaMethodConfig),
|
||||
variableExtractor: createVariableExtractor(javaVariableConfig),
|
||||
classExtractor: createClassExtractor(javaClassConfig),
|
||||
heritageExtractor: createHeritageExtractor(javaHeritageConfig),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ import { createMethodExtractor } from '../method-extractors/generic.js';
|
|||
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 { kotlinHeritageConfig } from '../heritage-extractors/configs/jvm.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.
|
||||
|
|
@ -116,6 +118,7 @@ export const kotlinProvider = defineLanguage({
|
|||
methodExtractor: createMethodExtractor(kotlinMethodConfig),
|
||||
variableExtractor: createVariableExtractor(kotlinVariableConfig),
|
||||
classExtractor: createClassExtractor(kotlinClassConfig),
|
||||
heritageExtractor: createHeritageExtractor(kotlinHeritageConfig),
|
||||
builtInNames: BUILT_INS,
|
||||
labelOverride: (functionNode, defaultLabel) => {
|
||||
if (defaultLabel !== 'Function') return defaultLabel;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ import { createVariableExtractor } from '../variable-extractors/generic.js';
|
|||
import { phpVariableConfig } from '../variable-extractors/configs/php.js';
|
||||
import { createCallExtractor } from '../call-extractors/generic.js';
|
||||
import { phpCallConfig } from '../call-extractors/configs/php.js';
|
||||
import { createHeritageExtractor } from '../heritage-extractors/generic.js';
|
||||
import { phpHeritageConfig } from '../heritage-extractors/configs/php.js';
|
||||
|
||||
const BUILT_INS: ReadonlySet<string> = new Set([
|
||||
'echo',
|
||||
|
|
@ -248,6 +250,7 @@ export const phpProvider = defineLanguage({
|
|||
methodExtractor: createMethodExtractor(phpMethodConfig),
|
||||
variableExtractor: createVariableExtractor(phpVariableConfig),
|
||||
classExtractor: createClassExtractor(phpClassConfig),
|
||||
heritageExtractor: createHeritageExtractor(phpHeritageConfig),
|
||||
descriptionExtractor: phpDescriptionExtractor,
|
||||
isRouteFile: isPhpRouteFile,
|
||||
builtInNames: BUILT_INS,
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ import { createVariableExtractor } from '../variable-extractors/generic.js';
|
|||
import { pythonVariableConfig } from '../variable-extractors/configs/python.js';
|
||||
import { createCallExtractor } from '../call-extractors/generic.js';
|
||||
import { pythonCallConfig } from '../call-extractors/configs/python.js';
|
||||
import { createHeritageExtractor } from '../heritage-extractors/generic.js';
|
||||
import { pythonHeritageConfig } from '../heritage-extractors/configs/python.js';
|
||||
|
||||
const BUILT_INS: ReadonlySet<string> = new Set([
|
||||
'print',
|
||||
|
|
@ -74,5 +76,6 @@ export const pythonProvider = defineLanguage({
|
|||
methodExtractor: createMethodExtractor(pythonMethodConfig),
|
||||
variableExtractor: createVariableExtractor(pythonVariableConfig),
|
||||
classExtractor: createClassExtractor(pythonClassConfig),
|
||||
heritageExtractor: createHeritageExtractor(pythonHeritageConfig),
|
||||
builtInNames: BUILT_INS,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ import { createVariableExtractor } from '../variable-extractors/generic.js';
|
|||
import { rubyVariableConfig } from '../variable-extractors/configs/ruby.js';
|
||||
import { createCallExtractor } from '../call-extractors/generic.js';
|
||||
import { rubyCallConfig } from '../call-extractors/configs/ruby.js';
|
||||
import { createHeritageExtractor } from '../heritage-extractors/generic.js';
|
||||
import { rubyHeritageConfig } from '../heritage-extractors/configs/ruby.js';
|
||||
|
||||
/** Ruby method/singleton_method: extract name from 'name' field, label as Method. */
|
||||
const rubyExtractFunctionName = (
|
||||
|
|
@ -137,5 +139,6 @@ export const rubyProvider = defineLanguage({
|
|||
}),
|
||||
variableExtractor: createVariableExtractor(rubyVariableConfig),
|
||||
classExtractor: createClassExtractor(rubyClassConfig),
|
||||
heritageExtractor: createHeritageExtractor(rubyHeritageConfig),
|
||||
builtInNames: BUILT_INS,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ import { createVariableExtractor } from '../variable-extractors/generic.js';
|
|||
import { rustVariableConfig } from '../variable-extractors/configs/rust.js';
|
||||
import { createCallExtractor } from '../call-extractors/generic.js';
|
||||
import { rustCallConfig } from '../call-extractors/configs/rust.js';
|
||||
import { createHeritageExtractor } from '../heritage-extractors/generic.js';
|
||||
import { rustHeritageConfig } from '../heritage-extractors/configs/rust.js';
|
||||
|
||||
/** Rust impl_item: find the function_item child and extract its name as a Method. */
|
||||
const rustExtractFunctionName = (
|
||||
|
|
@ -134,5 +136,6 @@ export const rustProvider = defineLanguage({
|
|||
}),
|
||||
variableExtractor: createVariableExtractor(rustVariableConfig),
|
||||
classExtractor: createClassExtractor(rustClassConfig),
|
||||
heritageExtractor: createHeritageExtractor(rustHeritageConfig),
|
||||
builtInNames: BUILT_INS,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ import { createVariableExtractor } from '../variable-extractors/generic.js';
|
|||
import { swiftVariableConfig } from '../variable-extractors/configs/swift.js';
|
||||
import { createCallExtractor } from '../call-extractors/generic.js';
|
||||
import { swiftCallConfig } from '../call-extractors/configs/swift.js';
|
||||
import { createHeritageExtractor } from '../heritage-extractors/generic.js';
|
||||
import { swiftHeritageConfig } from '../heritage-extractors/configs/swift.js';
|
||||
|
||||
/**
|
||||
* Group Swift files by SPM target for implicit module visibility.
|
||||
|
|
@ -254,6 +256,7 @@ export const swiftProvider = defineLanguage({
|
|||
}),
|
||||
variableExtractor: createVariableExtractor(swiftVariableConfig),
|
||||
classExtractor: createClassExtractor(swiftClassConfig),
|
||||
heritageExtractor: createHeritageExtractor(swiftHeritageConfig),
|
||||
implicitImportWirer: wireSwiftImplicitImports,
|
||||
builtInNames: BUILT_INS,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -43,6 +43,11 @@ import {
|
|||
typescriptCallConfig,
|
||||
javascriptCallConfig,
|
||||
} from '../call-extractors/configs/typescript-javascript.js';
|
||||
import { createHeritageExtractor } from '../heritage-extractors/generic.js';
|
||||
import {
|
||||
typescriptHeritageConfig,
|
||||
javascriptHeritageConfig,
|
||||
} from '../heritage-extractors/configs/typescript-javascript.js';
|
||||
|
||||
/**
|
||||
* TypeScript/JavaScript: arrow_function and function_expression get their name
|
||||
|
|
@ -182,6 +187,7 @@ export const typescriptProvider = defineLanguage({
|
|||
}),
|
||||
variableExtractor: createVariableExtractor(typescriptVariableConfig),
|
||||
classExtractor: createClassExtractor(typescriptClassConfig),
|
||||
heritageExtractor: createHeritageExtractor(typescriptHeritageConfig),
|
||||
builtInNames: BUILT_INS,
|
||||
});
|
||||
|
||||
|
|
@ -201,5 +207,6 @@ export const javascriptProvider = defineLanguage({
|
|||
}),
|
||||
variableExtractor: createVariableExtractor(javascriptVariableConfig),
|
||||
classExtractor: createClassExtractor(javascriptClassConfig),
|
||||
heritageExtractor: createHeritageExtractor(javascriptHeritageConfig),
|
||||
builtInNames: BUILT_INS,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ import { createVariableExtractor } from '../variable-extractors/generic.js';
|
|||
import { typescriptVariableConfig } from '../variable-extractors/configs/typescript-javascript.js';
|
||||
import { createCallExtractor } from '../call-extractors/generic.js';
|
||||
import { typescriptCallConfig } from '../call-extractors/configs/typescript-javascript.js';
|
||||
import { createHeritageExtractor } from '../heritage-extractors/generic.js';
|
||||
import { typescriptHeritageConfig } from '../heritage-extractors/configs/typescript-javascript.js';
|
||||
|
||||
const VUE_SPECIFIC_BUILT_INS = [
|
||||
'ref',
|
||||
|
|
@ -76,5 +78,6 @@ export const vueProvider = defineLanguage({
|
|||
fieldExtractor: typescriptFieldExtractor,
|
||||
variableExtractor: createVariableExtractor(typescriptVariableConfig),
|
||||
classExtractor: vueClassExtractor,
|
||||
heritageExtractor: createHeritageExtractor(typescriptHeritageConfig),
|
||||
builtInNames: VUE_BUILT_INS,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1699,6 +1699,26 @@ const processFileGroup = (
|
|||
if (callNameNode) {
|
||||
const calledName = callNameNode.text;
|
||||
|
||||
// Check heritage extractor for call-based heritage (e.g., Ruby include/extend/prepend)
|
||||
if (provider.heritageExtractor?.extractFromCall) {
|
||||
const heritageItems = provider.heritageExtractor.extractFromCall(
|
||||
calledName,
|
||||
captureMap['call']!,
|
||||
{ filePath: file.path, language },
|
||||
);
|
||||
if (heritageItems && heritageItems.length > 0) {
|
||||
for (const item of heritageItems) {
|
||||
result.heritage.push({
|
||||
filePath: file.path,
|
||||
className: item.className,
|
||||
parentName: item.parentName,
|
||||
kind: item.kind,
|
||||
});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Dispatch: route language-specific calls (heritage, properties, imports)
|
||||
const routed = callRouter?.(calledName, captureMap['call']);
|
||||
if (routed) {
|
||||
|
|
@ -1878,40 +1898,24 @@ const processFileGroup = (
|
|||
continue;
|
||||
}
|
||||
|
||||
// Extract heritage (extends/implements)
|
||||
// Extract heritage (extends/implements) via provider heritage extractor
|
||||
if (captureMap['heritage.class']) {
|
||||
if (captureMap['heritage.extends']) {
|
||||
// Go struct embedding: the query matches ALL field_declarations with
|
||||
// type_identifier, but only anonymous fields (no name) are embedded.
|
||||
// Named fields like `Breed string` also match — skip them.
|
||||
const extendsNode = captureMap['heritage.extends'];
|
||||
const fieldDecl = extendsNode.parent;
|
||||
const isNamedField =
|
||||
fieldDecl?.type === 'field_declaration' && fieldDecl.childForFieldName('name');
|
||||
if (!isNamedField) {
|
||||
if (provider.heritageExtractor) {
|
||||
const heritageItems = provider.heritageExtractor.extract(captureMap, {
|
||||
filePath: file.path,
|
||||
language,
|
||||
});
|
||||
for (const item of heritageItems) {
|
||||
result.heritage.push({
|
||||
filePath: file.path,
|
||||
className: captureMap['heritage.class'].text,
|
||||
parentName: captureMap['heritage.extends'].text,
|
||||
kind: 'extends',
|
||||
className: item.className,
|
||||
parentName: item.parentName,
|
||||
kind: item.kind,
|
||||
});
|
||||
}
|
||||
}
|
||||
if (captureMap['heritage.implements']) {
|
||||
result.heritage.push({
|
||||
filePath: file.path,
|
||||
className: captureMap['heritage.class'].text,
|
||||
parentName: captureMap['heritage.implements'].text,
|
||||
kind: 'implements',
|
||||
});
|
||||
}
|
||||
if (captureMap['heritage.trait']) {
|
||||
result.heritage.push({
|
||||
filePath: file.path,
|
||||
className: captureMap['heritage.class'].text,
|
||||
parentName: captureMap['heritage.trait'].text,
|
||||
kind: 'trait-impl',
|
||||
});
|
||||
if (heritageItems.length > 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (
|
||||
captureMap['heritage.extends'] ||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue