GitNexus/docs/code-indexing/cobol/graph-model.md
Gergo Magyar 4af677e637 feat: add COBOL language support with regex extraction pipeline
Standalone COBOL processor following the markdown-processor.ts pattern:
- No LanguageProvider modification — COBOL uses regex, not tree-sitter
- No SupportedLanguages enum change — standalone processor pattern

New files:
- cobol-processor.ts — orchestrator (processCobol, isCobolFile, isJclFile)
- cobol/cobol-preprocessor.ts — regex state machine extraction (~888 LOC)
- cobol/cobol-copy-expander.ts — COPY statement expansion with circular detection
- cobol/jcl-parser.ts — JCL job/step/DD extraction
- cobol/jcl-processor.ts — JCL graph node creation

Extraction produces:
- Module nodes (PROGRAM-ID)
- Function nodes (paragraphs)
- Namespace nodes (sections)
- Property nodes (data items)
- CALLS edges (PERFORM intra-file, CALL cross-program)
- IMPORTS edges (COPY statements)
- CONTAINS edges (section → paragraph hierarchy)

Pipeline integration: single processCobol() call in Phase 2.6

54 new tests (33 COBOL + 21 JCL), all 3889 tests pass.
2026-03-24 14:39:25 +00:00

8.8 KiB

COBOL Graph Model

This document describes the graph nodes and edges that GitNexus creates for COBOL codebases. The COBOL graph model is richer than most tree-sitter languages because it captures domain-specific constructs: file declarations, FD entries, data hierarchies, SQL tables, CICS maps, and cross-program contracts.

Entity-Relationship Diagram

