You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Create a Docs/architecture.md covering the LSP server's overall architecture, component relationships, analysis strategy, and key design decisions — especially the deliberate choice of syntax-only analysis in the diagnostics layer.
Background
The repo has a Docs/ directory with feature-level design docs (attribute completions, E2E testing) but no central architecture document. The README describes what the server does and its repository structure, but not why the architecture is the way it is. Key design decisions are currently captured only in code comments.
During the implementation of trigger payload validation (#42, PR #49), a significant question arose: should the diagnostics validators use Roslyn's semantic model (CSharpCompilation + SemanticModel) or syntax-only analysis (CSharpSyntaxTree.ParseText)?
The decision was syntax-only, for reasons that should be documented as an architecture decision record so future contributors don't re-investigate the same trade-off.
Proposed Content
1. Component Overview
Server architecture: handlers, validators, services, stores
VS Code extension: lifecycle, file watching, connection merging
SdkIndex: assembly analysis and metadata management
How components interact (handler → validator → SdkIndex flow)
2. Analysis Strategy: Syntax-Only vs. Semantic Model
Current state:
CodeLensHandler, HoverHandler, CompletionHandler, and TextDocumentSyncHandler create CSharpCompilation with SDK assembly references to get SemanticModel for symbol resolution
All diagnostic validators (AttributeValidator, ConnectionConfigValidator, TriggerPayloadValidator) use syntax-only analysis via CSharpSyntaxTree.ParseText — no compilation, no references
Design decision: diagnostics use syntax-only analysis
Factor
Syntax-only
Semantic model
Latency
~1-5ms per file
~50-500ms per file
Dependencies
None — just parse text
Must load all referenced assemblies
Failure modes
Cannot fail
Assembly resolution can fail silently
What it resolves
Token text, tree structure
Types, symbols, overloads, using resolution
Why syntax-only is the right choice for diagnostics:
Diagnostics run on every keystroke via LSP; latency budget is tight
The SDK's target audience writes straightforward Azure Functions code — using System.Text.Json; at the top, JsonSerializer.Deserialize<T>(body) in the method body
The edge cases where syntax-only fails (aliased types, local type shadows, same-named types in different namespaces) are addressed through heuristics: namespace-gated serializer detection, local type shadow scanning, global:: normalization, conditional access rejection
The heuristic cost is a few extra lines of code with ~0ms runtime impact, vs. 100ms+ for compilation on every keystroke
Unqualified type matching by simple name may be incorrect if the SDK contains same-named types in different namespaces (none exist today)
CSDK204 checks naming convention (EndsWith("TriggerPayload")) rather than type hierarchy — intentional since syntax analysis cannot inspect inheritance
3. Diagnostic Validator Architecture
IDiagnosticValidator interface and registration
Priority chain in TriggerPayloadValidator (CSDK203 → CSDK201 → CSDK202 → match → CSDK204 → CSDK200)
Summary
Create a
Docs/architecture.mdcovering the LSP server's overall architecture, component relationships, analysis strategy, and key design decisions — especially the deliberate choice of syntax-only analysis in the diagnostics layer.Background
The repo has a
Docs/directory with feature-level design docs (attribute completions, E2E testing) but no central architecture document. The README describes what the server does and its repository structure, but not why the architecture is the way it is. Key design decisions are currently captured only in code comments.During the implementation of trigger payload validation (#42, PR #49), a significant question arose: should the diagnostics validators use Roslyn's semantic model (
CSharpCompilation+SemanticModel) or syntax-only analysis (CSharpSyntaxTree.ParseText)?The decision was syntax-only, for reasons that should be documented as an architecture decision record so future contributors don't re-investigate the same trade-off.
Proposed Content
1. Component Overview
2. Analysis Strategy: Syntax-Only vs. Semantic Model
Current state:
CodeLensHandler,HoverHandler,CompletionHandler, andTextDocumentSyncHandlercreateCSharpCompilationwith SDK assembly references to getSemanticModelfor symbol resolutionAttributeValidator,ConnectionConfigValidator,TriggerPayloadValidator) use syntax-only analysis viaCSharpSyntaxTree.ParseText— no compilation, no referencesDesign decision: diagnostics use syntax-only analysis
Why syntax-only is the right choice for diagnostics:
using System.Text.Json;at the top,JsonSerializer.Deserialize<T>(body)in the method bodyglobal::normalization, conditional access rejectionIDiagnosticValidatorinterface can be extended to optionally accept a semantic model — but this is an optimization, not a correctness requirementKnown limitations (acceptable):
EndsWith("TriggerPayload")) rather than type hierarchy — intentional since syntax analysis cannot inspect inheritance3. Diagnostic Validator Architecture
IDiagnosticValidatorinterface and registrationTriggerPayloadValidator(CSDK203 → CSDK201 → CSDK202 → match → CSDK204 → CSDK200)ValidatorHelpersSdkIndex4. Cross-references
Docs/Acceptance Criteria
Docs/architecture.mdexists with sections above