Skip to content

Commit ed49fd6

Browse files
csharpfritzCopilot
andauthored
feat: BWFC013/014 analyzers, architecture guide, CI docs (#487)
* feat: Add BWFC013/014 analyzers, architecture guide, and CI docs Analyzer Expansion: - BWFC013: Detects Response.Write/WriteFile/Clear/Flush/End usage - BWFC014: Detects Request.Form/Cookies/Headers/Files/QueryString access - Both produce WARNING diagnostics with guidance-only code fixes (TODO comments) - 21 new tests (111 total, all passing) Documentation: - dev-docs/ANALYZER-ARCHITECTURE.md: Contributor guide for building analyzers - docs/Migration/Analyzers.md: BWFC013/014 entries, CI/CD integration section, .editorconfig severity tuning, prioritization guide Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs(ai-team): Analyzer sprint 1 complete orchestration & decision logs merged Session: 2026-03-20T14-18-05Z-analyzer-sprint1 Requested by: Scribe Changes: - Orchestration logs for Cyclops (BWFC013/014 analyzers, 6 files, 111 tests) and Beast (architecture guide, 579 lines) - Session log for analyzer sprint 1 execution - Merged 10 decision inbox files decisions.md (BWFC013/014 IDs, analyzer docs, deprecation guidance, ASHX/AXD middleware, RouteData fix, component audit, navigation UX, sample pages, middleware testing) - Deleted all inbox files after merge - Appended team updates to Cyclops, Beast, Forge, Jubilee, Rogue history.md files - PR #487 opened on upstream targeting dev branch * feat: bundle analyzers in main NuGet + add -Prescan switch to L1 script Task 1: Added ProjectReference from BlazorWebFormsComponents to BlazorWebFormsComponents.Analyzers with OutputItemType=Analyzer so consumers get Roslyn analyzers automatically via the main NuGet package. Task 2: Added -Prescan switch to bwfc-migrate.ps1 that scans source .cs files for 9 BWFC analyzer patterns (BWFC001-005, 011-014) and outputs a JSON summary report without performing any migration. Includes human-readable breakdown via Write-Host. Build: 0 errors, 111 analyzer tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * ci: add Roslyn analyzer tests to build and squad-ci workflows - build.yml: restore, build, run, upload, and publish analyzer test results - squad-ci.yml: replace placeholder with dotnet restore/build/test for both suites - Add setup-dotnet step to squad-ci.yml for .NET 10.0.x Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use DetectEndOfLine() for cross-platform CI compatibility All 4 code fix providers (BWFC001, BWFC004, BWFC013, BWFC014) used hardcoded \r\n in SyntaxFactory.EndOfLine(), causing test failures on Linux CI where source strings use \n. - Add SyntaxExtensions.DetectEndOfLine() helper that reads line endings from the existing syntax tree - Replace hardcoded \r\n with root.DetectEndOfLine() in all 4 code fix providers - Replace foreach+if with LINQ .Where() (CodeQL suggestion) All 111 analyzer tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use DetectEndOfLine() in MissingParameterAttributeCodeFixProvider The using directive insertion used SyntaxFactory.CarriageReturnLineFeed which hardcodes CRLF, failing on Linux CI where source uses LF. Replace with newRoot.DetectEndOfLine() for cross-platform compatibility. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 83e0f45 commit ed49fd6

35 files changed

Lines changed: 2482 additions & 806 deletions

.github/workflows/build.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ jobs:
4242
dotnet restore src/BlazorWebFormsComponents/BlazorWebFormsComponents.csproj
4343
dotnet restore src/BlazorWebFormsComponents.Test/BlazorWebFormsComponents.Test.csproj
4444
dotnet restore samples/AfterBlazorServerSide/AfterBlazorServerSide.csproj
45+
dotnet restore src/BlazorWebFormsComponents.Analyzers.Test/BlazorWebFormsComponents.Analyzers.Test.csproj
4546
dotnet restore scripts/GenerateHealthSnapshot/GenerateHealthSnapshot.csproj
4647
4748
- name: Build library
@@ -50,12 +51,18 @@ jobs:
5051
- name: Build test project
5152
run: dotnet build src/BlazorWebFormsComponents.Test/BlazorWebFormsComponents.Test.csproj --configuration Release --no-restore
5253

54+
- name: Build analyzer tests
55+
run: dotnet build src/BlazorWebFormsComponents.Analyzers.Test/BlazorWebFormsComponents.Analyzers.Test.csproj --configuration Release --no-restore
56+
5357
- name: Build server-side sample
5458
run: dotnet build samples/AfterBlazorServerSide/AfterBlazorServerSide.csproj --configuration Release --no-restore
5559

5660
- name: Run tests
5761
run: dotnet test src/BlazorWebFormsComponents.Test/BlazorWebFormsComponents.Test.csproj --configuration Release --no-build --verbosity normal --logger "trx;LogFileName=test-results.trx" --results-directory src/BlazorWebFormsComponents.Test/TestResults
5862

63+
- name: Run analyzer tests
64+
run: dotnet test src/BlazorWebFormsComponents.Analyzers.Test/BlazorWebFormsComponents.Analyzers.Test.csproj --configuration Release --no-build --verbosity normal --logger "trx;LogFileName=analyzer-test-results.trx" --results-directory src/BlazorWebFormsComponents.Analyzers.Test/TestResults
65+
5966
- name: Generate health snapshot
6067
run: dotnet run --project scripts/GenerateHealthSnapshot/GenerateHealthSnapshot.csproj --configuration Release -- ${{ github.workspace }} ${{ github.workspace }}/health-snapshot.json
6168

@@ -73,6 +80,13 @@ jobs:
7380
name: test-results
7481
path: src/BlazorWebFormsComponents.Test/TestResults/*.trx
7582

83+
- name: Upload analyzer test results
84+
uses: actions/upload-artifact@v4
85+
if: always()
86+
with:
87+
name: analyzer-test-results
88+
path: src/BlazorWebFormsComponents.Analyzers.Test/TestResults/*.trx
89+
7690
- name: Publish test results
7791
uses: dorny/test-reporter@v2
7892
if: always()
@@ -81,3 +95,12 @@ jobs:
8195
path: src/BlazorWebFormsComponents.Test/TestResults/*.trx
8296
reporter: dotnet-trx
8397
fail-on-error: true
98+
99+
- name: Publish analyzer test results
100+
uses: dorny/test-reporter@v2
101+
if: always()
102+
with:
103+
name: Analyzer Test Results
104+
path: src/BlazorWebFormsComponents.Analyzers.Test/TestResults/*.trx
105+
reporter: dotnet-trx
106+
fail-on-error: true

.github/workflows/squad-ci.yml

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@ jobs:
1717
steps:
1818
- uses: actions/checkout@v4
1919

20+
- name: Setup .NET
21+
uses: actions/setup-dotnet@v4
22+
with:
23+
dotnet-version: '10.0.x'
24+
2025
- name: Build and test
2126
run: |
22-
# TODO: Add your dotnet build/test commands here
23-
# Go: go test ./...
24-
# Python: pip install -r requirements.txt && pytest
25-
# .NET: dotnet test
26-
# Java (Maven): mvn test
27-
# Java (Gradle): ./gradlew test
28-
echo "No build commands configured — update squad-ci.yml"
27+
dotnet restore
28+
dotnet build --configuration Release --no-restore
29+
dotnet test src/BlazorWebFormsComponents.Test/BlazorWebFormsComponents.Test.csproj --configuration Release --no-build --verbosity normal
30+
dotnet test src/BlazorWebFormsComponents.Analyzers.Test/BlazorWebFormsComponents.Analyzers.Test.csproj --configuration Release --no-build --verbosity normal

.squad/agents/beast/history.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,3 +497,69 @@ Updated `.squad/skills/migration-standards/SKILL.md` to add new section at end:
497497
- Created docs/ValidationControls/BaseValidator.md
498498
- Created docs/ValidationControls/BaseCompareValidator.md
499499
- Updated mkdocs.yml (Validation Controls section)
500+
501+
### Analyzer Architecture & Expansion Documentation (Feature/analyzer-sprint1)
502+
503+
**Delivered:** Comprehensive analyzer contributor guide and expanded rule documentation for BWFC013 and BWFC014 rules.
504+
505+
**Files created/updated:**
506+
1. **dev-docs/ANALYZER-ARCHITECTURE.md** (18.7 KB, new) Contributor guide for developing new Roslyn analyzers
507+
2. **docs/Migration/Analyzers.md** (updated) Added BWFC013 (Response Object Usage) and BWFC014 (Request Object Usage) rule documentation
508+
509+
**ANALYZER-ARCHITECTURE.md content:**
510+
- **Project Layout** File naming convention, rule ID assignment, directory structure (Analyzers/ and Analyzers.Test/)
511+
- **DiagnosticAnalyzer anatomy** Minimum viable structure with DiagnosticDescriptor, Initialize(), SyntaxKind callbacks, SeverityLevels (Hidden/Info/Warning/Error)
512+
- **CodeFixProvider anatomy** BatchFixer pattern, RegisterCodeFixesAsync, trivia preservation, async best practices
513+
- **Testing strategy** CSharpAnalyzerTest/CSharpCodeFixTest patterns, stub types for external dependencies ({|#N:code|} markers), positive/negative/edge cases
514+
- **Common pitfalls** Trivia handling (EndOfLine between comment/semicolon), null guards on ancestor traversal, SyntaxKind selection mistakes, string comparisons vs syntax API, message format arguments
515+
- **PR checklist** Analyzer implementation (7 items), CodeFixProvider (8 items), Testing (6 items), Documentation (5 items), Integration (3 items)
516+
- **Reference implementation** Points to ResponseRedirectAnalyzer as working example
517+
- **Build/test commands** dotnet build, test, pack workflows
518+
519+
**Analyzers.md updates:**
520+
- **Updated summary table** Added BWFC013 and BWFC014 to rule matrix
521+
- **BWFC013: Response Object Usage** Detects Response.Write(), WriteFile(), Clear(), Flush(), End()
522+
- Mapping table: Web Forms method Blazor equivalent (markup rendering, FileResult, not needed, not needed, early return)
523+
- Before/after example: HTML export page markup-based rendering
524+
- Recommended patterns: component state + markup for write, minimal API endpoint with FileResult for writeFile
525+
- **BWFC014: Request Object Usage** Detects Request.Form[], Cookies[], Headers[], Files, QueryString[], ServerVariables[]
526+
- Mapping table: Request collection Blazor equivalent (form binding, HttpContextAccessor, InputFile, nav params, etc.)
527+
- Before/after example: Page_Load with multiple Request accesses component with recommended patterns
528+
- Recommended patterns: route parameters (QueryString), @bind (Form), HttpContextAccessor (Cookies/Headers for Blazor Server), InputFile (Files)
529+
- **"Using Analyzers in CI/CD" section** (new) .editorconfig per-rule severity settings, dotnet build integration, grep for violations in CI scripts
530+
- **"Prioritization Guide: Which Rules to Fix First"** (new) Phase 1 (Blocking: BWFC001, BWFC003, BWFC004, BWFC011), Phase 2 (Data: BWFC002, BWFC005, BWFC014), Phase 3 (Output: BWFC013, BWFC012, BWFC010)
531+
532+
**Format & style:**
533+
- Analyzer guide written for experienced C# developers contributing new rules (Cyclops' audience)
534+
- Analyzers.md entries written for Web Forms developers learning to interpret/fix violations
535+
- All code examples are complete and compilable (test-driven)
536+
- Admonitions (!!! note, !!! warning, !!! tip) for actionable insights
537+
- Before/After pairs show real Web Forms patterns and Blazor migrations
538+
- Tables for quick reference (SyntaxKind callbacks, mapping tables, phase priorities)
539+
- Consistent with existing BWFC doc style (Deprecation Guidance, MigratingAshxHandlers)
540+
541+
**MkDocs verification:**
542+
- Ran python -m mkdocs build --strict 0 errors, 54.08s build time
543+
- Unshipped analyzer notes already present in AnalyzerReleases.Unshipped.md (BWFC013, BWFC014 added by Cyclops in advance)
544+
- No documentation links or cross-references broken
545+
546+
**Design decisions:**
547+
- ANALYZER-ARCHITECTURE.md placed in dev-docs/ (developer-only, not end-user docs) vs docs/ (migration user-facing)
548+
- Prioritization guide ordered by business impact (blocking patterns first) vs alphabetical, with rationale for each phase
549+
- CI/CD section emphasizes dotnet build + .editorconfig as the primary integration point, with note that detailed CI templates are "available separately"
550+
- Request.Form[] @bind example is the most direct mapping; QueryString examples show both route parameters and NavigationManager.Uri approaches
551+
552+
**Audience understanding:**
553+
- Analyzer rules address code-behind patterns (BWFC001BWFC005: property/state/event patterns; BWFC010BWFC014: specific object usage)
554+
- Developers see these rules in Visual Studio's Error List after L1 migration script + L2 Copilot transforms
555+
- Rules guide developers from "code compiles but behaves wrong" (blindspots) to "code compiles and works correctly" (full migration)
556+
- Prioritization guide helps developers allocate effort, fixing high-impact rules first to unblock testing/UAT
557+
558+
**Branch:** eature/analyzer-sprint1
559+
**Tests:** All analyzer tests in Analyzers.Test/ pass (no new analyzer implementations in this doc-only sprint)
560+
**Verified:** MkDocs build passes strict mode, no broken links or syntax errors in markdown
561+
562+
563+
564+
**Team update (2026-03-20):** Analyzer architecture guide (579 lines) + expanded Analyzers.md (+363 lines). Deprecation Guidance docs (#438, 32 KB). BaseValidator/BaseCompareValidator base class docs. MkDocs strict build clean. PR #487 opened on upstream. decided by Beast
565+

.squad/agents/cyclops/history.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,3 +468,35 @@ Team update: ModalPopupExtender and CollapsiblePanelExtender implemented by Cycl
468468
3. **CS1503** in GridView/Selection.razor — SelectedIndexChanged handler took int but component expects EventCallback<GridViewSelectEventArgs>. Changed handler (and code example) to accept GridViewSelectEventArgs.
469469

470470
**Key insight:** Always check the base class parameter types — ImageButton inherits OnClick from ButtonBaseComponent which uses EventArgs, not MouseEventArgs. GridView's SelectedIndexChanged was recently changed to GridViewSelectEventArgs (matching Web Forms behavior).
471+
472+
### BWFC013 + BWFC014 Analyzer Implementation (2026-03-20)
473+
474+
**Summary:** Implemented two new Roslyn analyzers following established patterns (ResponseRedirect/Session as templates).
475+
476+
- **BWFC013 ResponseObjectUsageAnalyzer:** Detects Response.Write(), WriteFile(), Clear(), Flush(), End() via InvocationExpression + ImmutableHashSet method matching. Code fix replaces with TODO comment.
477+
- **BWFC014 RequestObjectUsageAnalyzer:** Detects Request.Form/Cookies/Headers/QueryString/ServerVariables["key"] via ElementAccessExpression, and Request.Files via SimpleMemberAccessExpression. Code fix replaces with TODO comment.
478+
- Both analyzers use xpressionText.EndsWith(".Response") / .EndsWith(".Request") pattern to match his.Response, HttpContext.Current.Response, and any *.Response prefix.
479+
- 21 new tests (10 for BWFC013, 11 for BWFC014): 5+6 positive, 3+3 negative, 2+2 code fix tests.
480+
- Updated AllAnalyzersIntegrationTests ExpectedIds and analyzer count (810).
481+
- Updated AnalyzerReleases.Unshipped.md with both rules.
482+
- All 111 tests pass (90 existing + 21 new).
483+
484+
**Key patterns:** Code fix uses EmptyStatement with SyntaxFactory.EndOfLine("\r\n") between comment trivia and semicolon. BWFC014 registers for both ElementAccessExpression (indexed properties) and SimpleMemberAccessExpression (direct properties like Files), with parent-check to avoid double-reporting.
485+
486+
487+
**Team update (2026-03-20):** BWFC013/BWFC014 analyzers + architecture (6 files, 21 tests, 111 passing, commit b267b854). PR #487 opened on upstream. Next analyzer ID: BWFC015. decided by Cyclops
488+
489+
### NuGet Analyzer Integration + L1 Prescan Switch (2026-03-20)
490+
491+
**Summary:** Two tasks completed on feature/analyzer-sprint1:
492+
493+
1. **NuGet Analyzer Integration** — Added ProjectReference from BlazorWebFormsComponents.csproj to BlazorWebFormsComponents.Analyzers.csproj with `PrivateAssets="all" ReferenceOutputAssembly="false" OutputItemType="Analyzer"`. Consumers now get Roslyn analyzers automatically when referencing the main NuGet package.
494+
495+
2. **L1/L2 Pipeline Pre-Scan** — Added `-Prescan` switch to `bwfc-migrate.ps1`. Scans source .cs files for 9 BWFC analyzer patterns (BWFC001-005, 011-014) and outputs JSON summary with file-level detail + human-readable breakdown. Early return — no migration transforms executed.
496+
497+
**Verification:** Build succeeds (0 errors), all 111 analyzer tests pass, prescan tested against src/ (1,092 matches across 176 files).
498+
499+
500+
### CI Workflow: Analyzer Tests Added (2026-03-20)
501+
502+
**Summary:** Updated .github/workflows/build.yml to restore, build, run, upload, and publish analyzer test results alongside the existing unit tests. Also replaced the squad-ci.yml placeholder with real dotnet restore/build/test commands covering both test suites, including setup-dotnet for .NET 10. YAML validated with Python yaml parser.

.squad/agents/forge/history.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,3 +430,7 @@ Jeff directed a design pivot: replace custom `[HandlerRoute]` attribute + `MapBl
430430
**Impact:** ~100 fewer lines of production code (400 vs 500). One fewer file (`HandlerRouteAttribute.cs` gone). Issue 2 (routing) shrinks from Size S to XS. Estimated timeline: 2-3 weeks (was 3-4). Adapter layer (`HttpHandlerContext`, `HttpHandlerResponse`, `HttpHandlerServer`) completely unchanged.
431431

432432
**Learning:** Original §7.3 rejected Minimal API because "they require completely different code structure." Wrong framing — Jeff's insight is to use Minimal API as *registration and dispatch infrastructure* while keeping the `HttpHandlerBase` class structure intact. The handler code developers write is nearly identical. Only the plumbing underneath changes.
433+
434+
435+
**Team update (2026-03-20):** Component audit recommendations merged (March 2026 prioritization guide). 52/54 components at 100% health (96.3%). Tier 1 quick wins identified: FileUpload properties, infrastructure docs, View docs, ScriptManager decision. decided by Forge
436+

.squad/agents/jubilee/history.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,7 @@
205205
- **Build verified:** 0 errors.
206206

207207

208+
209+
210+
**Team update (2026-03-20):** Navigation UX improvements (alphabetical sort, AJAX collapse on desktop) + standalone sample pages for Content, ContentPlaceHolder, View. ComponentCatalog updated. decided by Jubilee
211+

.squad/agents/rogue/history.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,3 +304,7 @@ Test file: `src/BlazorWebFormsComponents.Test/UpdatePanel/ContentTemplateTests.r
304304
- Tests: src/BlazorWebFormsComponents.Test/Handlers/*.cs (5 test files)
305305
- Build: dotnet build src\BlazorWebFormsComponents.Test\BlazorWebFormsComponents.Test.csproj validates all
306306
- Run handler tests: dotnet test --filter "FullyQualifiedName~Handlers"
307+
308+
309+
**Team update (2026-03-20):** Middleware integration testing pattern established (TestServer + AspxRewriteMiddlewareTests.cs, 46 tests). Microsoft.AspNetCore.TestHost added to test dependencies. decided by Rogue
310+

0 commit comments

Comments
 (0)