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 definitionsSELECT name, start_line, peekFROM 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 argumentsSELECT captures['X'].peek as dangerous_input, file_path, start_lineFROM ast_match('code', 'eval(__X__)', 'python');
-- Pattern matching with variadic wildcardsSELECT captures['F'].name as func_name, captures['Y'].peek as return_valueFROM ast_match('code', 'def __F__(__): %__<BODY*>__% return __Y__', 'python');
-- Security audit: find dangerous function callsSELECT * FROM ast_security_audit('code')WHERE risk_level = 'high';
-- Function complexity metricsSELECT name, cyclomatic, max_depth, linesFROM ast_function_metrics('code')WHERE cyclomatic > 10;
-- Cross-language analysis with semantic typesSELECT language, COUNT(*) as functionsFROM 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 matchingSELECT * FROM ast_match('code', 'class __C__: %__<**>__% def __M__(self): %__<BODY*>__%', 'python');
-- Optional and negation wildcardsSELECT * 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 patternsSELECT 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 useCREATE 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 Typklassifikationast_call_graph(source)- aggregierter Caller→Callee-Graph mit Aufrufzahlenast_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 LISTzurück; v1.7.0) ast_match(source, pattern, lang)- Musterabgleich für die Codesucheast_select(source, css_selector)- CSS-Selektor-Abfragenast_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 computationSELECT 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üfenast_inside(source, child_type, parent_type, parent_name)- Knoten in bestimmten Eltern findenast_precedes(source, before_type, after_type)- Ordnungsprädikateast_follows(source, after_type, before_type)- Ordnungsprädikateast_not_has(source, parent_type, child_type)- negiertes Enthaltensein
Analysemakros (dateipfadbasiert):
ast_definitions(source)- Alle benannten Definitionen mit Kategorienast_function_metrics(source)- Zyklomatische Komplexität, Nesting-Tiefe, Zeilenzahlenast_security_audit(source)- gefährliche Funktionsaufrufmuster erkennenast_dead_code(source)- potenziell ungenutzte Funktionen/Klassen findenast_nesting_analysis(source)- tief verschachtelten Code identifizierenast_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 Wurzelast_children(table, node_id)- unmittelbare Kinderast_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 Bezeichnersemantic_type- Normalisierter Typ für sprachübergreifende Abfragenfile_path,language- Quellortstart_line,end_line,depth- Position und Verschachtelungdescendant_count- Für O(1)-Teilbaumabfragenpeek- Konfigurierbare Quellvorschauqualified_name- Scope-basierter, dateiweit eindeutiger Pfad (FormatC[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#; FlagIS_EXPORTEDfür Sichtbarkeit auf Dateiebene)scope- STRUCT<current, function, class, module, stack> (v1.7.4); ersetzt die Spaltenscope_id/scope_stackaus v1.7.2.scope.functionbeantwortet „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 | [] |