Track progress on SonarCloud findings for this project.
Addressed in commits af11135 and 37ca7b9 (2026-06-21):
✅ Completed
Security
Reliability (real bugs)
False positives (suppressed with justification)
Design / API quality
Maintainability
Test quality
❌ Pending
Breaking / high effort
Medium effort
Remaining SonarCloud findings (not yet triaged)
Notes
ExpressionShortcuts scope constraint
When refactoring code in files that use the Expressions.Shortcuts library (PartialBinder, BlockHelperFunctionBinder, etc.), variables created with Arg(...), Cast<T>(...), or New(...) must be declared in the same lexical block as the Call(() => ...) lambda that references them. Hoisting them to an outer scope causes runtime InvalidCastException or NullReferenceException because ExpressionShortcuts rewrites the lambda's expression tree at build time and out-of-scope references are not rewritten. Safe to hoist: CompilationContext.Args.BindingContext and CompilationContext.Args.EncodedWriter (these are parameter expressions, not new constant nodes).
Track progress on SonarCloud findings for this project.
Addressed in commits
af11135and37ca7b9(2026-06-21):✅ Completed
Security
timheuer/base64-to-fileCI action to full commit SHA (release.yml)NUGET_ORG_PUSH_KEYout of inlinerun:block intoenv:sectionRegexinstances inWhitespaceRemover.csReliability (real bugs)
== nullon unconstrained generic type parameters withEqualityComparer<T>.Default.Equals(value, default)inHtmlEncoder,HtmlEncoderLegacy,DictionarySlim,FixedSizeDictionary,GenericDictionaryAccessor,ReadOnlyGenericDictionaryAccessorFalse positives (suppressed with justification)
ReaderWriterLockSlimExtensions: lock IS released viaDisposableContainerinusing; not a bugIteratorBinder: swappingtemplate/ifEmptyfor theInversecase is intentionalPartialBinder: cast is a C# explicit operator onExpressionContainer<T>, not a runtime hierarchy castDesign / API quality
TextEncoderWrapperandClosureBuilder(IDisposable pool types with private constructors)IInternalObjectPoolPolicy<T>.Create()in all six pool policy types to eliminate method-name shadowingIndexOutOfRangeExceptionwithArgumentOutOfRangeExceptioninArguments.csandSubstring.csArray.Empty<Expression>()instead ofnullinHandlebarsExpressionVisitor[AttributeUsage(AttributeTargets.Class)]toFeatureOrderAttributeImmutableStack<T>pool field (intentional per-T instance)outcovariance toValueTypeGetterDelegate<T, TValue>ReflectionMemberAccessorprivate method lookupMissingBlockHelperDescriptor_enumeratorfieldreadonlyinExtendedEnumeratorifstatements inDelegatedMemberAliasProviderEndExpressionToken,StartExpressionToken,PartialBlockAccumulatorContextArgumentOutOfRangeExceptioninBlockHelperFunctionBinderexp→nodeinHandlebarsExpressionVisitor.Visit()to match base class signatureMaintainability
ProcessStatementfromWhitespaceRemover.ProcessTokens(cognitive complexity reduced; partial indentation logic preserved)HandleRawStartfromRawHelperAccumulator.ConvertTokens(cognitive complexity reduced)Compatibility.RelaxedHelperNaminginPathBinder,HelperConverter,HelperFunctionBinder,HandlebarsConfigurationAdapterTest quality
Assert.Equal(actual, expected)argument order inCustomConfigurationTestsnewmodifier to hiding method inFixedSizeDictionaryTests❌ Pending
Breaking / high effort
IDescriptor<TOptions>: type parameterTOptionsis declared but never used in the interface body. Removing it is a breaking API change requiring a major version bump.Tokenizer.cscognitive complexity = 76 (threshold: 15). Significant refactor; needs careful incremental extraction to avoid destabilizing the lexer.Medium effort
LiteralParser.cs: complexity above threshold; no known constraints, medium refactor.BlockHelperFunctionBinder.BindByRef: the nestedswitch/ifstructure is tied to expression-tree construction — naive extraction causes runtimeNullReferenceException. Needs a careful approach (see ExpressionShortcuts scope constraint note below).PartialBinder.VisitPartialExpression: complexity climbed with the partial-indentation feature. Any extraction must keepArg(...)/Cast<T>(...)variables scoped to theCall(() => ...)that uses them.ReusableStringWriter(IO/PolledStringWriter.cs) is not sealed; Sonar flags the IDisposable pattern on non-sealed classes that don't expose aprotected virtual Dispose(bool)to subclasses consistently. Evaluate whether sealing is appropriate or the pattern needs asealed override.Remaining SonarCloud findings (not yet triaged)
Notes
ExpressionShortcuts scope constraint
When refactoring code in files that use the
Expressions.Shortcutslibrary (PartialBinder,BlockHelperFunctionBinder, etc.), variables created withArg(...),Cast<T>(...), orNew(...)must be declared in the same lexical block as theCall(() => ...)lambda that references them. Hoisting them to an outer scope causes runtimeInvalidCastExceptionorNullReferenceExceptionbecause ExpressionShortcuts rewrites the lambda's expression tree at build time and out-of-scope references are not rewritten. Safe to hoist:CompilationContext.Args.BindingContextandCompilationContext.Args.EncodedWriter(these are parameter expressions, not new constant nodes).