Explorar el Código

Delphi concept

Olaf Monien hace 4 meses
padre
commit
645fd71e45

+ 72 - 0
Delphi/Docs/01-Implementation-Plan.md

@@ -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 - 0
Delphi/Docs/02-Capture-Convention.md

@@ -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 - 0
Delphi/Docs/03-TreeSitter-Query-Sketches.md

@@ -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 - 0
Delphi/Docs/04-Checklist.md

@@ -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

+ 25 - 0
Delphi/README.md

@@ -0,0 +1,25 @@
+# CodeGraph Pascal/Delphi Support (Fork-Konzept)
+
+Dieses ZIP ist **kein fertiger CodeGraph-Fork**, sondern ein **umsetzbarer Bauplan** inklusive Query-Skizzen, Scaffold-Dateistruktur, Test-Fixtures und einer Checkliste.
+
+Ziel: CodeGraph soll **Pascal/Delphi**-Dateien indexieren und daraus **Nodes** (Units, Klassen, Methoden, …) sowie **Edges** (uses/imports, calls, extends, implements, …) extrahieren.
+
+## Inhalt
+
+- `Docs/` – Konzept, Capture-Konventionen, Implementations-Schritte
+- `Scaffold/` – vorgeschlagene Ordner/Dateien für `src/languages/pascal/` inkl. `.scm` Queries
+- `fixtures/` – kleine Delphi-Beispieldateien zum Testen der Extraktion
+- `resolution/` – Resolver-Heuristiken (Unit-Mapping, Call-Resolution)
+
+## Wie du damit arbeitest
+
+1. **Im CodeGraph-Repo** die bestehende Struktur für eine Sprache ansehen (z.B. `src/languages/go` oder `src/languages/java`).
+2. Dieses ZIP als Vorlage nehmen und **1:1** in deinen Fork übertragen:
+   - `src/languages/pascal/**`
+   - Extension-Mapping (`.pas`, `.dpr`, `.dpk`, `.lpr`, optional `.inc`)
+   - Language-Registry erweitern
+3. Queries (`.scm`) auf die **Capture-Namen** mappen, die CodeGraph intern erwartet.
+4. Resolver erweitern (mindestens `uses` → Unit-File, einfache Call-Auflösung).
+5. Fixtures in die Tests aufnehmen.
+
+> Hinweis: Tree-sitter ist die Grundlage. Für Pascal/Delphi bietet sich `tree-sitter-pascal` an (Delphi + FreePascal). 

+ 15 - 0
Delphi/Scaffold/src/languages/pascal/README.md

@@ -0,0 +1,15 @@
+# Pascal / Delphi Language Module (Scaffold)
+
+Diese Dateien sind als **Startpunkt** für einen CodeGraph-Fork gedacht.
+
+## Strukturvorschlag
+
+- `language.ts` – registriert Parser, Extensions, Query-Files
+- `queries/nodes.scm` – Node-Extraktion
+- `queries/edges.scm` – Edge-Extraktion
+- `queries/comments.scm` (optional) – Docstrings/Kommentare
+
+## Wichtig
+
+Die Capture-Namen in den `.scm` Dateien sind **Platzhalter**.
+Passe sie so an, dass sie zum internen Schema von CodeGraph passen (siehe `Docs/02-Capture-Convention.md`).

+ 29 - 0
Delphi/Scaffold/src/languages/pascal/language.ts

@@ -0,0 +1,29 @@
+/**
+ * Pascal / Delphi language registration scaffold for CodeGraph.
+ *
+ * NOTE: This is intentionally pseudo-code / a template.
+ * You must adapt it to the actual CodeGraph codebase structure.
+ */
+
+export const pascalLanguage = {
+  id: 'pascal',
+  displayName: 'Pascal / Delphi',
+
+  // MVP extensions
+  extensions: ['.pas', '.dpr', '.dpk', '.lpr'],
+
+  // Suggested tree-sitter grammar package name (verify in your fork)
+  // parser: require('tree-sitter-pascal'),
+
+  // Queries used by the extractor
+  queries: {
+    nodes: __dirname + '/queries/nodes.scm',
+    edges: __dirname + '/queries/edges.scm',
+    // comments: __dirname + '/queries/comments.scm',
+  },
+
+  // Optional language-specific settings
+  options: {
+    // includeFiles: ['**/*.inc'] // only if you decide to support includes
+  }
+};

+ 38 - 0
Delphi/Scaffold/src/languages/pascal/queries/edges.scm

