Skip to content

test: fill critical coverage gaps in type checking, config, and diagnostics - #62

Merged
R-unic merged 3 commits into
masterfrom
test/coverage-critical-paths
Jul 24, 2026
Merged

test: fill critical coverage gaps in type checking, config, and diagnostics#62
R-unic merged 3 commits into
masterfrom
test/coverage-critical-paths

Conversation

@R-unic

@R-unic R-unic commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

Ran dotnet test -c Release --collect:"XPlat Code Coverage" --settings Loom.Testing/coverlet.runsettings and targeted the largest real gaps by absolute missed-line count, not just percentage, per direction to focus on files with substantial branching logic and aim for ~90%+ rather than chasing every last percent everywhere.

File Before After
TypeNarrower.cs 90.6% 95.3%
TypeInferrer.cs 80.7% 81.4%
Resolver.cs 96.8% 97.3%
LuauGenerator.cs 90.0% 100%
DiagnosticBag.cs 75.0% 91.7%
Config/ConfigReader.cs 72.7% 86.4%
Config/ProjectTypeConverter.cs 75.0% 100%
CompilationUnit.cs 88.0% 100%
Text/TextSpan.cs 45.5% 100%
Text/Location.cs 75.0% 100%

Highlights:

  • TypeNarrower's union-narrow-by-element-index path (arr[i] == literal where arr is a union of array types) and logical AND/OR merge-of-unnarrowed-states path were completely untested.
  • Loom.Config had no dedicated test file at all — added ConfigReaderTest.cs covering LocateFromDirectory's null-return branches, the ProjectDirectory-into-Files.SourceDirectory/OutputDirectory path-joining, and ProjectTypeConverter's valid/invalid parsing.
  • CompilationUnit.Compile()'s declaration-file → Globals population loop had zero coverage — no existing test compiled a project with an actual .d.loom file present.
  • Found and fixed a mislabeled test: DiagnosticBagTest.FailFast_WhenTrue_ExitsOnError actually set FailFast = false (not true), never restored the global static afterward (real cross-test pollution risk), and never exercised the exit path at all (Environment.Exit can't be tested in-process). Renamed to reflect what it actually verifies and wrapped in try/finally.
  • LuauGenerator.cs's invalid luau_name attribute diagnostic (non-string-literal argument) had no test.

Known remaining gaps, left deliberately:

  • Compiler.cs's top-level exception-recovery catch block — a defensive catch-all that's fragile to trigger deliberately without contriving an internal crash.
  • Some of TypeInferrer.cs's deepest generic-matching branches and InvocationMacroReference.cs's element-access/union-provider-resolution paths — these directly overlap the generic-function-argument-inference work issue Infer instantiated function types #30 is about to touch, so covering them now would likely need rewriting again shortly after.

Test plan

  • dotnet build — succeeds, no warnings
  • dotnet test — 1845/1845 pass (1809 existing + 36 new)
  • Re-ran coverage after adding tests and confirmed each targeted file's line-rate actually moved (not just that new tests pass)

🤖 Generated with Claude Code

…ostics

Ran coverage collection and targeted the largest real gaps rather than
chasing percentage alone: TypeNarrower's union-narrow-by-element-index
path (90.6% -> 95.3%), TypeInferrer's union/intersection arity-mismatch
and repeated-binding paths, Resolver's scattered error branches, and
LuauGenerator's invalid luau_name-attribute diagnostic (90% -> 100%).

Added Loom.Config test coverage from scratch (ConfigReader,
ProjectTypeConverter, LoomConfig -> FilesConfig path joining) and
CompilationUnit's declaration-file Globals population, both previously
untested (72.7%/75%/88% -> 86.4%/100%/100%).

DiagnosticBag.FailFast_WhenTrue_ExitsOnError was mislabeled: it set
FailFast to false (not true), never restored the static afterward
(real cross-test pollution risk on a global), and never exercised the
exit path at all - Environment.Exit can't be tested in-process. Renamed
it to reflect what it actually verifies and wrapped it in try/finally.

TextSpan (45.5% -> 100%) and Location (75% -> 100%) needed only their
missing operator/Equals overload cases. Compiler.cs's top-level
exception-recovery catch block and some InvocationMacroReference/
MacroExpander/TypeChecker generic-inference edge cases are left as
known remaining gaps - the former is a defensive catch-all that's
fragile to trigger deliberately, and TypeInferrer's deepest gaps
directly overlap the generic-function-argument inference issue #30 is
about to touch, so covering them now would likely be rewritten shortly
after.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@R-unic
R-unic merged commit 3e4d76a into master Jul 24, 2026
2 checks passed
@github-project-automation github-project-automation Bot moved this from Backlog to Done in Loom Release 1.0.0 Jul 24, 2026
@R-unic
R-unic deleted the test/coverage-critical-paths branch July 24, 2026 11:25
@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown

Qodana for .NET

261 new problems were found

Inspection name Severity Problems
RoslynAnalyzers Local functions cannot be test functions 🔴 Failure 2
Auto-property accessor is never used (private accessibility) 🔶 Warning 6
Auto-property accessor is never used (non-private accessibility) 🔶 Warning 5
Use preferred body style (convert into method or operator with preferred body style) 🔶 Warning 2
Non-accessed positional property (non-private accessibility) 🔶 Warning 2
Redundant cast 🔶 Warning 2
Suspicious type conversion or check 🔶 Warning 2
Redundant name qualifier 🔶 Warning 1
Redundant using directive 🔶 Warning 1
Type member is never used (private accessibility) 🔶 Warning 1
Unused local variable 🔶 Warning 1
Type member is never used (non-private accessibility) ◽️ Notice 92
Use preferred style of 'new' expression when created type is not evident ◽️ Notice 83
Member can be made private (non-private accessibility) ◽️ Notice 20
Invert 'if' statement to reduce nesting ◽️ Notice 5
Class is never instantiated (non-private accessibility) ◽️ Notice 4
Some values of the enum are not processed inside 'switch' statement ◽️ Notice 4
Use preferred style for trailing comma before new line in multiline lists ◽️ Notice 3
Auto-property can be made get-only (non-private accessibility) ◽️ Notice 3
RoslynAnalyzers The member referenced by the MemberData attribute returns untyped data rows ◽️ Notice 3
RoslynAnalyzers Do not use Enumerable methods on indexable collections ◽️ Notice 2
Property can be made init-only (non-private accessibility) ◽️ Notice 2
Auto-property can be made get-only (private accessibility) ◽️ Notice 1
RoslynAnalyzers Use concrete types when possible for improved performance ◽️ Notice 1
RoslynAnalyzers Use char overload ◽️ Notice 1
Dictionary lookup can be simplified with 'GetValueOrDefault' ◽️ Notice 1
'if-return' statement can be rewritten as 'return' statement ◽️ Notice 1
Foreach loop can be converted into LINQ-expression but another 'GetEnumerator' method will be used ◽️ Notice 1
Merge null/pattern checks into complex pattern ◽️ Notice 1
Redundant string interpolation ◽️ Notice 1
Replace with 'field' keyword ◽️ Notice 1
Add explicit 'return' or 'continue' before local functions ◽️ Notice 1
Some values of the enum are not processed inside 'switch' statement and are handled via default section ◽️ Notice 1
Tail recursive call can be replaced with loop ◽️ Notice 1
Type member is never accessed via base type (non-private accessibility) ◽️ Notice 1
Method return value is never used (non-private accessibility) ◽️ Notice 1
Literal length can be reduced by using verbatim string ◽️ Notice 1

☁️ View the detailed Qodana report

Detected 1 dependency

Third-party software list

This page lists the third-party software dependencies used in Loom

Dependency Version Licenses
Tomlyn 2.6.0 BSD-2-Clause
Contact Qodana team

Contact us at qodana-support@jetbrains.com

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.

1 participant