Route Kotlin through the structural matcher
ober
de6d2cf11d8acc603ca14a9435eafc4892ef07db
--- a/HANDOFF_OPUS_4_8.md +++ b/HANDOFF_OPUS_4_8.md @@ -7,7 +7,7 @@ Packaged Semgrep oracle: `/Users/user/.local/bin/semgrep` Branch: `java-structural-migration` (off `main`; carries java+scala+rust); Go and PHP migrations already merged. -## Summary: Go, PHP, Java, Scala, Rust, Ruby all on the real structural matcher +## Summary: Go, PHP, Java, Scala, Rust, Ruby, Kotlin on the structural matcher Five languages migrated off the regex generic-matcher approximation onto the real tree-sitter structural matcher; `generic-language?` (scan.ss ~809) no @@ -16,7 +16,7 @@ compiled into `jerboa-treesitter`: go/php/scala/rust (ABI 15), java (ABI 14, within the runtime's 13-15 window); scala/rust/php carry external scanners, go/java are parser-only. `make test` 321/321; smoke 15/15 (parse case per lang). Per-language normalize-oracle fixture results: java 42/42, scala 18/18, -rust 11/11, ruby 4/4, php 29/29, go 16/16. +rust 11/11, ruby 4/4, kotlin 4/4, php 29/29, go 16/16. ### Java/Scala/Rust migration (branch `java-structural-migration`) @@ -124,8 +124,10 @@ The two remaining fixtures are blocked by the same gap that limits ~12 languages, so closing them is the tip of the larger work: 1. **AST matching for the "generic" languages (the big one).** - python/js/ts/go/php/java/scala/rust/ruby now use the tree-sitter structural - matcher. C#, Swift, Dart, Kotlin, C, C++ remain `generic-language?` + python/js/ts/go/php/java/scala/rust/ruby/kotlin now use the tree-sitter + structural matcher. C#, Swift, Dart, C, C++ remain (Dart grammar is vendored + but deferred: bare patterns parse as top-level declarations, needing Go-style + scaffolding) `generic-language?` (scan.ss ~809) and use the regex-based `scan-generic-pattern`. That matcher approximates patterns with regexes and cannot express several Semgrep constructs. Real tree-sitter grammars for these languages would replace the --- a/lib/semgrep/match/structural.sls +++ b/lib/semgrep/match/structural.sls @@ -583,6 +583,10 @@ [(string=? language "ruby") (or (string=? type "program") (string=? type "expression_statement"))] + [(string=? language "kotlin") + (or (string=? type "source_file") + (string=? type "statement") + (string=? type "expression_statement"))] [else #f])) (def (normalized-pattern-root language root) (let loop ([current root] [owned '()]) --- a/lib/semgrep/parse/parse-target.sls +++ b/lib/semgrep/parse/parse-target.sls @@ -29,6 +29,7 @@ [(string=? canonical "scala") 'scala] [(string=? canonical "rust") 'rust] [(string=? canonical "ruby") 'ruby] + [(string=? canonical "kotlin") 'kotlin] [else (error 'parse-target-string "unsupported language in current MVP" --- a/lib/semgrep/scan.sls +++ b/lib/semgrep/scan.sls @@ -748,7 +748,6 @@ (string=? canonical "dart") (string=? canonical "move_on_aptos") (string=? canonical "julia") - (string=? canonical "kotlin") (string=? canonical "cpp")))) (def (c-language? language) (let ([canonical (or (canonical-language language) @@ -31277,6 +31276,8 @@ '("$L = $R" "$L[$I] = $R" "val $L = $R" "var $L = $R")] [(string=? language "rust") '("$L = $R" "$L[$I] = $R" "let $L = $R" "let mut $L = $R")] + [(string=? language "kotlin") + '("$L = $R" "$L[$I] = $R" "val $L = $R" "var $L = $R")] [else '("$L = $R" "$L[$I] = $R")])) (def (scan-implicit-assignment-propagators rule language path source target-root) --- a/src/.jerbuild-hashes +++ b/src/.jerbuild-hashes @@ -2,12 +2,12 @@ ("src/semgrep/result.ss" . "22D23E40B49BA529") ("src/semgrep/output/json.ss" . "293881CFA2ADB7BC") ("src/semgrep/lang.ss" . "6982E07679D20836") - ("src/semgrep/parse/parse-target.ss" . "AD193DA8CA67B2B2") - ("src/semgrep/scan.ss" . "82F2DEBA214D9CFD") - ("src/semgrep/output/text.ss" . "BE476CB84B807FBA") + ("src/semgrep/parse/parse-target.ss" . "904B71D207617229") + ("src/semgrep/scan.ss" . "A994804D70D4F26E") ("src/semgrep/fix.ss" . "2E5B65B1FEF3B2B1") - ("src/semgrep/schema/lang.ss" . "CAE2CA859C9A9FD0") + ("src/semgrep/output/text.ss" . "BE476CB84B807FBA") ("src/semgrep/rule.ss" . "E12C108153C181FA") - ("src/semgrep/match/structural.ss" . "3CE2210D6FE588E4") + ("src/semgrep/schema/lang.ss" . "CAE2CA859C9A9FD0") + ("src/semgrep/match/structural.ss" . "6047821D83B32FCE") ("src/semgrep/main.ss" . "A4EC9E7F2A09D25E") ("src/semgrep/cli.ss" . "EBDC4B1DAD3F13CC")) --- a/src/semgrep/match/structural.ss +++ b/src/semgrep/match/structural.ss @@ -607,6 +607,10 @@ [(string=? language "ruby") (or (string=? type "program") (string=? type "expression_statement"))] + [(string=? language "kotlin") + (or (string=? type "source_file") + (string=? type "statement") + (string=? type "expression_statement"))] [else #f])) (def (normalized-pattern-root language root) --- a/src/semgrep/parse/parse-target.ss +++ b/src/semgrep/parse/parse-target.ss @@ -21,6 +21,7 @@ [(string=? canonical "scala") 'scala] [(string=? canonical "rust") 'rust] [(string=? canonical "ruby") 'ruby] + [(string=? canonical "kotlin") 'kotlin] [else (error 'parse-target-string "unsupported language in current MVP" language)]))) --- a/src/semgrep/scan.ss +++ b/src/semgrep/scan.ss @@ -820,7 +820,6 @@ (string=? canonical "dart") (string=? canonical "move_on_aptos") (string=? canonical "julia") - (string=? canonical "kotlin") (string=? canonical "cpp")))) (def (c-language? language) @@ -31263,6 +31262,12 @@ "$L[$I] = $R" "let $L = $R" "let mut $L = $R")] + [(string=? language "kotlin") + ;; Kotlin bindings are val/var property declarations. + '("$L = $R" + "$L[$I] = $R" + "val $L = $R" + "var $L = $R")] [else '("$L = $R" "$L[$I] = $R")]))