erDiagram
    File ||--o{ Module : DEFINES
    File ||--o{ Function : DEFINES
    File ||--o{ Namespace : DEFINES
    File ||--o{ Record : DEFINES
    File ||--o{ Property : DEFINES
    File ||--o{ Const : DEFINES
    File ||--o{ CodeElement : DEFINES
    File ||--o{ Constructor : DEFINES
    File }o--o{ File : IMPORTS

    Module ||--o{ Record : CONTAINS
    Module ||--o{ Constructor : CONTAINS
    Module }o--o{ CodeElement : ACCESSES
    Module }o--o{ Module : CALLS
    Module }o--o{ Module : CONTRACTS
    Module }o--o{ Property : RECEIVES

    Record ||--o{ Property : CONTAINS
    Record ||--o{ Const : CONTAINS
    Record }o--o{ Record : REDEFINES

    Property ||--o{ Property : CONTAINS
    Property ||--o{ Const : CONTAINS
    Property }o--o{ Property : REDEFINES
    Property }o--o{ CodeElement : RECORD_KEY_OF
    Property }o--o{ CodeElement : FILE_STATUS_OF

    CodeElement ||--o{ CodeElement : CONTAINS
    CodeElement ||--o{ Record : CONTAINS

    Function }o--o{ Function : CALLS

Node Types

Node Type COBOL Concept Created From Example
Module PROGRAM-ID PROGRAM-ID. BGTABFL Name: BGTABFL, description may include author and date
Function Paragraph PROCESS-RECORD. at column 8 Name: PROCESS-RECORD
Namespace Procedure section MAIN-LOGIC SECTION. at column 8 Name: MAIN-LOGIC
Record 01-level data item 01 WK-EMPLOYEE. Description: level:01 section:working-storage
Property 02-49/66/77 data item 05 WK-NAME PIC X(30). Description: level:05 pic:X(30) section:working-storage
Const 88-level condition 88 WK-ACTIVE VALUE "A". Description: level:88 values:A
CodeElement SELECT, FD, SQL table, CICS map, cursor, transid Various Description varies by subtype
Constructor ENTRY point ENTRY "SUBPROG" USING WK-DATA Description: entry params:WK-DATA

CodeElement Subtypes

CodeElement is used for multiple COBOL constructs, distinguished by their description prefix:

Subtype ID Pattern Description Format Example
File SELECT CodeElement:{path}:SELECT:{name} select org:INDEXED access:DYNAMIC ... SELECT MASTER-FILE
FD entry CodeElement:{path}:FD:{name} fd record:{recordName} FD MASTER-FILE
SQL table CodeElement:{path}:sql-table:{name} sql-table op:SELECT Table EMPLOYEES
SQL cursor CodeElement:{path}:sql-cursor:{name} sql-cursor Cursor C-EMPLOYEES
CICS map CodeElement:{path}:cics-map:{name} cics-map cmd:SEND MAP Map EMPMENU
CICS transid CodeElement:{path}:cics-transid:{name} cics-transid cmd:START Transid EMP1

Edge Types

Edge Type Source Target Created By Confidence Example
DEFINES File any node File defines its symbols 1.0 File -> Module BGTABFL
CALLS Function Function PERFORM X [THRU Y] (via call-processor) PROCESS-RECORD -> CALC-TAX
CALLS Module Module CALL "BGTABUP" (via call-processor) BGTABFL -> BGTABUP
CALLS Module Module EXEC CICS LINK PROGRAM('X') (via call-processor) BGTABFL -> BGTABUP
IMPORTS File File COPY copybook (via import-processor) Source file -> Copybook file
CONTAINS Module Record Data hierarchy root 1.0 BGTABFL -> WK-EMPLOYEE
CONTAINS Record Property Data hierarchy 1.0 WK-EMPLOYEE -> WK-NAME
CONTAINS Property Property Nested data items 1.0 WK-ADDRESS -> WK-CITY
CONTAINS Record/Property Const 88-level parent 1.0 WK-STATUS -> WK-ACTIVE
CONTAINS CodeElement (FD) Record FD record link 1.0 FD:MASTER-FILE -> MASTER-RECORD
CONTAINS CodeElement (SELECT) CodeElement (FD) SELECT-FD link 0.9 SELECT:MASTER-FILE -> FD:MASTER-FILE
CONTAINS Module Constructor ENTRY in module 1.0 BGTABFL -> SUBPROG
REDEFINES Record Record 01 X REDEFINES Y 1.0 WK-DATE-NUM -> WK-DATE-ALPHA
REDEFINES Property Property 05 X REDEFINES Y 1.0 WK-CODE-NUM -> WK-CODE-ALPHA
RECORD_KEY_OF Property CodeElement (SELECT) RECORD KEY IS field 0.8 WK-EMP-ID -> SELECT:MASTER-FILE
FILE_STATUS_OF Property CodeElement (SELECT) FILE STATUS IS field 0.8 WK-FS -> SELECT:MASTER-FILE
ACCESSES Module CodeElement EXEC SQL/CICS 0.9 BGTABFL -> sql-table:EMPLOYEES
RECEIVES Module Property PROCEDURE USING 0.8 BGTABFL -> WK-INPUT-REC
CONTRACTS Module Module Shared copybook detection 0.9 BGTABFL -> BGTABUP (via CPSESP)

Full Annotated Example

Given this COBOL program:

       IDENTIFICATION DIVISION.
       PROGRAM-ID. EMPMAINT.
       AUTHOR. Development Team.

       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT EMP-FILE
               ASSIGN TO "EMPLOYEE.DAT"
               ORGANIZATION IS INDEXED
               ACCESS MODE IS DYNAMIC
               RECORD KEY IS EMP-ID
               FILE STATUS IS WS-FILE-STATUS.

       DATA DIVISION.
       FILE SECTION.
       FD  EMP-FILE.
       01  EMP-RECORD.
           05  EMP-ID             PIC 9(6).
           05  EMP-NAME           PIC X(30).

       WORKING-STORAGE SECTION.
       01  WS-FLAGS.
           05  WS-FILE-STATUS     PIC X(02).
           05  WS-EOF-FLAG        PIC X(01).
               88  WS-EOF         VALUE "Y".

       LINKAGE SECTION.
       01  LK-SEARCH-KEY          PIC 9(6).

       PROCEDURE DIVISION USING LK-SEARCH-KEY.
       MAIN-LOGIC SECTION.
       MAIN-START.
           PERFORM OPEN-FILE
           PERFORM PROCESS-RECORDS
           PERFORM CLOSE-FILE
           STOP RUN.

       OPEN-FILE.
           OPEN I-O EMP-FILE.

       PROCESS-RECORDS.
           MOVE LK-SEARCH-KEY TO EMP-ID
           EXEC SQL
               SELECT EMP_SALARY INTO :WS-SALARY
               FROM EMPLOYEES
               WHERE EMP_ID = :EMP-ID
           END-EXEC
           CALL "EMPREPORT".

       CLOSE-FILE.
           CLOSE EMP-FILE.

The graph produced contains:

Nodes:

  • Module: EMPMAINT (description: author:Development Team)
  • Namespace: MAIN-LOGIC
  • Function: MAIN-START, OPEN-FILE, PROCESS-RECORDS, CLOSE-FILE
  • Record: EMP-RECORD, WS-FLAGS, LK-SEARCH-KEY
  • Property: EMP-ID, EMP-NAME, WS-FILE-STATUS, WS-EOF-FLAG
  • Const: WS-EOF (values: Y)
  • CodeElement: SELECT:EMP-FILE, FD:EMP-FILE, sql-table:EMPLOYEES
  • (COPY imports, if any, would produce File IMPORTS edges)

Edges:

  • DEFINES: File -> all nodes
  • CONTAINS: EMPMAINT -> EMP-RECORD, EMPMAINT -> WS-FLAGS, EMPMAINT -> LK-SEARCH-KEY
  • CONTAINS: EMP-RECORD -> EMP-ID, EMP-RECORD -> EMP-NAME
  • CONTAINS: WS-FLAGS -> WS-FILE-STATUS, WS-FLAGS -> WS-EOF-FLAG
  • CONTAINS: WS-EOF-FLAG -> WS-EOF
  • CONTAINS: FD:EMP-FILE -> EMP-RECORD
  • CONTAINS: SELECT:EMP-FILE -> FD:EMP-FILE
  • CALLS: MAIN-START -> OPEN-FILE, MAIN-START -> PROCESS-RECORDS, MAIN-START -> CLOSE-FILE
  • CALLS: EMPMAINT -> EMPREPORT (external CALL)
  • ACCESSES: EMPMAINT -> sql-table:EMPLOYEES
  • RECEIVES: EMPMAINT -> LK-SEARCH-KEY (PROCEDURE USING)
  • RECORD_KEY_OF: EMP-ID -> SELECT:EMP-FILE
  • FILE_STATUS_OF: WS-FILE-STATUS -> SELECT:EMP-FILE

How COBOL Differs from Tree-Sitter Languages

Aspect COBOL Tree-Sitter Languages
Node variety 8 types (Module, Function, Namespace, Record, Property, Const, CodeElement, Constructor) Typically 4-6 (Function, Class, Method, Interface, Module, Const)
Domain edges RECORD_KEY_OF, FILE_STATUS_OF, ACCESSES, RECEIVES, CONTRACTS, REDEFINES Primarily CALLS, IMPORTS, EXTENDS, IMPLEMENTS
Data hierarchy Deep CONTAINS chains (01 -> 05 -> 10 -> 88) Flat class members
Cross-program calls CALL "name" + CICS LINK PROGRAM Import-based resolution
Contract detection Shared COPY copybook between caller/callee Not applicable
Metadata AUTHOR, DATE-WRITTEN on Module JSDoc/docstring (not indexed)

Source Files

  • gitnexus/src/core/ingestion/workers/parse-worker.ts -- processCobolRegexOnly(), node/edge emission logic
  • gitnexus/src/core/ingestion/pipeline.ts -- detectCrossProgamContracts() for CONTRACTS edges
  • gitnexus/src/core/ingestion/cobol-preprocessor.ts -- CobolRegexResults interface (all extracted data)