refactor(extractors): remove unnecessary conditionals and boost branch coverage#173
Merged
refactor(extractors): remove unnecessary conditionals and boost branch coverage#173
Conversation
…xture tests
Replace the fragile test architecture:
- Delete core.test.ts, tier2.test.ts, tier3.test.ts (snapshot-based)
- Delete coverage.test.ts (915 lines of inline source strings)
- Delete typeref.test.ts (488 lines of inline + fixture hybrid)
- Delete all __snapshots__/ files
Replace with 23 per-language test files (one per extractor):
bash, c, cpp, csharp, elixir, elm, go, haskell, java, javascript,
julia, kotlin, lua, objc, ocaml, php, python, ruby, rust, scala,
swift, typescript, zig
Each file:
1. Parses the fixture via parseAndExtractStrict
2. Asserts specific expectations (symbol names/kinds, imports, call refs,
relationships, type refs, routes)
3. No snapshots, no inline source strings
health.test.ts (structural invariants) and extractorHelper.ts retained as-is.
-5423 lines, +1185 lines (net −4238)
…new constructs Enrich fixture files for 19 languages with constructs that exercise previously uncovered extractor branches: - TypeScript: enum, namespace import, as-cast, type assertion, interface extends, variable type annotations, class fields - Go: pointer/value receiver methods, struct field types, type alias, var decls, type assertion, aliased import, interface embedding - C++: enum, base class inheritance, typedef, function declaration, sizeof, dynamic_cast, field/variable type refs - C#: struct, using alias, new expressions, as-cast, variable type refs, generic args - Java: interface extends interface, class extends + implements, static import, cast expression, field/variable type refs - Kotlin: interface implementation, as cast, nullable types, class field type refs - Swift: enum, struct conformance, property declarations, as-cast, optional/array types - ObjC: protocol declaration, protocol conformance, @import, category, ivars, class implementation, method type refs - PHP: extends + implements, grouped use, member/scoped calls, field type refs - Rust: enum, as-cast, let type annotation - Python: aliased from..import, wildcard import - Julia: short function definition, macro definition - Elixir: defstruct, defprotocol, defimpl, use/require directives - OCaml: fun expression, multiple variant types, module type definition - Zig: const declarations, @import builtin - Elm: port annotation, plain value declaration, call refs from view function - Haskell: type signatures - Lua: call refs from nested calls Added corresponding assertions in all 23 per-language test fileAdded corresponding assertions in all 23 per-language test fileAdded corresp% → 62.4% (+9.1%)
…h coverage - Remove duplicate type extractions in C#, C++, and sizeof helpers - Simplify TS isNodeExported (remove 2 dead checks) - Simplify 8 TS type_annotation unwrap ternaries - Remove Go short_var_declaration no-op dispatch - Remove dead OCaml fallback chains in type/module extraction - Cache Kotlin name node to avoid repeated re-lookup - Remove JS redundant pathNode/handlerNode guard - Remove C/C++ dead inner===node checks (8 sites) - Combine Lua duplicate extractFunction/extractLocalFunction - Combine Haskell 3 identical switch cases via fall-through - Remove OCaml/Zig no-op switch cases - Fold C# predefined_type into shared condition - Replace Elixir runtime set lookup with explicit switch cases - Remove ObjC tautological/dead guards - Remove Rust redundant namedChildCount on identifier nodes - Enrich fixtures across 19 languages to improve branch coverage - Add inline tests for TS declaration mode and Go gin routes - Branch coverage: 60.5% → 64.04% (meets 64% threshold)
3a82586 to
38d5f61
Compare
Replace all toBeGreaterThanOrEqual(0) no-op assertions with precise expectations: - Zig imports: toBe(0) — grammar doesn't produce BUILTIN nodes - OCaml imports: toBe(0) — grammar doesn't produce open_statement - ObjC type refs: toBeGreaterThan(0) — fixture produces type refs - TS cast refs: toBe(0) — as/assertion use primitives, not type_identifier - C return refs: toBe(0) — primitive_specifier, not type_identifier - C sizeof refs: toBe(0) — parsed as parenthesized_expression - C++ cast refs: toBe(0) — named casts produce pointer_declarator - Rust field refs: toBe(0) — f64 is primitive, not type_identifier Each assertion now documents why the count is what it is.
# Conflicts: # tests/extractors/__snapshots__/core.test.ts.snap
- haskell: remove class/instance decls that produce empty-name symbols - elixir: remove defmacro addition that diluted callerSymbol ratio - javascript: remove extra route calls that diluted callerSymbol ratio - objc: remove cast/var in category impl with unresolved enclosingSymbol
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #173 +/- ##
==========================================
+ Coverage 83.26% 84.49% +1.23%
==========================================
Files 83 83
Lines 8705 8683 -22
Branches 2733 2714 -19
==========================================
+ Hits 7248 7337 +89
+ Misses 1457 1346 -111 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Replace single-file inline parse() tests with per-scenario fixture files.
Each test scenario now has its own .{ext} file under tests/fixtures/{lang}/,
enabling exact assertions without aggregate checks.
- ~170 focused fixture files across 23 languages
- Each describe block loads one fixture, one concern
- Assertions test exact expected output, not aggregates
- sample.{ext} files preserved for health tests
- Haskell extractor: skip anonymous nodes to fix class keyword collision
- Elixir extractor: resolve callerSymbol for defmacro/defmacrop
- ObjC extractor: add category_implementation to symbol node types
225 scenario tests + 168 health tests = 1477 total, all passing.
Branch coverage: 68.16% (threshold: 64%).
Add targeted fixtures to cover new/changed source lines that Codecov's patch check flagged as uncovered: - elixir: guard-delegate.ex exercises defguard/defdelegate no-op cases - elixir: macro-callref.ex exercises defmacro callerSymbol resolution - objc: category-implementation.m exercises category_implementation case
This was referenced Mar 11, 2026
Merged
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
Deep crawl of all 23 language extractors to identify and remove unnecessary code conditionals/branches, followed by test fixture enrichment to improve branch coverage.
Extractor refactoring (14 files)
HIGH — Duplicate work / dead branches removed
extractVariable/SizeofTypeRefs— removed duplicateextractTypeNamecalls that were already performed insidecreateTypeRefEmittershort_var_declaration— removed no-op function dispatch (calledextractGoVarTypeRefswhich immediately exited for this node type)isNodeExported— removed 2 dead checks (.children.some()and.text.startsWith()) that could never fire after theexport_statementtype checkMEDIUM — Dead else-branches / redundant guards
type_annotationunwrap ternaries where one branch was always dead; removed dead guard inextractTsTypeAssertionRefextractTypeDefinitionandextractModuleDefinitionchildForFieldName('name')re-lookup on every.find()iteration!pathNode || !handlerNodeguard (guaranteed by prior length check)inner === nodechecks inextractDeclaratorNameandextractInnermostIdentifier(8 sites total — children can never equal their parent)LOW — Dead code / style duplication
extractLocalFunction(identical toextractFunction); combined switch casesnewtype,type_alias,data_type) via fall-throughvalue_definition,ContainerDecl)predefined_typeinto sharedreturn typeNode.textconditionELIXIR_DEFINITION_KEYWORDSset lookup with 5 explicit no-op switch cases; removed dead!calleeRawguardif (superName)guard; removed dead!selectorNode && !receiverNodeguardnamedChildCount === 0onidentifiernodes (always leaf nodes)Test coverage improvements
.d.ts) and Go gin routes (all 8 HTTP methods)Test results