@@ -0,0 +1,38 @@
+; Pascal/Delphi edge extraction queries (SCAFFOLD)
+; -----------------------------------------------
+; IMPORTANT: Replace capture names with the exact ones CodeGraph expects.
+
+; === uses (imports) ===
+
+; (uses_clause (qualified_identifier) @cg.target) @cg.edge
+; (#set! cg.kind "imports")
+
+
+; === class inheritance ===
+
+; (class_type
+;   base_class: (qualified_identifier) @cg.target
+; ) @cg.edge
+; (#set! cg.kind "extends")
+
+
+; === implements interfaces ===
+
+; (class_type
+;   implements: (interface_list (qualified_identifier) @cg.target)
+; ) @cg.edge
+; (#set! cg.kind "implements")
+
+
+; === call graph (best-effort) ===
+
+; (call_expression function: (identifier) @cg.target) @cg.edge
+; (#set! cg.kind "calls")
+
+; Qualified calls: Obj.Foo(), TMyClass.Bar()
+; (call_expression
+;   function: (qualified_identifier
+;              qualifier: (identifier) @cg.qualifier
+;              name: (identifier) @cg.target)
+; ) @cg.edge
+; (#set! cg.kind "calls")

+ 61 - 0
Delphi/Scaffold/src/languages/pascal/queries/nodes.scm

@@ -0,0 +1,61 @@
+; Pascal/Delphi node extraction queries (SCAFFOLD)
+; -------------------------------------------------
+; IMPORTANT: Replace capture names with the exact ones CodeGraph expects.
+; Use existing languages as reference.
+
+; === Unit / Program / Library / Package ===
+
+; (unit_header name: (identifier) @cg.name) @cg.node
+; (#set! cg.kind "unit")
+
+; (program_header name: (identifier) @cg.name) @cg.node
+; (#set! cg.kind "program")
+
+; (library_header name: (identifier) @cg.name) @cg.node
+; (#set! cg.kind "library")
+
+; (package_header name: (identifier) @cg.name) @cg.node
+; (#set! cg.kind "package")
+
+
+; === Types: class / interface / record ===
+
+; (type_definition
+;   name: (identifier) @cg.name
+;   value: (class_type)
+; ) @cg.node
+; (#set! cg.kind "class")
+
+; (type_definition
+;   name: (identifier) @cg.name
+;   value: (interface_type)
+; ) @cg.node
+; (#set! cg.kind "interface")
+
+; (type_definition
+;   name: (identifier) @cg.name
+;   value: (record_type)
+; ) @cg.node
+; (#set! cg.kind "record")
+
+
+; === Top-level procedures/functions ===
+
+; (procedure_declaration name: (identifier) @cg.name) @cg.node
+; (#set! cg.kind "procedure")
+
+; (function_declaration name: (identifier) @cg.name) @cg.node
+; (#set! cg.kind "function")
+
+
+; === Methods (depending on grammar) ===
+
+; (method_declaration name: (identifier) @cg.name) @cg.node
+; (#set! cg.kind "method")
+
+; Constructors / Destructors (optional)
+; (constructor_declaration name: (identifier) @cg.name) @cg.node
+; (#set! cg.kind "constructor")
+;
+; (destructor_declaration name: (identifier) @cg.name) @cg.node
+; (#set! cg.kind "destructor")

+ 19 - 0
Delphi/fixtures/App.dpr

@@ -0,0 +1,19 @@
+program App;
+
+{$APPTYPE CONSOLE}
+
+uses
+  System.SysUtils,
+  UAuth in 'UAuth.pas';
+
+var
+  Svc: TAuthService;
+
+begin
+  Svc := TAuthService.Create;
+  try
+    Writeln(Svc.Login('olaf', 'secret'));
+  finally
+    Svc.Free;
+  end;
+end.

+ 36 - 0
Delphi/fixtures/UAuth.pas

@@ -0,0 +1,36 @@
+unit UAuth;
+
+interface
+
+uses
+  System.SysUtils,
+  System.Classes;
+
+type
+  ITokenValidator = interface
+    ['{11111111-1111-1111-1111-111111111111}']
+    function Validate(const AToken: string): Boolean;
+  end;
+
+  TAuthService = class(TInterfacedObject, ITokenValidator)
+  public
+    function Validate(const AToken: string): Boolean;
+    function Login(const AUser, APass: string): string;
+  end;
+
+implementation
+
+function TAuthService.Validate(const AToken: string): Boolean;
+begin
+  Result := AToken <> '';
+end;
+
+function TAuthService.Login(const AUser, APass: string): string;
+begin
+  if Validate(AUser + ':' + APass) then
+    Result := 'ok'
+  else
+    Result := '';
+end;
+
+end.

+ 30 - 0
Delphi/resolution/UnitResolution.md

@@ -0,0 +1,30 @@
+# Unit Resolution Heuristics (uses → File)
+
+## Input
+
+- Extracted edges of kind `imports` from `uses` clauses.
+- Extracted nodes of kind `unit|program|package|library` with their names.
+
+## MVP Algorithm
+
+1. Build `unitName -> nodeId` map for all indexed files.
+2. For each `imports` edge with target name `X`:
+   - try exact match `X`
+   - try case-insensitive match
+   - try namespace normalization:
+     - `System.SysUtils` may correspond to unit `SysUtils` (optional heuristic)
+3. If resolved: store `edge.to_node_id = targetNodeId`.
+4. If not resolved: keep `edge.to_symbol = X` so search still works.
+
+## DPR/DPK "in 'path'" cases (Phase 2)
+
+In Delphi project files you can have:
+
+```
+uses
+  Foo in 'src/Foo.pas',
+  Bar in 'Bar.pas';
+```
+
+Enhancement:
+- Parse optional path literal and resolve directly to file.