sitting_duck

Quellcode-ASTs aus 27 Programmiersprachen mit tree-sitter-Grammatiken, Musterabgleich und struktureller Suche parsen und analysieren

Maintainer: teaguesterling

Installation und Laden

INSTALL sitting_duck FROM community;
LOAD sitting_duck;

Beispiel

-- Parse Python code and find function definitions
SELECT name, start_line, peek
FROM parse_ast('
def hello():
return "hello world"
def greet(name):
print(f"Hello, {name}!")
return name
', 'python')
WHERE is_function_definition(semantic_type);
-- Pattern matching: find eval() calls and capture arguments
SELECT captures['X'].peek as dangerous_input, file_path, start_line
FROM ast_match('code', 'eval(__X__)', 'python');
-- Pattern matching with variadic wildcards
SELECT captures['F'].name as func_name, captures['Y'].peek as return_value
FROM ast_match('code',
'def __F__(__):
%__<BODY*>__%
return __Y__', 'python');
-- Security audit: find dangerous function calls
SELECT * FROM ast_security_audit('code')
WHERE risk_level = 'high';
-- Function complexity metrics
SELECT name, cyclomatic, max_depth, lines
FROM ast_function_metrics('code')
WHERE cyclomatic > 10;
-- Cross-language analysis with semantic types
SELECT language, COUNT(*) as functions
FROM read_ast(['src/**/*.py', 'src/**/*.js', 'src/**/*.go'])
WHERE is_function_definition(semantic_type)
GROUP BY language;

Über sitting_duck

Sitting Duck ist eine DuckDB-Erweiterung zum Parsen von Quellcode in Abstract Syntax Trees (ASTs) mit tree-sitter-Grammatiken. Sie bietet eine leistungsstarke SQL-Schnittstelle, um Codestruktur über 25+ Programmiersprachen zu analysieren, zu durchsuchen und zu verstehen.

Dokumentation: https://sitting-duck.readthedocs.io/

Kernfunktionen

Musterabgleich: Finden Sie Codestrukturen per Pattern-by-Example-Matching mit Wildcards:

-- Recursive wildcards for deep matching
SELECT * FROM ast_match('code', 'class __C__: %__<**>__% def __M__(self): %__<BODY*>__%', 'python');
-- Optional and negation wildcards
SELECT * FROM ast_match('code', 'def __F__(__<?ARGS>__): %__<BODY*>__%', 'python');

See: https://sitting-duck.readthedocs.io/en/latest/guide/pattern-matching/

CSS-Selektor-Abfragen (v1.6.0, erweitert in v1.7.0+): Fragen Sie AST-Knoten mit CSS-Selektor-Syntax ab — bootstrapped mit der eigenen CSS-Grammatik von Sitting Duck:

SELECT name FROM ast_select('src/*.py', '.func:has(.call#execute):not(:has(try_statement))');
-- v1.7.0: :match (current-node) vs :contains (subtree) structural patterns
SELECT name FROM ast_select('src/*.py', '.func:contains("db.execute()")');
SELECT name FROM ast_select('src/*.py', 'call:match("db.execute()")');
-- v1.7.2: parse once, query many — orders of magnitude faster for interactive use
CREATE TABLE my_ast AS SELECT * FROM read_ast('src/**/*.py');
SELECT * FROM ast_select_from('my_ast', '.class:named');
SELECT * FROM ast_select_from('my_ast', '.func:has(return_statement)');

Unterstützt Typselektoren, #name, .semantic (ca. 80 Aliasse), Kombinatoren, :has(), :not(), strukturelle Muster :match() / :contains(), Scope-/Call-Graph-Pseudoklassen und Pseudoelement-Navigation. Nackter Typabgleich: if trifft if + if_statement + if_clause.

v1.10.0 fügt zur Laufzeit ladbare tree-sitter-Grammatiken hinzu (register_language(), standardmäßig aus hinter sitting_duck_enable_runtime_grammars), ast_to_blocks (Codestruktur als duck_blocks-Dokumente darstellen) sowie ast_patch/ast_replace (AST-verankertes Source-Patching und selektorgesteuertes Umschreiben in SQL).

v1.9.0 härtet die Selektor-Engine: keine still-leeren Ergebnisse mehr (Selektoren, die die Engine nicht umsetzen kann, werfen jetzt einen klaren Fehler statt 0 Zeilen), #name an Call-Knoten bindet einheitlich über alle 27 Grammatiken, und NULL-Spalten matchen nicht mehr zu viel oder zu wenig.

Filterung zur Parse-Zeit (v1.8.0): max_depth := und prune := verkleinern den AST zur Parse-Zeit, mit automatischer Tree-Heilung:

SELECT * FROM read_ast('file.py', max_depth := 2);
SELECT * FROM read_ast('src/**/*.py', prune := ['syntax', 'comments', 'punctuation']);

Prune-Richtlinien: syntax, comments, literals, imports, types, punctuation, unnamed, leaves, internal.

Call-Graph-Makros (v1.8.0):

  • ast_get_calls(source) - Aufrufe mit Caller-Zuordnung und Typklassifikation
  • ast_call_graph(source) - aggregierter Caller→Callee-Graph mit Aufrufzahlen
  • ast_find_references(source, name) - symbolische Referenzauflösung mit Scope-Kette

Tabellenfunktionen:

  • read_ast(file_pattern, language := NULL) - Quelldateien in AST-Zeilen parsen (parallel)
  • parse_ast(content, language) - Quellcode-Zeichenketten parsen (Tabellenfunktion)
  • parse_ast_list(content, language) - Quellcode-Zeichenketten parsen (Skalar, gibt LIST zurück; v1.7.0)
  • ast_match(source, pattern, lang) - Musterabgleich für die Codesuche
  • ast_select(source, css_selector) - CSS-Selektor-Abfragen
  • ast_select_from(table_name, selector) - CSS-Selektoren auf vorgeparsten Tabellen (v1.7.2)
  • ast_type_map(language) - Knotentyp-Entdeckung über Sprachen hinweg

Extraktionssuffix v1.7.0: Jeder Extraktionsparameter (context, source, structure, peek) kann ein Suffix +schema erhalten, das den vollen Spaltensatz im Ausgabeschema als NULLs behält, ohne sie zu berechnen:

-- Keep peek column in schema but skip its computation
SELECT name, peek FROM read_ast('file.py', peek := 'none+schema');

Ermöglicht SQL-Makros, stabile Schemas zu deklarieren, unabhängig davon, welche Spalten sie füllen.

Relationale Prädikate (v1.5.0):

  • ast_has(source, parent_type, child_type) - Enthaltensein prüfen
  • ast_inside(source, child_type, parent_type, parent_name) - Knoten in bestimmten Eltern finden
  • ast_precedes(source, before_type, after_type) - Ordnungsprädikate
  • ast_follows(source, after_type, before_type) - Ordnungsprädikate
  • ast_not_has(source, parent_type, child_type) - negiertes Enthaltensein

Analysemakros (dateipfadbasiert):

  • ast_definitions(source) - Alle benannten Definitionen mit Kategorien
  • ast_function_metrics(source) - Zyklomatische Komplexität, Nesting-Tiefe, Zeilenzahlen
  • ast_security_audit(source) - gefährliche Funktionsaufrufmuster erkennen
  • ast_dead_code(source) - potenziell ungenutzte Funktionen/Klassen finden
  • ast_nesting_analysis(source) - tief verschachtelten Code identifizieren
  • ast_definition_parent(table) - nächsten Definitionsvorfahren je Knoten auflösen

Baumnavigation:

  • ast_descendants(table, node_id) - Teilbaum holen (O(1) über descendant_count)
  • ast_ancestors(table, node_id) - Pfad vom Knoten zur Wurzel
  • ast_children(table, node_id) - unmittelbare Kinder
  • ast_function_scope(table, node_id) - Funktionskörper ohne verschachtelte Funktionen

Semantische Prädikate: Sprachenübergreifende Filterung mit normalisierten Typen:

  • is_function_definition(st), is_class_definition(st), is_variable_definition(st)
  • is_function_call(st), is_literal(st), is_conditional(st), is_loop(st)

Unterstützte Sprachen (27)

Category Languages
Web JavaScript, TypeScript, HTML, CSS
Systems C, C++, Go, Rust, Zig
Scripting Python, Ruby, PHP, Lua, R, Bash
Enterprise Java, C#, Kotlin, Swift
Mobile Dart
Data SQL, JSON, TOML, GraphQL, HCL
Documentation Markdown

AST-Schema

Jeder geparste Knoten enthält:

  • type, name - Knotentyp und extrahierter Bezeichner
  • semantic_type - Normalisierter Typ für sprachübergreifende Abfragen
  • file_path, language - Quellort
  • start_line, end_line, depth - Position und Verschachtelung
  • descendant_count - Für O(1)-Teilbaumabfragen
  • peek - Konfigurierbare Quellvorschau
  • qualified_name - Scope-basierter, dateiweit eindeutiger Pfad (Format C[User] F[__init__]; v1.7.0)
  • signature_type, parameters, modifiers, annotations - Native Extraktion (v1.8.0: modifiers[] befüllt für Python, JS, TS, Rust, Kotlin, Swift, Dart, C#; Flag IS_EXPORTED für Sichtbarkeit auf Dateiebene)
  • scope - STRUCT<current, function, class, module, stack> (v1.7.4); ersetzt die Spalten scope_id / scope_stack aus v1.7.2. scope.function beantwortet „in welcher Funktion bin ich?“ als einzelnes Spaltenlesen.

Vollständiges Schema: https://sitting-duck.readthedocs.io/en/latest/api/output-schema/

Anwendungsfälle

  • Sicherheitsaudit – gefährliche Muster finden (eval, exec, SQL-Injection)
  • Codequalität – Komplexitätsmetriken, Erkennung toten Codes, Nesting-Analyse
  • Refactoring – musterbasiertes Codesuchen in großen Codebasen
  • Dokumentation – Funktionssignaturen und Struktur extrahieren
  • KI-Workflows – strukturiertes Codeverständnis für LLM-Werkzeuge

GitHub: https://github.com/teaguesterling/sitting_duck

Hinzugefügte Funktionen

function_name function_type description comment examples
ast_ancestors table_macro NULL NULL
ast_call_arguments table_macro NULL NULL
ast_call_graph table_macro NULL NULL
ast_callees table_macro NULL NULL
ast_callers table_macro NULL NULL
ast_capture macro NULL NULL
ast_children table_macro NULL NULL
ast_class_members table_macro NULL NULL
ast_containing_line table_macro NULL NULL
ast_dead_code table_macro NULL NULL
ast_definition_parent table_macro NULL NULL
ast_definitions table_macro NULL NULL
ast_descendants table_macro NULL NULL
ast_dispatch_predicate macro NULL NULL
ast_exports table_macro NULL NULL
ast_find_references table_macro NULL NULL
ast_follows table_macro NULL NULL
ast_function_metrics table_macro NULL NULL
ast_function_scope table_macro NULL NULL
ast_functions_containing table_macro NULL NULL
ast_get_calls table_macro NULL NULL
ast_get_source macro NULL NULL
ast_get_source_line macro NULL NULL
ast_get_source_numbered macro NULL NULL
ast_has table_macro NULL NULL
ast_imports table_macro NULL NULL
ast_in_range table_macro NULL NULL
ast_inside table_macro NULL NULL
ast_match table_macro NULL NULL
ast_nesting_analysis table_macro NULL NULL
ast_node_edit macro NULL NULL
ast_not_has table_macro NULL NULL
ast_patch table_macro NULL NULL
ast_pattern table_macro NULL NULL
ast_pattern_list macro NULL NULL
ast_peek_contains_any scalar NULL NULL
ast_precedes table_macro NULL NULL
ast_qualified_name_as_string macro NULL NULL
ast_replace table_macro NULL NULL
ast_resolve table_macro NULL NULL
ast_security_audit table_macro NULL NULL
ast_select table_macro NULL NULL
ast_select_from table_macro NULL NULL
ast_select_list table_macro NULL NULL
ast_select_rules table_macro NULL NULL
ast_siblings table_macro NULL NULL
ast_source_of table_macro NULL NULL
ast_supported_languages table NULL NULL
ast_to_blocks table_macro NULL NULL
ast_to_blocks_from table_macro NULL NULL
ast_to_blocks_list table_macro NULL NULL
ast_type_map table NULL NULL
binds_name scalar NULL NULL
clean_pattern macro NULL NULL
detect_language scalar NULL NULL
get_kind scalar NULL NULL
get_searchable_types scalar NULL NULL
get_super_kind scalar NULL NULL
has_body scalar NULL NULL
is_annotation macro NULL NULL
is_arithmetic macro NULL NULL
is_assignment macro NULL NULL
is_block macro NULL NULL
is_boolean_literal macro NULL NULL
is_call scalar NULL NULL
is_class_definition macro NULL NULL
is_comment macro NULL NULL
is_comparison macro NULL NULL
is_conditional macro NULL NULL
is_construct scalar NULL NULL
is_control_flow scalar NULL NULL
is_declaration_only scalar NULL NULL
is_definition scalar NULL NULL
is_directive macro NULL NULL
is_embodied scalar NULL NULL
is_export macro NULL NULL
is_exported scalar NULL NULL
is_foreign macro NULL NULL
is_function_call macro NULL NULL
is_function_definition macro NULL NULL
is_identifier scalar NULL NULL
is_import macro NULL NULL
is_jump macro NULL NULL
is_kind scalar NULL NULL
is_list macro NULL NULL
is_literal macro NULL NULL
is_logical macro NULL NULL
is_loop macro NULL NULL
is_member_access macro NULL NULL
is_module_definition macro NULL NULL
is_name_declaration scalar NULL NULL
is_name_definition scalar NULL NULL
is_name_reference scalar NULL NULL
is_number_literal macro NULL NULL
is_parser_specific scalar NULL NULL
is_pattern_wildcard macro NULL NULL
is_punctuation scalar NULL NULL
is_scope scalar NULL NULL
is_semantic_type scalar NULL NULL
is_string_literal macro NULL NULL
is_syntax_only scalar NULL NULL
is_type_composite macro NULL NULL
is_type_definition macro NULL NULL
is_type_generic macro NULL NULL
is_type_primitive macro NULL NULL
is_type_reference macro NULL NULL
is_variable_definition macro NULL NULL
kind_code scalar NULL NULL
name_role scalar NULL NULL
parse_ast table NULL NULL
parse_ast_flat table NULL NULL
parse_ast_hierarchical table NULL NULL
parse_ast_list scalar NULL NULL
parse_ast_list_table table_macro NULL NULL
parse_html_wildcard macro NULL NULL
pattern_has_recursive macro NULL NULL
pattern_has_variadic macro NULL NULL
read_ast table NULL NULL
read_ast_flat table NULL NULL
read_ast_hierarchical table NULL NULL
read_ast_hierarchical_new table NULL NULL
register_language table NULL NULL
semantic_type_base macro NULL NULL
semantic_type_code scalar NULL NULL
semantic_type_to_string scalar NULL NULL
sitting_duck_enable_dynamic_predicates pragma NULL NULL
string_contains_any scalar NULL NULL
string_contains_any_i scalar NULL NULL
wildcard_capture_name macro NULL NULL

Überladene Funktionen

Diese Erweiterung fügt keine Funktionsüberladungen hinzu.

Hinzugefügte Typen

Diese Erweiterung fügt keine Typen hinzu.

Hinzugefügte Einstellungen

name description input_type scope aliases
sitting_duck_enable_runtime_grammars Allow register_language() to load native tree-sitter grammar libraries, which executes arbitrary native code in-process. Disabled by default. BOOLEAN GLOBAL []