feat(lang): introduce language abstraction layer and Go refactor#2
Merged
feat(lang): introduce language abstraction layer and Go refactor#2
Conversation
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>
This was referenced Apr 21, 2026
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>
Collaborator
|
This looks great. Thanks! |
cffls
approved these changes
Apr 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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,TestRunnerinterfaces + 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 tolang.Language.cmd/diffguard/main.go— iterateslang.All(); blank-imports onlygoanalyzer(no TS/Rust yet).MULTI_LANGUAGE_SUPPORT.md,docs/rust-typescript-support.md,docs/multi-lang-followups.md.What does NOT change
README.md— stays atmain's version; the multi-language README rewrite lands in PR feat(lang): add TypeScript checker #3.go.mod/go.sum— no new deps (tree-sitter lands in PR feat(lang): introduce language abstraction layer and Go refactor #2)..github/workflows/ci.yml,Makefile— unchanged.Verification
go build ./... && go vet ./... && go test ./... -count=1— green. 11 test packages (tsanalyzer + rustanalyzer absent as intended).cmd/diffguard/main_test.gocarved by function name (not line number) to keep Go-only tests here;TestMixedRepo_*+buildDiffguardBinarydeferred to PR feat(lang): add TypeScript checker #3.TestCheckExitCode_FailInAnyLanguageEscalateskept in PR feat(lang): add Rust and TypeScript analyzer support #1 despite referencing[rust]/[typescript]— those are literal strings inreport.Section{Name: ...}fixtures, no runtime dependency.Reviewer notes
TestRun_SingleLanguageGoreferencesTestMixedRepo_*— intentional forward reference resolved by PR feat(lang): add TypeScript checker #3 (preserves byte-parity with the original bundled branch).cmd/diffguard/main.gogrows to two in PR feat(lang): introduce language abstraction layer and Go refactor #2 and three in PR feat(lang): add TypeScript checker #3. Three touches of the same file across the stack; not conflict-prone.