Skip to content

feat(lang): introduce language abstraction layer and Go refactor#2

Merged
cffls merged 7 commits intomainfrom
feat/lang-foundation
Apr 23, 2026
Merged

feat(lang): introduce language abstraction layer and Go refactor#2
cffls merged 7 commits intomainfrom
feat/lang-foundation

Conversation

@donnfelker
Copy link
Copy Markdown
Contributor

Summary

Splits the first of three stacked PRs from feat/multi-language-support-v1. Lands the language-abstraction layer and moves all Go-specific logic behind it. Zero behavior change on Go-only repos. No new runtime dependencies.

Stacked sibling PRs: # (TypeScript), # (Rust + cross-cutting).

What ships

  • internal/lang/Language, FileFilter, ComplexityCalculator, ComplexityScorer, FunctionExtractor, ImportResolver, MutantGenerator, MutantApplier, AnnotationScanner, TestRunner interfaces + thread-safe registry + manifest/detector-based auto-detection.
  • internal/lang/goanalyzer/ — full Go implementation behind the new interfaces.
  • internal/lang/evalharness/ — shared harness lands here so PR feat(lang): introduce language abstraction layer and Go refactor #2 can use it.
  • internal/deps/graph.go — new pure-math helpers (cycle detection, coupling, instability, SDP) split out so any language can reuse.
  • internal/{diff,complexity,sizes,deps,churn,mutation}/ — refactored into thin orchestrators that delegate to lang.Language.
  • cmd/diffguard/main.go — iterates lang.All(); blank-imports only goanalyzer (no TS/Rust yet).
  • Docs: MULTI_LANGUAGE_SUPPORT.md, docs/rust-typescript-support.md, docs/multi-lang-followups.md.

What does NOT change

Verification

  • go build ./... && go vet ./... && go test ./... -count=1 — green. 11 test packages (tsanalyzer + rustanalyzer absent as intended).
  • cmd/diffguard/main_test.go carved by function name (not line number) to keep Go-only tests here; TestMixedRepo_* + buildDiffguardBinary deferred to PR feat(lang): add TypeScript checker #3.
  • Test TestCheckExitCode_FailInAnyLanguageEscalates kept in PR feat(lang): add Rust and TypeScript analyzer support #1 despite referencing [rust]/[typescript] — those are literal strings in report.Section{Name: ...} fixtures, no runtime dependency.

Reviewer notes

donnfelker and others added 6 commits April 21, 2026 15:40
Introduces the core lang.Language interface, global registry
(Register/Get/All), and manifest-based language detection.
All language implementations will self-register via init() so
zero wiring is needed in main for each new language.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…rface

Moves all Go-specific AST parsing, complexity, sizes, deps, mutation
(generate/annotate/apply), and test-runner logic into
internal/lang/goanalyzer and registers as "go" via init(). Existing
orchestrators will delegate to this package through the Language interface.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Provides a reusable golden-file test runner for language analyzers.
Each language can drive snapshot comparisons without reimplementing
fixture loading and JSON diffing.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
diff, complexity, sizes, deps, churn, and mutation now accept language
interfaces (ComplexityCalculator, FunctionExtractor, ImportResolver, etc.)
instead of embedding Go-specific AST code. Adds deps/graph.go for
pure-math helpers (cycle detection, coupling, instability, SDP) shared
across language analyzers.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replaces hard-wired Go orchestration in main with the language-registry
dispatch loop. Only goanalyzer is blank-imported, so this PR stays Go-only.
Carved main_test.go keeps the Go smoke test and registry unit tests;
the mixed-repo E1 integration tests land in PR #3 alongside Rust/TS.
Adds TestRegistry_OnlyGoRegistered to lock in that tsanalyzer/rustanalyzer
are absent at this stack layer.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Captures the architecture decisions behind the language abstraction layer,
the planned Rust and TypeScript analyzer specs, and outstanding follow-up
items for the multi-language roadmap.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Split four high-complexity functions (run, AssertMatches,
ScanPackageImports, anyMatchingFinding) into helpers so each falls
under the cognitive-complexity threshold and run() fits the size
budget. Add targeted tests across evalharness, goanalyzer,
testrunner, churn, diff.Filter, and cmd/diffguard to raise Tier-1
mutation kill rate above the 80% threshold.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@donnfelker donnfelker marked this pull request as ready for review April 21, 2026 20:41
@donnfelker donnfelker requested a review from cffls April 21, 2026 22:01
@cffls
Copy link
Copy Markdown
Collaborator

cffls commented Apr 22, 2026

This looks great. Thanks!

@cffls cffls merged commit 5d6f4fd into main Apr 23, 2026
4 checks passed
@donnfelker donnfelker deleted the feat/lang-foundation branch April 24, 2026 20:48
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