chore: refactor for sonarqube issues
SonarQube Analysis / sonarqube (pull_request) Successful in 6m3s

This commit is contained in:
Thom Lamb
2026-05-22 17:13:31 -05:00
parent 063d5a7ba0
commit 012e693fe1
22 changed files with 522 additions and 461 deletions
@@ -689,44 +689,74 @@ public class StatementParser
// Only process keywords at top level (outside parentheses)
if (parenthesisDepth == 0 && type == TokenType.String)
{
// Check for multi-word keywords (GROUP BY, ORDER BY)
if (string.Equals(value, "GROUP", StringComparison.OrdinalIgnoreCase) &&
tokenIndex + 1 < tokens.Count &&
tokens[tokenIndex + 1].type == TokenType.String &&
string.Equals(tokens[tokenIndex + 1].value, "BY", StringComparison.OrdinalIgnoreCase))
{
if (!clausePositions.ContainsKey(KeywordGroupBy))
{
clausePositions[KeywordGroupBy] = position;
}
skipNextToken = true; // Skip BY in next iteration
}
else if (string.Equals(value, "ORDER", StringComparison.OrdinalIgnoreCase) &&
tokenIndex + 1 < tokens.Count &&
tokens[tokenIndex + 1].type == TokenType.String &&
string.Equals(tokens[tokenIndex + 1].value, "BY", StringComparison.OrdinalIgnoreCase))
{
if (!clausePositions.ContainsKey(KeywordOrderBy))
{
clausePositions[KeywordOrderBy] = position;
}
skipNextToken = true; // Skip BY in next iteration
}
else if (keywordSet.Contains(value))
{
var matchedKeyword = keywords.FirstOrDefault(k =>
string.Equals(k, value, StringComparison.OrdinalIgnoreCase));
if (matchedKeyword != null && !clausePositions.ContainsKey(matchedKeyword))
{
clausePositions[matchedKeyword] = position;
}
}
skipNextToken = TryRecordKeywordAtToken(tokens, tokenIndex, value, position, keywords, keywordSet, clausePositions);
}
}
}
/// <summary>
/// Records the keyword at the given token (single-word or multi-word) into <paramref name="clausePositions"/>.
/// </summary>
/// <returns>True if a multi-word keyword (GROUP BY / ORDER BY) was matched and the following token should be skipped.</returns>
private static bool TryRecordKeywordAtToken(
List<(TokenType type, string value, int position)> tokens,
int tokenIndex,
string value,
int position,
string[] keywords,
HashSet<string> keywordSet,
Dictionary<string, int> clausePositions)
{
// Check for multi-word keywords (GROUP BY, ORDER BY); they consume the following BY token.
if (TryRecordMultiWordKeyword(tokens, tokenIndex, "GROUP", KeywordGroupBy, clausePositions) ||
TryRecordMultiWordKeyword(tokens, tokenIndex, "ORDER", KeywordOrderBy, clausePositions))
{
return true;
}
if (keywordSet.Contains(value))
{
var matchedKeyword = keywords.FirstOrDefault(k =>
string.Equals(k, value, StringComparison.OrdinalIgnoreCase));
if (matchedKeyword != null && !clausePositions.ContainsKey(matchedKeyword))
{
clausePositions[matchedKeyword] = position;
}
}
return false;
}
/// <summary>
/// Records a two-word keyword (e.g., "GROUP BY") when the token at <paramref name="tokenIndex"/> matches
/// <paramref name="firstWord"/> and is immediately followed by "BY".
/// </summary>
/// <returns>True if the multi-word keyword pattern matched.</returns>
private static bool TryRecordMultiWordKeyword(
List<(TokenType type, string value, int position)> tokens,
int tokenIndex,
string firstWord,
string canonicalKeyword,
Dictionary<string, int> clausePositions)
{
var (_, value, position) = tokens[tokenIndex];
if (!string.Equals(value, firstWord, StringComparison.OrdinalIgnoreCase) ||
tokenIndex + 1 >= tokens.Count ||
tokens[tokenIndex + 1].type != TokenType.String ||
!string.Equals(tokens[tokenIndex + 1].value, "BY", StringComparison.OrdinalIgnoreCase))
{
return false;
}
if (!clausePositions.ContainsKey(canonicalKeyword))
{
clausePositions[canonicalKeyword] = position;
}
return true;
}
public virtual SqlClauses ExtractAllClauses(string sql, Dictionary<string, int> clausePositions)
{
var clauses = new SqlClauses