From 5b36d04447bf38d102db4e9c3cf8ec3e6eb4b608 Mon Sep 17 00:00:00 2001 From: Oleg Dizus Date: Tue, 24 Mar 2026 14:00:59 +0600 Subject: [PATCH] feat(phase8): add field type data structures and extractor interface --- .../src/core/ingestion/field-extractor.ts | 81 +++++++++++++++++++ gitnexus/src/core/ingestion/field-types.ts | 56 +++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 gitnexus/src/core/ingestion/field-extractor.ts create mode 100644 gitnexus/src/core/ingestion/field-types.ts diff --git a/gitnexus/src/core/ingestion/field-extractor.ts b/gitnexus/src/core/ingestion/field-extractor.ts new file mode 100644 index 000000000..c8f1b87f1 --- /dev/null +++ b/gitnexus/src/core/ingestion/field-extractor.ts @@ -0,0 +1,81 @@ +// gitnexus/src/core/ingestion/field-extractor.ts + +import type { SyntaxNode } from './utils.js'; +import { SupportedLanguages } from '../../config/supported-languages.js'; +import type { + FieldExtractorContext, + ExtractedFields +} from './field-types.js'; + +/** + * Language-specific field extractor + */ +export interface FieldExtractor { + /** Language this extractor handles */ + language: SupportedLanguages; + + /** + * Extract fields from a class/struct/interface declaration + */ + extract(node: SyntaxNode, context: FieldExtractorContext): ExtractedFields | null; + + /** + * Check if this node represents a type declaration with fields + */ + isTypeDeclaration(node: SyntaxNode): boolean; +} + +/** + * Registry of field extractors by language + */ +export class FieldExtractorRegistry { + private extractors = new Map(); + + register(extractor: FieldExtractor): void { + this.extractors.set(extractor.language, extractor); + } + + get(language: SupportedLanguages): FieldExtractor | undefined { + return this.extractors.get(language); + } + + has(language: SupportedLanguages): boolean { + return this.extractors.has(language); + } +} + +/** + * Base class for field extractors with common utilities + */ +export abstract class BaseFieldExtractor implements FieldExtractor { + abstract language: SupportedLanguages; + + abstract extract(node: SyntaxNode, context: FieldExtractorContext): ExtractedFields | null; + abstract isTypeDeclaration(node: SyntaxNode): boolean; + + protected normalizeType(type: string | null): string | null { + if (!type) return null; + return type.trim().replace(/\s+/g, ' '); + } + + protected resolveType(typeName: string, context: FieldExtractorContext): string | null { + const { typeEnv, symbolTable, filePath } = context; + + // Try to find in type environment (check file scope first) + const fileEnv = typeEnv.get(''); + if (fileEnv) { + const local = fileEnv.get(typeName); + if (local) return local; + } + + // Try symbol table lookup in current file + const symbols = symbolTable.lookupExactAll(filePath, typeName); + if (symbols.length === 1) { + return symbols[0].nodeId; + } + + return typeName; + } + + protected abstract extractVisibility(node: SyntaxNode): string; +} diff --git a/gitnexus/src/core/ingestion/field-types.ts b/gitnexus/src/core/ingestion/field-types.ts new file mode 100644 index 000000000..eb6d765c2 --- /dev/null +++ b/gitnexus/src/core/ingestion/field-types.ts @@ -0,0 +1,56 @@ +// gitnexus/src/core/ingestion/field-types.ts + +import type { TypeEnv } from './type-env.js'; +import type { SymbolTable } from './symbol-table.js'; +import { SupportedLanguages } from '../../config/supported-languages.js'; + +/** + * Represents a field or property within a class/struct/interface + */ +export interface FieldInfo { + /** Field name */ + name: string; + /** Resolved type (may be primitive, FQN, or generic) */ + type: string | null; + /** Visibility: public, private, protected, internal */ + visibility: string; + /** Is this a static member? */ + isStatic: boolean; + /** Is this readonly/const? */ + isReadonly: boolean; + /** Source file path */ + sourceFile: string; + /** Line number */ + line: number; +} + +/** + * Maps owner type FQN to its fields + */ +export type FieldTypeMap = Map; + +/** + * Context for field extraction + */ +export interface FieldExtractorContext { + /** Type environment for resolution */ + typeEnv: TypeEnv; + /** Symbol table for FQN lookups */ + symbolTable: SymbolTable; + /** Current file path */ + filePath: string; + /** Language ID */ + language: SupportedLanguages; +} + +/** + * Result of field extraction from a type declaration + */ +export interface ExtractedFields { + /** Owner type FQN */ + ownerFqn: string; + /** Extracted fields */ + fields: FieldInfo[]; + /** Nested types found during extraction */ + nestedTypes: string[]; +}