Delphi concept

This commit is contained in:
Olaf Monien
2026-02-10 23:55:42 +01:00
parent adaff67219
commit 645fd71e45
12 changed files with 529 additions and 0 deletions
+72
View File
@@ -0,0 +1,72 @@
# Implementation Plan: Pascal/Delphi in CodeGraph
## 0) Prämissen
- CodeGraph extrahiert **Nodes** und **Edges** über **tree-sitter** und language-spezifische **Queries (`.scm`)**.
- Danach folgt **Reference Resolution** (Calls → Definitionen, imports → Dateien, inheritance, framework patterns).
## 1) Parser / Grammar
Empfohlen: `tree-sitter-pascal` (unterstützt Delphi + FreePascal).
**Tasks:**
- Dependency hinzufügen (wie bei bestehenden Sprachen).
- Language-Loader/Registry erweitern: `languageId = "pascal"` (oder `"delphi"`, aber konsistent).
## 2) File-Erkennung
Extensions (MVP):
- `.pas` (Units)
- `.dpr` (Program)
- `.dpk` (Package)
- `.lpr` (Lazarus Program)
Optional:
- `.inc` (Include-Fragmente) erst später oder nur, wenn Parser tolerant genug ist.
## 3) Queries (MVP)
### 3.1 Nodes
Extrahiere mindestens:
- Unit/Program/Package Name
- Klassen / Interfaces / Records
- Procedures/Functions
- Methoden (class/instance)
### 3.2 Edges
Extrahiere mindestens:
- `uses` (import/dependency)
- `extends` (Basisklasse)
- `implements` (Interface-Implementierungen)
- `calls` (Identifier + optional Qualifier)
## 4) Reference Resolution (MVP)
### 4.1 Unit-Auflösung (`uses`)
- Index-Phase: Map `UnitName -> fileId` (aus Units/Programs/Packages)
- Resolution: Bei `uses Foo, Bar;` Edges auf Ziel-Units setzen.
- Spezialfälle (später): `Foo in 'path\Foo.pas'` (DPR/DPK), Namespaces (`System.SysUtils`).
### 4.2 Call-Auflösung (best effort)
- Extraktion: `callName`, optional `qualifier` (`Obj.DoIt`, `TMyClass.DoIt`)
- Heuristik-Reihenfolge:
1. lokale Procs/Funcs in der gleichen Unit
2. Methoden in der gleichen Klasse
3. Units aus `uses`
4. globaler Fallback nach Name
## 5) Tests
- Fixtures aus `fixtures/` in die Test-Suite aufnehmen
- Assertions:
- Node-Anzahl + zentrale Namen
- `uses`-Edges
- `extends`/`implements`-Edges
- einfache Call-Edges
## 6) Definition of Done
- `codegraph index` indexiert Delphi/ Pascal-Dateien ohne Crash
- `codegraph_search` findet Klassen/Methoden
- `codegraph_callers/callees` liefert sinnvolle Ergebnisse für einfache Fälle
- `uses`-Graph stimmt (Unit-Abhängigkeiten)
+53
View File
@@ -0,0 +1,53 @@
# Capture Convention (wie die `.scm` Queries an CodeGraph andocken)
Da wir hier nur ein ZIP-Konzept liefern (ohne den CodeGraph-Source lokal auszulesen), ist das wichtigste: **du musst die Captures so benennen, wie CodeGraph sie in den bestehenden Sprachen bereits erwartet**.
## Vorgehen
1. Öffne im CodeGraph-Repo eine bestehende Sprache (z.B. Go/Rust/Java).
2. Suche nach `.scm` Dateien und schaue:
- welche Capture-Namen verwendet werden
- wie Node-Kind/Edge-Kind gesetzt werden (oft via `#set!`)
3. Übertrage exakt dieses Schema auf Pascal.
## Empfohlene semantische Einteilung
Unabhängig von den konkreten Capture-Namen sollte jedes Query-Match folgende Informationen liefern:
### Für Nodes
- **kind**: `unit | program | package | class | interface | record | function | procedure | method | property | field | type | enum | variable`
- **name**: Symbolname
- **container** (optional): z.B. Klassenname für Methoden
- **signature** (optional): Parameter/Returntype, falls leicht verfügbar
- **range**: Start/Ende im File (Line/Column)
### Für Edges
- **kind**: `imports | calls | extends | implements | contains | returns_type`
- **from**: Node-ID der Quelle (oder "current scope")
- **to**: Zielsymbol (Name) oder Ziel-Node-ID, wenn schon auflösbar
- **raw**: Originaltext (hilft Resolvern)
## Minimaler Capture-Satz (Pseudo)
> **Wichtig:** Diese Namen sind **Platzhalter**. Bitte auf das CodeGraph-interne Schema mappen.
- `@cg.node` mit Properties:
- `(#set! cg.kind "class")`
- `(#set! cg.name @nameCapture)` oder per separate captures
- `@cg.edge` mit Properties:
- `(#set! cg.kind "calls")`
- Zielsymbol als Capture: `@cg.target`
Wenn CodeGraph statt `#set!` eine feste Capture-Nomenklatur nutzt (z.B. `@definition.function`), dann übernimm exakt diese.
## Delphi-spezifische Stolperfallen
- `procedure Foo;` vs `function Foo: Integer;`
- `class procedure` / `class function`
- `constructor` / `destructor`
- `property` (kann wie Feld wirken, ist aber call-ähnlich)
- `with`-Statements (Call-Qualifier wird verschleiert)
- Namespaces: `System.SysUtils`
Für MVP: **nicht perfekt auflösen**, aber **zuverlässig extrahieren**.
+119
View File
@@ -0,0 +1,119 @@
# Tree-sitter Query Skizzen (Pascal/Delphi)
Diese Skizzen sind bewusst so geschrieben, dass du sie schnell an die **konkreten Node-Namen** von `tree-sitter-pascal` und die **Capture-Konvention** von CodeGraph anpassen kannst.
> Praxis-Tipp: Nutze `tree-sitter parse` bzw. Editor-Tools (z.B. Neovim `:InspectTree`) um die exakten Node-Typen im AST zu sehen.
## A) Nodes
### 1) Unit / Program / Package
- Match: `unit`/`program`/`library`/`package` header
- Extrahiere Name
Skizze:
```scm
; (unit_header name: (identifier) @NAME) @NODE
; (#set! "kind" "unit")
; (program_header name: (identifier) @NAME) @NODE
; (#set! "kind" "program")
```
### 2) Klassen / Interfaces / Records
Skizze:
```scm
; (type_declaration
; (type_definition
; name: (identifier) @TYPE_NAME
; value: (class_type) @CLASS
; )
; )
; (type_definition name: (identifier) @TYPE_NAME value: (interface_type) @IFACE)
; (type_definition name: (identifier) @TYPE_NAME value: (record_type) @REC)
```
### 3) Procs/Funcs (top-level)
```scm
; (procedure_declaration name: (identifier) @NAME) @NODE
; (#set! "kind" "procedure")
; (function_declaration name: (identifier) @NAME) @NODE
; (#set! "kind" "function")
```
### 4) Methoden
Je nach Grammar sind Methoden oft als procedure/function nodes innerhalb eines `class_body` oder `visibility_section` enthalten.
```scm
; (method_declaration name: (identifier) @NAME) @NODE
; (#set! "kind" "method")
; optional: capture class name via ancestor match (wenn CodeGraph das unterstützt)
```
## B) Edges
### 1) uses (imports/dependencies)
```scm
; (uses_clause (qualified_identifier) @UNIT_NAME) @EDGE
; (#set! "kind" "imports")
```
### 2) extends (Basisklasse)
```scm
; (class_type
; base_class: (qualified_identifier) @BASE
; ) @EDGE
; (#set! "kind" "extends")
```
### 3) implements (Interfaces)
```scm
; (class_type
; implements: (interface_list (qualified_identifier) @IFACE)
; ) @EDGE
; (#set! "kind" "implements")
```
### 4) calls (Call-Graph)
Du willst in Delphi mindestens folgende Formen sehen:
- `Foo()`
- `Obj.Foo()`
- `TMyClass.Foo()`
Skizze:
```scm
; (call_expression
; function: (identifier) @CALLEE
; ) @EDGE
; (#set! "kind" "calls")
; (call_expression
; function: (qualified_identifier
; qualifier: (identifier) @QUAL
; name: (identifier) @CALLEE)
; ) @EDGE
; (#set! "kind" "calls")
```
## C) MVP: „Contains“-Edges
Optional, aber oft sehr nützlich: Datei/Unit enthält Klassen/Procs.
```scm
; (type_definition name: (identifier) @CHILD) @EDGE
; (#set! "kind" "contains")
```
Das ist abhängig davon, wie CodeGraph containment modelliert.
+32
View File
@@ -0,0 +1,32 @@
# Checklist: Pascal/Delphi Support in CodeGraph
## A) Plumbing
- [ ] tree-sitter grammar dependency (Pascal)
- [ ] Language registry: `pascal` hinzufügen
- [ ] Extension mapping: `.pas .dpr .dpk .lpr` (optional `.inc`)
- [ ] Queries laden (nodes + edges)
## B) Extraction
- [ ] Unit/Program/Package Nodes
- [ ] Class/Interface/Record Nodes
- [ ] Procedure/Function Nodes
- [ ] Method Nodes
- [ ] uses -> imports edges
- [ ] extends edges
- [ ] implements edges
- [ ] calls edges (best-effort)
## C) Resolution
- [ ] unitName -> file/node mapping
- [ ] resolve `uses X;` to unit node
- [ ] resolve `X in 'path'` (DPR/DPK) (Phase 2)
- [ ] call resolution baseline (same file + class)
## D) Testing
- [ ] add fixtures to tests
- [ ] assert extracted nodes
- [ ] assert imports/extends/implements/calls
## E) Polishing
- [ ] expose language in `Supported Languages` docs
- [ ] update CLI help / config validation