Commit Graph
12 Commits
Author SHA1 Message Date
Thom Lamb 30f451d80c feat(sonar): Add SonarQube static analysis and code coverage setup
SonarQube Analysis / sonarqube (pull_request) Successful in 5m37s
Establishes tooling to systematically analyze and address technical debt.

This includes:
- `scan-sonar.ps1`: An orchestration script for local SonarQube scans with coverage.
- `Directory.Build.props`: Integrates SonarAnalyzer.CSharp for static analysis during build.
- `coverlet.runsettings`: Configures code coverage collection using Coverlet.
- `.claude/settings.local.json`: Adds permissions for AI to query SonarQube and local dev status.
2026-05-19 17:17:41 -05:00
Thom LambandClaude Opus 4.7 e01cfae359 perf+docs: fix IsValid allocation regression and document FilterGroup asymmetry
Code review follow-up on 6f85358:

- CalculationFilterGroup.IsValid() previously called GetValidFilters().Any(),
  which materialized a full filtered List<CalculationFilter> just to check
  existence. Reimplement directly as Filters.Any(x => x.IsValid()) so
  IsValid() recovers its pre-refactor O(1) early-exit behavior without
  allocations. GetValidFilters() remains for callers that need the full
  materialized list.

- QueryConfigExtensions.GetAllColumnIds line 16 uses FilterGroup (not
  CalculationFilterGroup), which pre-filters in its JsonConstructor and
  has no GetValidFilters() method. Add a comment to document the
  intentional asymmetry between line 14 and line 16.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 17:01:08 -05:00
Thom LambandClaude Opus 4.7 6f85358f63 refactor: address S2365 collection-copying property getters
Resolves SonarQube S2365 x3.

CalculationFilterGroup (Snowflake + SqlServer): the `Filters` getter
ran .Where(...).ToList() on every access. Convert to a plain
auto-property holding the raw collection plus a `GetValidFilters()`
method that does the filtering. Update internal IsValid() and the two
QueryConfigExtensions callers to use the new method.

HierarchicalData.AllChildData: part of the IHierarchicalData interface
and JSON-serialized; the transformation IS the property's contract.
Suppress S2365 with justification rather than refactor -- same pattern
as S3875.

Behavior change: CalculationFilterGroup JSON output now serializes the
raw filter collection rather than the pre-filtered one. Round-trip is
preserved; callers needing the filtered view must call GetValidFilters().

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 16:55:13 -05:00
Thom LambandClaude Opus 4.7 f96161a664 test(pgsql): align CommandVisitorTests namespace and drop dead fallback
Code review follow-up on acfe29e:
- Switch namespace to Strata.SqlTools.SqlBreakdown.Tests.PostgreSql to
  match the dominant convention in the sibling test folder.
- Remove the unreachable SqlServer.CommandVisitor fallback in the
  reflection helper. The Assert.That guard alone is enough to surface
  a future regression.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 16:39:31 -05:00
Thom LambandClaude Opus 4.7 acfe29ee98 fix(pgsql): make CommandVisitor parameter index instance-scoped
Resolves SonarQube S2696 in CommandVisitor.cs.

The static _parameterIndex field was mutated from an instance method,
causing every new CommandVisitor to inherit the previous instance's
counter and never reset. Parameter indices now restart at $1 per
visitor, which is the intended PostgreSQL behavior.

Adds CommandVisitorTests.TwoVisitors_HaveIndependentParameterIndices to
lock in the contract via reflection (FormatParameterName is protected).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 16:21:17 -05:00
Thom LambandClaude Opus 4.7 e2bfe3906a fix(rules): suppress S3875 on intentional DSL operator==
Resolves SonarQube S3875 (BLOCKER) in Expression.Operators.cs.

The operator== returns a Comparison expression (DSL semantics), not a
bool. The existing CS0660/CS0661 pragma already documents this design;
the new SuppressMessage attribute makes the Sonar analyzer agree.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 15:48:29 -05:00
Thom LambandClaude Opus 4.7 af2c3e054f fix(linq2sql): remove unread _breakdown field from builder
Resolves SonarQube S4487 in LinqQueryBreakdownBuilder.cs.

The field was assigned in the constructor but never read. Grep across
the project confirmed no external references.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 15:42:38 -05:00
Thom LambandClaude Opus 4.7 986fdfc503 fix(rules): rename IVisitor.VisitNotEquals parameter to match impls
Resolves SonarQube S927 x2 in ExpressionVisitor.cs.

The interface parameter was named ``Equal`` on a ``VisitNotEquals`` method,
which is semantically wrong and forced implementations to mismatch.
Implementations already used ``notEqual``; rename the interface to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 15:19:10 -05:00
Thom LambandClaude Opus 4.7 41e98258bf docs: implementation plan for critical-tier SonarQube tech-debt sweep
Five-task plan implementing the 2026-05-19 spec: per-rule commits on the
existing fix/Sonarqube-Tech-Debt branch with build+test verification
between each. Notes one spec deviation discovered during plan-time
exploration (HierarchicalData.AllChildData is suppressed rather than
refactored — it's an interface contract member tied to JSON shape).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 14:58:24 -05:00
Thom LambandClaude Opus 4.7 6b461095c6 docs: spec for critical-tier SonarQube tech-debt sweep
Design doc covering the 8 BLOCKER/CRITICAL non-S3776 issues across six
projects. Approach is a pragmatic mix: fix where the rule reflects a
real defect, suppress with justification where the rule conflicts with
deliberate design (DSL operator==).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 14:24:24 -05:00
Thom Lamb 8b0368e810 test: fix SqlBreakdown tests project
SonarQube Analysis / sonarqube (push) Failing after 3m21s
2026-05-15 13:39:14 -05:00
Thom Lamb 5e467bcc9c chore: initial git load of code space 2026-05-12 08:52:33 -05:00