Skip to content

Commit 25e0b0b

Browse files
committed
Added XML documentation to some internals to help with maintainability.
1 parent 2d787b7 commit 25e0b0b

7 files changed

Lines changed: 96 additions & 11 deletions

File tree

SqlServerSimulator/Collation.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
namespace SqlServerSimulator;
22

3+
/// <summary>
4+
/// The SQL Server equivalent to .NET's <see cref="IComparer{T}"/> for strings.
5+
/// </summary>
36
internal abstract class Collation : IComparer<string>, IEqualityComparer<string>
47
{
58
private protected Collation()

SqlServerSimulator/DataType.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
namespace SqlServerSimulator;
66

7+
/// <summary>
8+
/// Bridges .NET's native types, the various <see cref="DbType"/>s, and SQL Server's actual behavior.
9+
/// </summary>
710
internal abstract class DataType
811
{
912
private protected DataType()

SqlServerSimulator/Extensions.cs

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,44 @@ namespace SqlServerSimulator;
55

66
static class Extensions
77
{
8+
/// <summary>
9+
/// Moves to the next item in an enumeration (if possible) and transfers <see cref="IEnumerator{T}.Current"/> to <paramref name="current"/>.
10+
/// </summary>
11+
/// <typeparam name="T">The type of enumeration.</typeparam>
12+
/// <param name="enumerator">The enumerator to advance.</param>
13+
/// <param name="current">Receives the <see cref="IEnumerator{T}.Current"/> value, or the types default if advancement isn't possible.</param>
14+
/// <returns>True if the enumerator was advanced, otherwise false.</returns>
815
public static bool TryMoveNext<T>(this IEnumerator<T> enumerator, [NotNullWhen(true)] out T? current)
916
{
1017
bool moved;
1118
current = (moved = enumerator.MoveNext()) ? enumerator.Current : default;
1219
return moved;
1320
}
1421

22+
/// <summary>
23+
/// Returns the next token in the enumeration, throwing an exception if the end was reached instead.
24+
/// </summary>
25+
/// <param name="enumerator">The enumerator to advance.</param>
26+
/// <returns>The next token.</returns>
27+
/// <exception cref="SimulatedSqlException">Incorrect syntax near '{token}'.</exception>
1528
public static Parser.Token RequireNext(this IEnumerator<Parser.Token> enumerator)
1629
{
1730
Debug.Assert(enumerator.Current is not null);
1831
var previous = enumerator.Current;
1932
return enumerator.MoveNext() ? enumerator.Current : throw SimulatedSqlException.SyntaxErrorNear(previous);
2033
}
2134

35+
/// <summary>
36+
/// Returns the next token in the enumeration, throwing an exception if the end was reached instead or the token is the wrong type.
37+
/// </summary>
38+
/// <param name="enumerator">The enumerator to advance.</param>
39+
/// <returns>The next token.</returns>
40+
/// <exception cref="SimulatedSqlException">Incorrect syntax near '{token}'.</exception>
2241
public static T RequireNext<T>(this IEnumerator<Parser.Token> enumerator)
2342
where T : Parser.Token
2443
{
2544
Debug.Assert(enumerator.Current is not null);
2645
var previous = enumerator.Current;
27-
28-
if (enumerator.MoveNext())
29-
{
30-
var current = enumerator.Current as T;
31-
if (current is not null)
32-
return current;
33-
}
34-
35-
throw SimulatedSqlException.SyntaxErrorNear(previous);
46+
return enumerator.MoveNext() && enumerator.Current is T current ? current : throw SimulatedSqlException.SyntaxErrorNear(previous);
3647
}
3748
}

SqlServerSimulator/Parser/Expression.cs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,31 @@
33

44
namespace SqlServerSimulator.Parser;
55

6+
/// <summary>
7+
/// Contains the logic described by a SQL command and computes its results.
8+
/// </summary>
69
internal abstract class Expression
710
{
811
private protected Expression()
912
{
1013
}
1114

15+
/// <summary>
16+
/// A name or alias associated with an expression.
17+
/// Anonymous expressions return <see cref="string.Empty"/>.
18+
/// </summary>
1219
public virtual string Name => string.Empty;
1320

21+
/// <summary>
22+
/// Converts the tokens from a command into a single expression.
23+
/// </summary>
24+
/// <param name="simulation">Simulation shared context.</param>
25+
/// <param name="tokens">The sequence of command tokens. This will be advanced to the end of the expression.</param>
26+
/// <param name="token">Retains the most recently provided token from <paramref name="tokens"/>.</param>
27+
/// <param name="getVariableValue">Provides the value to any variable included alongside the command.</param>
28+
/// <returns>The parsed expression.</returns>
29+
/// <exception cref="SimulatedSqlException">A variety of messages are possible for various problems with the command.</exception>
30+
/// <exception cref="NotSupportedException">A condition was encountered that may be valid but can't currently be parsed.</exception>
1431
public static Expression Parse(Simulation simulation, IEnumerator<Token> tokens, ref Token? token, Func<string, object?> getVariableValue)
1532
{
1633
Expression? expression = null;
@@ -131,6 +148,11 @@ public static Expression Parse(Simulation simulation, IEnumerator<Token> tokens,
131148
return expression;
132149
}
133150

151+
/// <summary>
152+
/// Runs the expression, returning its result.
153+
/// </summary>
154+
/// <param name="getColumnValue">Provides the value for a column.</param>
155+
/// <returns>The result of the expression.</returns>
134156
public abstract object? Run(Func<List<string>, object?> getColumnValue);
135157

136158
#if DEBUG
@@ -144,6 +166,11 @@ public static Expression Parse(Simulation simulation, IEnumerator<Token> tokens,
144166
new("abs", (simulation, tokens, ref token, getVariableValue) => new AbsoluteValue(Expression.Parse(simulation, tokens, ref token, getVariableValue))),
145167
]);
146168

169+
/// <summary>
170+
/// An expression that has been given a name, such as with `as`.
171+
/// </summary>
172+
/// <param name="expression">The expression to be named.</param>
173+
/// <param name="name">The name of the expression, exposed via the <see cref="Name"/> property.</param>
147174
private sealed class NamedExpression(Expression expression, string name) : Expression
148175
{
149176
private readonly Expression expression = expression;
@@ -156,13 +183,11 @@ private sealed class NamedExpression(Expression expression, string name) : Expre
156183

157184
public override object? Run(Func<List<string>, object?> getColumnValue) => this.expression.Run(getColumnValue);
158185

159-
#if DEBUG
160186
/// <summary>
161187
/// Transfers the name to an outer expression.
162188
/// </summary>
163189
/// <param name="destination">The expression wrapping this<see cref="NamedExpression"/>.</param>
164190
/// <returns>A new <see cref="NamedExpression"/> wrapping <paramref name="destination"/> using <see cref="Name"/>.</returns>
165-
#endif
166191
public NamedExpression TransferName(Expression destination)
167192
{
168193
#if DEBUG
@@ -268,6 +293,10 @@ public sealed class Reference(Name name) : Expression
268293
#endif
269294
}
270295

296+
/// <summary>
297+
/// Encapsulates the SQL DATALENGTH command: https://learn.microsoft.com/en-us/sql/t-sql/functions/datalength-transact-sql
298+
/// </summary>
299+
/// <param name="source">Provides the value to be processed.</param>
271300
public sealed class DataLength(Expression source) : Expression
272301
{
273302
private readonly Expression source = source;
@@ -284,6 +313,10 @@ public sealed class DataLength(Expression source) : Expression
284313
#endif
285314
}
286315

316+
/// <summary>
317+
/// Encapsulates the SQL ABS command: https://learn.microsoft.com/en-us/sql/t-sql/functions/abs-transact-sql
318+
/// </summary>
319+
/// <param name="source">Provides the value to be processed.</param>
287320
public sealed class AbsoluteValue(Expression source) : Expression
288321
{
289322
private readonly Expression source = source;

SqlServerSimulator/Parser/Selection.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,26 @@
22

33
namespace SqlServerSimulator.Parser;
44

5+
/// <summary>
6+
/// Manages the higher-level logic to convert a sequence of command tokens into tabular results.
7+
/// </summary>
58
internal sealed class Selection
69
{
710
internal readonly SimulatedResultSet Results;
811

912
private Selection(SimulatedResultSet results) => this.Results = results;
1013

14+
/// <summary>
15+
/// Creates a <see cref="Selection"/> from a series of tokens.
16+
/// </summary>
17+
/// <param name="simulation">Simulation shared context.</param>
18+
/// <param name="tokens">The sequence of command tokens. This will be advanced to the end of the expression.</param>
19+
/// <param name="token">Retains the most recently provided token from <paramref name="tokens"/>.</param>
20+
/// <param name="getVariableValue">Provides the value to any variable included alongside the command.</param>
21+
/// <param name="depth">The current depth of recursed selection, such as with derived tables. 0 for the top-level SELECT.</param>
22+
/// <returns>The prepared command.</returns>
23+
/// <exception cref="SimulatedSqlException">A variety of messages are possible for various problems with the command.</exception>
24+
/// <exception cref="NotSupportedException">A condition was encountered that may be valid but can't currently be parsed.</exception>
1125
public static Selection Parse(Simulation simulation, IEnumerator<Token> tokens, ref Token? token, Func<string, object?> getVariableValue, uint depth)
1226
{
1327
token = tokens.RequireNext();

SqlServerSimulator/Parser/Token.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
namespace SqlServerSimulator.Parser;
22

3+
/// <summary>
4+
/// Describes a single token in a SQL command.
5+
/// </summary>
36
abstract class Token
47
{
58
private protected Token()

SqlServerSimulator/Parser/Tokenizer.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,14 @@
33

44
namespace SqlServerSimulator.Parser;
55

6+
/// <summary>
7+
/// Specializes in refining a SQL command string into sequence of <see cref="Token"/> instances.
8+
/// </summary>
69
static class Tokenizer
710
{
11+
/// <summary>
12+
/// Helps the tokenizer keep track of what it's doing.
13+
/// </summary>
814
enum State
915
{
1016
None,
@@ -17,6 +23,13 @@ enum State
1723
Numeric
1824
}
1925

26+
/// <summary>
27+
/// Refines a SQL command string into sequence of <see cref="Token"/> instances.
28+
/// </summary>
29+
/// <param name="command">The command to tokenize.</param>
30+
/// <returns>An enumeration of <paramref name="command"/>'s tokens.</returns>
31+
/// <exception cref="InvalidOperationException">ExecuteReader: CommandText property has not been initialized.</exception>
32+
/// <exception cref="NotSupportedException">An unsupported pattern was found in the command.</exception>
2033
public static IEnumerable<Token> Tokenize(string? command)
2134
{
2235
if (string.IsNullOrEmpty(command))
@@ -272,6 +285,11 @@ static bool TryGetNext(this CharEnumerator enumerator, out char c, ref int index
272285
return false;
273286
}
274287

288+
/// <summary>
289+
/// When true, the state is some variant of a quoted or delimited string.
290+
/// </summary>
291+
/// <param name="state">The state to check.</param>
292+
/// <returns>True if the string is delimited, otherwise false.</returns>
275293
static bool IsQuotedString(this State state) => state switch
276294
{
277295
State.BracketDelimitedString or State.SingleQuotedString or State.DoubleQuotedString => true,

0 commit comments

Comments
 (0)