Skip to content

feat(health): promote Scala to Full tier (LanguageNodeMap + perf dialect)#745

Merged
RaghavChamadiya merged 1 commit into
mainfrom
feat/scala-full-tier
Jul 10, 2026
Merged

feat(health): promote Scala to Full tier (LanguageNodeMap + perf dialect)#745
RaghavChamadiya merged 1 commit into
mainfrom
feat/scala-full-tier

Conversation

@RaghavChamadiya

Copy link
Copy Markdown
Member

Summary

Promotes Scala from the Good tier to the Full tier: code-health markers now run on Scala, backed by a new complexity-walker node map and a performance dialect. Dataflow (Extract Method) stays deferred.

LanguageNodeMap

  • Control flow: if-expressions, while / do-while / for-comprehensions, match with per-case counting; for-comprehension filters and match-case guards count toward CCN as flat branches (no nesting level, same treatment as Python's comprehension filters).
  • Boolean operators via the infix text sniff (Scala parses every binary op as a generic infix node).
  • Class metrics for class / object / trait / enum bodies, LCOM4 through explicit this.member access (implicit receivers degrade to the documented no-signal valve, same as Kotlin).
  • catch takes a case block in Scala, so catch clauses are left unmapped and each handler counts once via its case clause: per-handler parity with Python and Java, no double count.
  • Assertion runs for munit / JUnit-style assert* calls. ScalaTest's infix DSL (x shouldBe y) has no assert-prefixed callee and is a documented gap.
  • given definitions are deliberately not function kinds: a given instance with a body nests real defs, and function collection stops descending at a function boundary, so mapping them would hide the methods.

Perf dialect

Rides the JVM lexicon (imports the Java dialect's sink tables, since java.* interop appears verbatim in Scala) and adds Scala-native boundaries:

  • scala.io.Source (fromFile / fromURL split by boundary), os-lib (method-gated on the os receiver; the bare name is not seeded in io_kind because it would collide with Python's stdlib os), sttp send and http4s expect/fetch (network-evidence-gated), Slick db.run (db-evidence-gated), doobie transact (distinctive, ungated).
  • Regex recompile in a loop: both "...".r (a bare field access, routed through the statement hook) and Pattern.compile.
  • String concat in a loop is gated on a same-file var x = "" binding, because += in Scala is also collection append; both the += and x = x + "lit" shapes are covered.
  • Sync-over-Future: Scala has no async keyword, so the dialect treats a def with a declared Future[...] return type as the async context and flags Await.result / Await.ready / Thread.sleep inside it.
  • x.synchronized { } is recognized as a lock scope (lock_in_loop, blocking_io_under_lock).
  • Constant-bound loops (1 to 3) are suppressed; nested_loop_with_io and the same-collection quadratic fact ride the existing gates.

Known recall ceiling, documented in the dialect docstring and the docs footnote: idiomatic .map / .foreach iteration bodies are lambdas, which reset loop depth, so combinator-driven loops produce no loop markers yet.

io_kind

Scala ecosystem seeds: slick, doobie, scalikejdbc, anorm, getquill (db); sttp, http4s, akka-http, play-ws (network); scala.io (filesystem).

Docs

README badges and tier tables, LANGUAGE_SUPPORT.md (Full-tier row, health checklist row with the assertion-gap footnote, roadmap), architecture doc and complexity README counts.

Testing

  • 15 new unit tests: walker CCN / nesting / match guards / flat match, LCOM4 with object and trait grouping, assertion runs, a perf fixture with negatives (hoisted regex, constant-bound loop, collection +=, plain helper calls), 9 parametrized gate cases, and the quadratic fact.
  • Full unit suite: 6,743 passed, 1 skipped.
  • Real-repo smoke on com-lihaoyi/os-lib: 59 Scala files, zero parse errors, 1,068 symbols indexed in 10s. Both raw io_in_loop findings verified as true positives by reading the code (os.write per zip entry in ZipOps, os.list in the recursive watch loop). Walker cost sits in the same envelope as the other Full languages.

…ect)

Scala LanguageNodeMap: complexity, nesting, cognitive, class metrics
(class/object/trait/enum, LCOM4 via this.member field_expression),
match/for-comprehension guards as flat branches, catch cases counted
per handler, assertion runs for munit/plain assert calls.

Scala perf dialect riding the JVM lexicon (Java sink tables) plus
Scala-native boundaries: scala.io.Source, os-lib (method-gated),
sttp/http4s (network-gated), Slick db.run (db-gated), doobie transact.
Scala-specific markers: "...".r and Pattern.compile recompiled in a
loop, string concat gated on a var-String binding (collection += never
fires), Await.result/Thread.sleep inside a Future-returning def as
blocking_sync_in_async, x.synchronized as lock scope, constant-bound
(1 to N) loop suppression, same-collection quadratic fact.

io_kind seeds for the Scala ecosystem (slick, doobie, scalikejdbc,
anorm, getquill, sttp, http4s, akka-http, play-ws, scala.io).

15 new unit tests; os-lib smoke: 59 files, zero parse errors, both raw
perf findings true positives on manual review; full suite green.
Dataflow dialect deferred per plan; .map/.foreach combinator iteration
is a documented recall ceiling pending the Ruby block-iteration design.
@repowise-bot

repowise-bot Bot commented Jul 10, 2026

Copy link
Copy Markdown

✅ Health: 7.7 (unchanged)

📋 At a glance
1 file changed health · 5 hotspots touched · 4 new findings introduced · 5 co-change pairs left out · 5 files with recent fix history.

Files & modules (2)
  • packages (5 files)
    • .../complexity/cyclomatic.py
    • .../complexity/perf_walk.py
    • .../external_systems/io_kind.py
    • .../complexity/languages.py
    • .../complexity/ast_utils.py
  • tests (2 files)
    • .../health/test_perf_dialects.py
    • .../health/test_complexity_walker.py

🚨 Change risk: high (riskier than 69% of this repo's commits · raw 9.4/10)
This change's risk is driven by:

  • more lines added than baseline
  • more scattered than baseline

🩹 Review priority (files here with the most recent bug-fix history — defects cluster, so review these first)

File Score Δ Why
.../health/test_perf_dialects.py 5.8 → 6.0 ▲ +0.2 ✅ resolved dry violation
🔎 More signals (2)

🔥 Hotspots touched (5)

  • .../complexity/cyclomatic.py — 3 commits/90d, 3 dependents · primary owner: Raghav Chamadiya (85%)
  • .../health/test_perf_dialects.py — 8 commits/90d, 3 dependents · primary owner: Raghav Chamadiya (99%)
  • .../health/test_complexity_walker.py — 8 commits/90d, 2 dependents · primary owner: Raghav Chamadiya (80%)
2 more
  • .../complexity/perf_walk.py — 5 commits/90d, 1 dependents · primary owner: Raghav Chamadiya (90%)
  • .../external_systems/io_kind.py — 4 commits/90d, 8 dependents · primary owner: Raghav Chamadiya (100%)

🔗 Hidden coupling (3 files)

  • .../complexity/languages.py co-changes with these files (not in this PR):
    • docs/LANGUAGE_SUPPORT.md (7× — 🟢 routine)
    • .../complexity/walker.py (4× — 🟢 routine)
  • .../health/test_perf_dialects.py co-changes with these files (not in this PR):
    • .../dialects/go.py (4× — 🟢 routine)
    • .../dialects/python.py (4× — 🟢 routine)
  • .../health/test_complexity_walker.py co-changes with .../complexity/walker.py (4× — 🟢 routine) — not in this PR.

📊 Full report · ⭐ Star Repowise · 📥 Install bot · Last updated 2026-07-10 09:03 UTC
Silence on a single PR with [skip repowise] in the title · Per-repo toggle on repowise.dev/settings?tab=bot

@RaghavChamadiya RaghavChamadiya merged commit a9f8dd8 into main Jul 10, 2026
7 checks passed
@RaghavChamadiya RaghavChamadiya deleted the feat/scala-full-tier branch July 10, 2026 09:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants