
Erstellen und Abfragen einer Graphdatenbank-Repräsentation von Quellcode
Analysiere Quellcode in abfragbare Graphen von Funktionen, Klassen, Aufrufen und semantischen Annotationen für die Sicherheitsanalyse.
Trailmark verwendet tree-sitter für sprachunabhängiges AST-Parsing und rustworkx für leistungsstarke Graphendurchläufe. Die langfristige Vision ist es, diesen Graphen mit Mutationstests und coverage-gesteuertem Fuzzing zu kombinieren, um Lücken zwischen Annahmen und Testabdeckung zu identifizieren, die über Benutzereingaben erreichbar sind.
Trailmark arbeitet in drei Phasen: Parsen, Indexieren und Abfragen.```mermaid flowchart TD A["Source Files"] --> B["tree-sitter Parser"] B --> C["CodeGraph (nodes + edges)"] C --> D["rustworkx GraphStore"] D --> E["QueryEngine"] E --> F["JSON / Summary / Hotspots"]
classDef src fill:#007bff26,stroke:#007bff,color:#007bff
classDef parse fill:#28a74526,stroke:#28a745,color:#28a745
classDef data fill:#6f42c126,stroke:#6f42c1,color:#6f42c1
classDef query fill:#ffc10726,stroke:#e6a817,color:#e6a817
class A src
class B parse
class C,D data
class E,F query
### 1. Parsen
Ein sprachspezifischer Parser durchläuft das Verzeichnis, parst jede Datei in einen tree-sitter AST und extrahiert:
- **Knoten** — Funktionen, Methoden, Klassen, Strukturen, Schnittstellen, Traits, Enumerationen, Module, Namensräume
- **Kanten** — Aufrufe, Vererbung, Implementierung, Enthalten, Importe
- **Metadaten** — Typannotationen, zyklomatische Komplexität, Verzweigungen, Dokumentationsstrings, Ausnahmetypen
### Unterstützte Sprachen
| Sprache | Erweiterungen | Wichtige Konstrukte |
| --- | --- | --- |
| Python | `.py` | Funktionen, Klassen, Methoden |
| JavaScript | `.js`, `.jsx`, `.mjs`, `.cjs` | Funktionen, Klassen, Arrow-Funktionen |
| TypeScript | `.ts`, `.tsx` | Funktionen, Klassen, Schnittstellen, Enums |
| PHP | `.php` | Funktionen, Klassen, Schnittstellen, Traits |
| Ruby | `.rb` | Methoden, Klassen, Module |
| C | `.c`, `.h` | Funktionen, Strukturen, Enums |
| C++ | `.cpp`, `.hpp`, `.cc`, `.hh`, `.cxx`, `.hxx` | Funktionen, Klassen, Strukturen, Namensräume |
| C# | `.cs` | Methoden, Klassen, Schnittstellen, Strukturen, Enums, Namensräume |
| Java | `.java` | Methoden, Klassen, Schnittstellen, Enums |
| Go | `.go` | Funktionen, Methoden, Strukturen, Schnittstellen |
| Rust | `.rs` | Funktionen, Strukturen, Traits, Enums, Impl-Blöcke |
| Solidity | `.sol` | Verträge, Schnittstellen, Bibliotheken, Funktionen, Modifikatoren, Strukturen, Enums |
| Cairo | `.cairo` | Funktionen, Traits, Strukturen, Enums, Impl-Blöcke, StarkNet-Verträge |
| Circom | `.circom` | Vorlagen, Funktionen, Signale, Komponenten |
| Haskell | `.hs` | Funktionen, Datentypen, Typklassen, Instanzen |
| Erlang | `.erl` | Funktionen, Datensätze, Verhalten, Module |
| Miden Assembly | `.masm` | Prozeduren, Einstiegspunkte, Konstanten, Aufrufe |
| Swift | `.swift` | Funktionen, Klassen, Strukturen, Enums, Protokolle, Erweiterungen |
| Objective-C | `.m`, `.mm`, `.h` | C-Funktionen, Klassen, Methoden (selektorbasierte Namensgebung) |
| Kotlin | `.kt`, `.kts` | Funktionen, Klassen, Schnittstellen, Datenklassen, Objekte, Methoden |
| Dart | `.dart` | Funktionen, Klassen, abstrakte Klassen, Methoden, Konstruktoren |
| Move | `.move` | Module, Funktionen, Importe, direkte Aufrufe |
| Tact | `.tact` | Verträge, Strukturen, Empfänger, Funktionen |
| Func | `.fc`, `.func` | Funktionen, Includes, direkte Aufrufe |
| Sway | `.sw` | ABI-Schnittstellen, Strukturen, Impl-Methoden, Funktionen |
| Rego | `.rego` | Pakete, Importe, Policy-Regeln, Regelaufrufe |
| Proto | `.proto` | Dienste, RPCs, Nachrichten, Felder, Enums |
| Thrift | `.thrift` | Dienste, Funktionen, Strukturen, Felder, Enums |
| GraphQL | `.graphql`, `.gql` | Objekttypen, Root-Operationen, Felder, Enums |
| SQL | `.sql` | Schemata, Tabellen, Ansichten, Funktionen, Prozeduren |```mermaid
flowchart TD
subgraph "Per-File Parsing"
F["Source file"] --> TS["tree-sitter AST"]
TS --> EX["Extract nodes"]
TS --> EC["Extract call edges"]
TS --> EB["Count branches"]
TS --> ET["Resolve types"]
end
EX --> CG["CodeGraph"]
EC --> CG
EB --> CG
ET --> CG
classDef src fill:#007bff26,stroke:#007bff,color:#007bff
classDef parse fill:#28a74526,stroke:#28a745,color:#28a745
classDef extract fill:#ffc10726,stroke:#e6a817,color:#e6a817
classDef data fill:#6f42c126,stroke:#6f42c1,color:#6f42c1
class F src
class TS parse
class EX,EC,EB,ET extract
class CG data
Node-IDs folgen dem Schema module:function, module:Class oder module:Class.method für eindeutige Nachschlagevorgänge. Die Verzeichnisanalyse löst bloße dateiübergreifende Aufrufe auf, wenn eine eindeutige Definition existiert; mehrdeutige dateiübergreifende Aufrufe werden auf dem ursprünglichen bestmöglichen Ziel belassen und mit uncertain markiert. Die Kantenkonfidenz wird als certain (direkte Aufrufe, self.method()), inferred (Attributzugriff auf Nicht-self-Objekte) oder uncertain (dynamischer Dispatch oder mehrdeutige Auflösung) gekennzeichnet.
Der GraphStore lädt den CodeGraph in einen rustworkx PyDiGraph und erstellt bidirektionale ID/Index-Zuordnungen für schnelle Traversierung.
Die QueryEngine bietet eine High-Level-API über den indizierten Graphen: