docs: fill missing XML docs and strip tracking IDs from src comments

Clears CommentChecker findings in src/ (3,280 -> 209, the remainder being false
positives like PLC-5/IEEE-754/M0.0) by adding missing summaries/params/returns,
normalising inheritdoc usage, and removing Gitea/review tracking IDs while keeping
the rationale they annotated. Comment-only: comment-stripped sources are identical
to the parent commit.
This commit is contained in:
Joseph Doherty
2026-10-15 06:14:58 -04:00
parent ebcbd81fca
commit 826312befe
430 changed files with 4434 additions and 3923 deletions
@@ -31,64 +31,71 @@ public sealed class SqlServerDialect : ISqlDialect
/// <inheritdoc/>
public DbProviderFactory Factory => SqlClientFactory.Instance;
/// <summary>
/// T-SQL markers are <c>@</c>-prefixed — <c>ParameterMarker("k0")</c> is <c>"@k0"</c>.
/// </summary>
/// <param name="baseName">The bare base name.</param>
/// <returns>The <c>@</c>-prefixed marker.</returns>
// <summary>
// T-SQL markers are <c>@</c>-prefixed — <c>ParameterMarker("k0")</c> is <c>"@k0"</c>.
// </summary>
// <param name="baseName">The bare base name.</param>
// <returns>The <c>@</c>-prefixed marker.</returns>
/// <inheritdoc />
public string ParameterMarker(string baseName) => "@" + baseName;
/// <summary>
/// Identical to <see cref="ParameterMarker"/>: <c>Microsoft.Data.SqlClient</c> expects
/// <see cref="DbParameter.ParameterName"/> to carry the same <c>@</c> the statement does. (It also
/// accepts a bare name and prepends the <c>@</c> itself, but spelling it out keeps the parameter
/// collection readable in a profiler trace and matches what the SQL text says.)
/// </summary>
/// <param name="baseName">The bare base name.</param>
/// <returns>The <c>@</c>-prefixed bind name.</returns>
// <summary>
// Identical to <see cref="ParameterMarker"/>: <c>Microsoft.Data.SqlClient</c> expects
// <see cref="DbParameter.ParameterName"/> to carry the same <c>@</c> the statement does. (It also
// accepts a bare name and prepends the <c>@</c> itself, but spelling it out keeps the parameter
// collection readable in a profiler trace and matches what the SQL text says.)
// </summary>
// <param name="baseName">The bare base name.</param>
// <returns>The <c>@</c>-prefixed bind name.</returns>
/// <inheritdoc />
public string ParameterBindName(string baseName) => "@" + baseName;
/// <summary>
/// No-op. <c>SqlCommand</c> binds by name out of the box, so there is nothing SQL Server needs set on a
/// fresh command — the member exists for Oracle's <c>BindByName</c> (see
/// <see cref="ISqlDialect.ConfigureCommand"/>).
/// </summary>
/// <param name="command">The command to configure; untouched here.</param>
// <summary>
// No-op. <c>SqlCommand</c> binds by name out of the box, so there is nothing SQL Server needs set on a
// fresh command — the member exists for Oracle's <c>BindByName</c> (see
// <see cref="ISqlDialect.ConfigureCommand"/>).
// </summary>
// <param name="command">The command to configure; untouched here.</param>
/// <inheritdoc />
public void ConfigureCommand(DbCommand command)
{
// Intentionally empty: see the summary.
}
/// <summary>
/// 2098 — SQL Server's hard cap is <b>2100 parameters per statement</b>, and
/// <c>Microsoft.Data.SqlClient</c> spends two of them itself: a parameterized command is executed
/// through <c>sp_executesql</c>, whose first two arguments are the statement text and the parameter
/// declaration list. A caller filling 2100 would therefore be rejected with
/// <c>"The incoming request has too many parameters"</c> for a limit it appeared to respect.
/// </summary>
// <summary>
// 2098 — SQL Server's hard cap is <b>2100 parameters per statement</b>, and
// <c>Microsoft.Data.SqlClient</c> spends two of them itself: a parameterized command is executed
// through <c>sp_executesql</c>, whose first two arguments are the statement text and the parameter
// declaration list. A caller filling 2100 would therefore be rejected with
// <c>"The incoming request has too many parameters"</c> for a limit it appeared to respect.
// </summary>
/// <inheritdoc />
public int MaxBindParameters => 2098;
/// <inheritdoc/>
public string LivenessSql => "SELECT 1";
/// <summary>
/// T-SQL limits after the <c>SELECT</c> keyword, so the whole limit lives in the prefix —
/// <c>"TOP 1 "</c>, trailing space included so <c>SELECT TOP 1 [col]</c> composes with no extra
/// separator at the call site.
/// </summary>
// <summary>
// T-SQL limits after the <c>SELECT</c> keyword, so the whole limit lives in the prefix —
// <c>"TOP 1 "</c>, trailing space included so <c>SELECT TOP 1 [col]</c> composes with no extra
// separator at the call site.
// </summary>
/// <inheritdoc />
public string SingleRowLimitPrefix => "TOP 1 ";
/// <summary>Empty — T-SQL has no trailing row-limit clause (<c>OFFSET/FETCH</c> is a paging construct, not this).</summary>
// <summary>Empty — T-SQL has no trailing row-limit clause (<c>OFFSET/FETCH</c> is a paging construct, not this).</summary>
/// <inheritdoc />
public string SingleRowLimitSuffix => string.Empty;
/// <inheritdoc/>
public string ListSchemasSql =>
"SELECT DISTINCT TABLE_SCHEMA FROM INFORMATION_SCHEMA.TABLES ORDER BY TABLE_SCHEMA";
/// <summary>
/// <c>SCHEMA_NAME()</c> with no argument returns the calling principal's default schema — the one an
/// unqualified object name resolves in, which is precisely the question the catalog gate asks.
/// </summary>
// <summary>
// <c>SCHEMA_NAME()</c> with no argument returns the calling principal's default schema — the one an
// unqualified object name resolves in, which is precisely the question the catalog gate asks.
// </summary>
/// <inheritdoc />
public string DefaultSchemaSql => "SELECT SCHEMA_NAME()";
/// <inheritdoc/>
@@ -101,31 +108,32 @@ public sealed class SqlServerDialect : ISqlDialect
"SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE FROM INFORMATION_SCHEMA.COLUMNS " +
"WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = @table ORDER BY ORDINAL_POSITION";
/// <summary>
/// Brackets one identifier part, doubling any embedded <c>]</c> — the T-SQL escape rule, and the only
/// metacharacter that could terminate a bracketed identifier early. <c>[</c>, quotes, semicolons and
/// comment markers are inert inside brackets and are therefore passed through unchanged.
/// </summary>
/// <remarks>
/// <para><b>Rejects</b> (all as <see cref="ArgumentException"/>): null / empty / all-whitespace; longer
/// than <see cref="MaxIdentifierLength"/>; any control character (which covers embedded NUL, and the
/// C0/C1 ranges that can truncate or corrupt a logged/audited statement); and any Unicode
/// <see cref="System.Globalization.UnicodeCategory.Format"/> character — bidi overrides, zero-width
/// spaces, soft hyphen, BOM. Those last cannot escape the brackets, but they spoof the <em>rendered</em>
/// text of a log line or an AdminUI label while comparing byte-different from the real catalog name
/// (the Trojan-Source class, CVE-2021-42574) — the same log/audit-integrity concern that motivates the
/// control-character rule.</para>
/// <para>The rejection messages deliberately do <b>not</b> echo the offending value — it is untrusted
/// input and this exception's text reaches the driver log.</para>
/// <para><b>This is a backstop, not the only defence.</b> Design §8.1's catalog gate
/// (<c>SqlCatalogGate</c>) resolves an authored table/column against the live catalog at
/// Initialize and substitutes the catalog's own spelling, so on the poll path the value arriving here
/// is a string read back out of the catalog. The rules below still run — the gate uses them as its own
/// charset filter, and they must hold for any future caller that has no catalog to check against.</para>
/// </remarks>
/// <param name="ident">The bare, unquoted identifier part.</param>
/// <returns>The bracket-quoted identifier.</returns>
/// <exception cref="ArgumentException">The value cannot be a valid SQL Server identifier.</exception>
// <summary>
// Brackets one identifier part, doubling any embedded <c>]</c> — the T-SQL escape rule, and the only
// metacharacter that could terminate a bracketed identifier early. <c>[</c>, quotes, semicolons and
// comment markers are inert inside brackets and are therefore passed through unchanged.
// </summary>
// <remarks>
// <para><b>Rejects</b> (all as <see cref="ArgumentException"/>): null / empty / all-whitespace; longer
// than <see cref="MaxIdentifierLength"/>; any control character (which covers embedded NUL, and the
// C0/C1 ranges that can truncate or corrupt a logged/audited statement); and any Unicode
// <see cref="System.Globalization.UnicodeCategory.Format"/> character — bidi overrides, zero-width
// spaces, soft hyphen, BOM. Those last cannot escape the brackets, but they spoof the <em>rendered</em>
// text of a log line or an AdminUI label while comparing byte-different from the real catalog name
// (the Trojan-Source class, CVE-2021-42574) — the same log/audit-integrity concern that motivates the
// control-character rule.</para>
// <para>The rejection messages deliberately do <b>not</b> echo the offending value — it is untrusted
// input and this exception's text reaches the driver log.</para>
// <para><b>This is a backstop, not the only defence.</b> Design §8.1's catalog gate
// (<c>SqlCatalogGate</c>) resolves an authored table/column against the live catalog at
// Initialize and substitutes the catalog's own spelling, so on the poll path the value arriving here
// is a string read back out of the catalog. The rules below still run — the gate uses them as its own
// charset filter, and they must hold for any future caller that has no catalog to check against.</para>
// </remarks>
// <param name="ident">The bare, unquoted identifier part.</param>
// <returns>The bracket-quoted identifier.</returns>
// <exception cref="ArgumentException">The value cannot be a valid SQL Server identifier.</exception>
/// <inheritdoc />
public string QuoteIdentifier(string ident)
{
if (string.IsNullOrWhiteSpace(ident))
@@ -154,29 +162,30 @@ public sealed class SqlServerDialect : ISqlDialect
return string.Concat("[", ident.Replace("]", "]]", StringComparison.Ordinal), "]");
}
/// <summary>
/// Folds an <c>INFORMATION_SCHEMA.COLUMNS.DATA_TYPE</c> family name onto a
/// <see cref="DriverDataType"/> per design §3.7.
/// </summary>
/// <remarks>
/// <para><b>Precision caveat:</b> <c>decimal</c> / <c>numeric</c> / <c>money</c> / <c>smallmoney</c>
/// collapse to <see cref="DriverDataType.Float64"/> in v1. A .NET <c>decimal</c> carries more
/// significant digits than a <c>double</c>, so a high-precision column (e.g. <c>decimal(38,10)</c>)
/// loses low-order digits. Authoring an explicit <c>"type": "String"</c> on the tag preserves the exact
/// textual value when that matters.</para>
/// <para><b>Fallback:</b> an unrecognised family maps to <see cref="DriverDataType.String"/> and never
/// throws — a schema browse must render a table containing an exotic column (<c>xml</c>,
/// <c>geography</c>, <c>hierarchyid</c>, <c>sql_variant</c>, a CLR UDT, <c>varbinary</c>) rather than
/// crash on it. Null/blank input takes the same fallback.</para>
/// <para><b>Deliberate non-mappings:</b> SQL Server's <c>timestamp</c>/<c>rowversion</c> is an opaque
/// 8-byte row version, <em>not</em> a date — it falls back to <see cref="DriverDataType.String"/>
/// rather than being mistaken for a <see cref="DriverDataType.DateTime"/>. <c>time</c> is a
/// time-of-day span, likewise not a point in time, and takes the same fallback.</para>
/// <para><c>tinyint</c> widens to <see cref="DriverDataType.Int16"/> (it is unsigned 0–255 in T-SQL, so
/// a signed 8-bit type would not hold it, and the driver type set has no <c>Byte</c>).</para>
/// </remarks>
/// <param name="sqlDataType">The bare SQL type family name; matched case-insensitively.</param>
/// <returns>The mapped driver data type, or <see cref="DriverDataType.String"/> when unrecognised.</returns>
// <summary>
// Folds an <c>INFORMATION_SCHEMA.COLUMNS.DATA_TYPE</c> family name onto a
// <see cref="DriverDataType"/> per design §3.7.
// </summary>
// <remarks>
// <para><b>Precision caveat:</b> <c>decimal</c> / <c>numeric</c> / <c>money</c> / <c>smallmoney</c>
// collapse to <see cref="DriverDataType.Float64"/> in v1. A .NET <c>decimal</c> carries more
// significant digits than a <c>double</c>, so a high-precision column (e.g. <c>decimal(38,10)</c>)
// loses low-order digits. Authoring an explicit <c>"type": "String"</c> on the tag preserves the exact
// textual value when that matters.</para>
// <para><b>Fallback:</b> an unrecognised family maps to <see cref="DriverDataType.String"/> and never
// throws — a schema browse must render a table containing an exotic column (<c>xml</c>,
// <c>geography</c>, <c>hierarchyid</c>, <c>sql_variant</c>, a CLR UDT, <c>varbinary</c>) rather than
// crash on it. Null/blank input takes the same fallback.</para>
// <para><b>Deliberate non-mappings:</b> SQL Server's <c>timestamp</c>/<c>rowversion</c> is an opaque
// 8-byte row version, <em>not</em> a date — it falls back to <see cref="DriverDataType.String"/>
// rather than being mistaken for a <see cref="DriverDataType.DateTime"/>. <c>time</c> is a
// time-of-day span, likewise not a point in time, and takes the same fallback.</para>
// <para><c>tinyint</c> widens to <see cref="DriverDataType.Int16"/> (it is unsigned 0–255 in T-SQL, so
// a signed 8-bit type would not hold it, and the driver type set has no <c>Byte</c>).</para>
// </remarks>
// <param name="sqlDataType">The bare SQL type family name; matched case-insensitively.</param>
// <returns>The mapped driver data type, or <see cref="DriverDataType.String"/> when unrecognised.</returns>
/// <inheritdoc />
public DriverDataType MapColumnType(string sqlDataType)
{
if (string.IsNullOrWhiteSpace(sqlDataType)) return DriverDataType.String;