-
Notifications
You must be signed in to change notification settings - Fork 0
Fix CodeQL alerts: Add missing XML documentation summaries #18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Addresses 8 CodeQL alerts for missing documentation summaries by adding <summary> tags to methods that were using only <include> tags. CodeQL requires explicit <summary> tags and doesn't recognize <include> tags as documentation. This change adds brief summaries while preserving the existing <include> tags for detailed documentation. Files modified: - FAnsi.Core/Discovery/IDiscoveredServerHelper.cs - FAnsi.Core/Discovery/DiscoveredServerHelper.cs - FAnsi.Core/Discovery/DiscoveredServer.cs - FAnsi.Core/Discovery/DiscoveredTable.cs - FAnsi.Core/Discovery/IDiscoveredTableHelper.cs Resolves CodeQL alerts: HicServices#33-40 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
catch (Exception ex) | ||
{ | ||
throw new InvalidOperationException( | ||
$"Failed to convert column '{columnName}' value '{value}' to type '{property.PropertyType.Name}'.", | ||
ex); | ||
} |
Check notice
Code scanning / CodeQL
Generic catch clause Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 days ago
To fix this genuine issue, replace the broad catch (Exception ex)
clause with more specific catch clauses for exception types that are reasonably expected during value conversion and property setting. In this context, failures are likely due to type mismatches, format errors, or property issues. Specifically, replace the catch block with multiple catch blocks:
- Catch
InvalidCastException
,FormatException
, andArgumentException
for conversion errors. - Catch
TargetException
andTargetInvocationException
for possible reflection/property setting issues.
Each should rethrow as anInvalidOperationException
with proper context.
Changes are required to only the block inside the method shown, i.e., lines 229-234 inFAnsi.Core/Discovery/Queryable/FAnsiQueryProvider.cs
.
No new imports are needed, since all exception types are part of the base class library.
-
Copy modified line R229 -
Copy modified lines R235-R258
@@ -226,12 +226,36 @@ | ||
var convertedValue = Convert.ChangeType(value, targetType); | ||
property.SetValue(instance, convertedValue); | ||
} | ||
catch (Exception ex) | ||
catch (InvalidCastException ex) | ||
{ | ||
throw new InvalidOperationException( | ||
$"Failed to convert column '{columnName}' value '{value}' to type '{property.PropertyType.Name}'.", | ||
ex); | ||
} | ||
catch (FormatException ex) | ||
{ | ||
throw new InvalidOperationException( | ||
$"Failed to convert column '{columnName}' value '{value}' to type '{property.PropertyType.Name}'.", | ||
ex); | ||
} | ||
catch (ArgumentException ex) | ||
{ | ||
throw new InvalidOperationException( | ||
$"Failed to convert column '{columnName}' value '{value}' to type '{property.PropertyType.Name}'.", | ||
ex); | ||
} | ||
catch (System.Reflection.TargetException ex) | ||
{ | ||
throw new InvalidOperationException( | ||
$"Failed to set property '{property.Name}' on type '{elementType.Name}'.", | ||
ex); | ||
} | ||
catch (System.Reflection.TargetInvocationException ex) | ||
{ | ||
throw new InvalidOperationException( | ||
$"Failed to set property '{property.Name}' on type '{elementType.Name}'.", | ||
ex); | ||
} | ||
} | ||
} | ||
} |
foreach (var clause in components.WhereClauses) | ||
{ | ||
string condition = clause.Operator switch | ||
{ | ||
WhereOperator.Equal => BuildComparison(clause.PropertyName, "=", clause.Value, ref paramIndex, parameters), | ||
WhereOperator.NotEqual => BuildComparison(clause.PropertyName, "!=", clause.Value, ref paramIndex, parameters), | ||
WhereOperator.GreaterThan => BuildComparison(clause.PropertyName, ">", clause.Value, ref paramIndex, parameters), | ||
WhereOperator.GreaterThanOrEqual => BuildComparison(clause.PropertyName, ">=", clause.Value, ref paramIndex, parameters), | ||
WhereOperator.LessThan => BuildComparison(clause.PropertyName, "<", clause.Value, ref paramIndex, parameters), | ||
WhereOperator.LessThanOrEqual => BuildComparison(clause.PropertyName, "<=", clause.Value, ref paramIndex, parameters), | ||
WhereOperator.Like => BuildComparison(clause.PropertyName, "LIKE", clause.Value, ref paramIndex, parameters), | ||
WhereOperator.IsNull => $"{WrapIdentifier(clause.PropertyName)} IS NULL", | ||
WhereOperator.IsNotNull => $"{WrapIdentifier(clause.PropertyName)} IS NOT NULL", | ||
_ => throw new NotSupportedException($"Operator {clause.Operator} is not supported") | ||
}; | ||
|
||
conditions.Add(condition); | ||
} |
Check notice
Code scanning / CodeQL
Missed opportunity to use Select Note
maps its iteration variable to another variable
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 days ago
To fix the issue, refactor the foreach
loop in the BuildWhereClause
method to use LINQ's Select
for mapping clause
to condition
. The resulting sequence of condition
s can be collected into a list or used directly in the subsequent code. Specifically, replace:
foreach (var clause in components.WhereClauses)
{
string condition = clause.Operator switch
{
// ...
};
conditions.Add(condition);
}
with:
var conditions = components.WhereClauses.Select(clause => /* mapping logic */).ToList();
The mapping logic involves the switch statement used to compute condition
, passing paramIndex
and parameters
as before. Since the side effects (mutating paramIndex
and adding to parameters
) are still essential, they can be safely included within the lambda function in Select
. No additional imports are required since System.Linq
is already present.
Only the lines for the loop and the collection of conditions
need adjustment, i.e., lines 123–143. Nothing else in the file requires changes.
-
Copy modified lines R125-R126 -
Copy modified lines R136-R137
@@ -120,12 +120,10 @@ | ||
if (!components.WhereClauses.Any()) | ||
return string.Empty; | ||
|
||
var conditions = new System.Collections.Generic.List<string>(); | ||
int paramIndex = 0; | ||
|
||
foreach (var clause in components.WhereClauses) | ||
{ | ||
string condition = clause.Operator switch | ||
var conditions = components.WhereClauses.Select(clause => | ||
clause.Operator switch | ||
{ | ||
WhereOperator.Equal => BuildComparison(clause.PropertyName, "=", clause.Value, ref paramIndex, parameters), | ||
WhereOperator.NotEqual => BuildComparison(clause.PropertyName, "!=", clause.Value, ref paramIndex, parameters), | ||
@@ -137,11 +133,9 @@ | ||
WhereOperator.IsNull => $"{WrapIdentifier(clause.PropertyName)} IS NULL", | ||
WhereOperator.IsNotNull => $"{WrapIdentifier(clause.PropertyName)} IS NOT NULL", | ||
_ => throw new NotSupportedException($"Operator {clause.Operator} is not supported") | ||
}; | ||
} | ||
).ToList(); | ||
|
||
conditions.Add(condition); | ||
} | ||
|
||
return " WHERE " + string.Join(" AND ", conditions); | ||
} | ||
|
foreach (var clause in components.WhereClauses) | ||
{ | ||
string condition = clause.Operator switch | ||
{ | ||
WhereOperator.Equal => BuildEqualityCondition(clause.PropertyName, clause.Value, ref paramIndex, paramList), | ||
WhereOperator.NotEqual => BuildInequalityCondition(clause.PropertyName, clause.Value, ref paramIndex, paramList), | ||
WhereOperator.GreaterThan => BuildComparisonCondition(clause.PropertyName, ">", clause.Value, ref paramIndex, paramList), | ||
WhereOperator.GreaterThanOrEqual => BuildComparisonCondition(clause.PropertyName, ">=", clause.Value, ref paramIndex, paramList), | ||
WhereOperator.LessThan => BuildComparisonCondition(clause.PropertyName, "<", clause.Value, ref paramIndex, paramList), | ||
WhereOperator.LessThanOrEqual => BuildComparisonCondition(clause.PropertyName, "<=", clause.Value, ref paramIndex, paramList), | ||
WhereOperator.Like => BuildLikeCondition(clause.PropertyName, clause.Value, ref paramIndex, paramList), | ||
WhereOperator.IsNull => $"{WrapIdentifier(clause.PropertyName)} IS NULL", | ||
WhereOperator.IsNotNull => $"{WrapIdentifier(clause.PropertyName)} IS NOT NULL", | ||
_ => throw new NotSupportedException($"Operator '{clause.Operator}' is not supported") | ||
}; | ||
|
||
conditions.Add(condition); | ||
} |
Check notice
Code scanning / CodeQL
Missed opportunity to use Select Note
maps its iteration variable to another variable
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 days ago
To fix this problem, we should replace the foreach
loop on lines 102–119 that builds the conditions
list by explicitly mapping each clause
to its corresponding condition
and adding it to conditions
. The idiomatic LINQ fix is to use .Select(...)
to project each clause
into its corresponding condition
, then use .ToList()
to construct the resulting list. All the logic inside the loop (the switch/call to condition-building methods, incrementing the paramIndex
as necessary, and adding to paramList
) remains in the lambda passed to Select
. This results in construction of the mapped conditions
list without a manual loop, making the transformation explicit and more readable.
What needs to change:
- Lines 99–119:
- Remove the manual creation of an empty
conditions
list and theforeach
loop. - Replace with initialization of
conditions
using LINQ's.Select(...)
and.ToList()
.
- Remove the manual creation of an empty
- Use a lambda that matches the loop logic for mapping each
clause
. - Ensure the scope of
paramIndex
andparamList
remains correct and mutations are preserved.
No additional methods or imports are needed, because System.Linq
is already imported.
-
Copy modified lines R100-R115
@@ -96,28 +96,24 @@ | ||
if (!components.WhereClauses.Any()) | ||
return string.Empty; | ||
|
||
var conditions = new System.Collections.Generic.List<string>(); | ||
int paramIndex = 0; | ||
var conditions = components.WhereClauses | ||
.Select(clause => | ||
clause.Operator switch | ||
{ | ||
WhereOperator.Equal => BuildEqualityCondition(clause.PropertyName, clause.Value, ref paramIndex, paramList), | ||
WhereOperator.NotEqual => BuildInequalityCondition(clause.PropertyName, clause.Value, ref paramIndex, paramList), | ||
WhereOperator.GreaterThan => BuildComparisonCondition(clause.PropertyName, ">", clause.Value, ref paramIndex, paramList), | ||
WhereOperator.GreaterThanOrEqual => BuildComparisonCondition(clause.PropertyName, ">=", clause.Value, ref paramIndex, paramList), | ||
WhereOperator.LessThan => BuildComparisonCondition(clause.PropertyName, "<", clause.Value, ref paramIndex, paramList), | ||
WhereOperator.LessThanOrEqual => BuildComparisonCondition(clause.PropertyName, "<=", clause.Value, ref paramIndex, paramList), | ||
WhereOperator.Like => BuildLikeCondition(clause.PropertyName, clause.Value, ref paramIndex, paramList), | ||
WhereOperator.IsNull => $"{WrapIdentifier(clause.PropertyName)} IS NULL", | ||
WhereOperator.IsNotNull => $"{WrapIdentifier(clause.PropertyName)} IS NOT NULL", | ||
_ => throw new NotSupportedException($"Operator '{clause.Operator}' is not supported") | ||
} | ||
).ToList(); | ||
|
||
foreach (var clause in components.WhereClauses) | ||
{ | ||
string condition = clause.Operator switch | ||
{ | ||
WhereOperator.Equal => BuildEqualityCondition(clause.PropertyName, clause.Value, ref paramIndex, paramList), | ||
WhereOperator.NotEqual => BuildInequalityCondition(clause.PropertyName, clause.Value, ref paramIndex, paramList), | ||
WhereOperator.GreaterThan => BuildComparisonCondition(clause.PropertyName, ">", clause.Value, ref paramIndex, paramList), | ||
WhereOperator.GreaterThanOrEqual => BuildComparisonCondition(clause.PropertyName, ">=", clause.Value, ref paramIndex, paramList), | ||
WhereOperator.LessThan => BuildComparisonCondition(clause.PropertyName, "<", clause.Value, ref paramIndex, paramList), | ||
WhereOperator.LessThanOrEqual => BuildComparisonCondition(clause.PropertyName, "<=", clause.Value, ref paramIndex, paramList), | ||
WhereOperator.Like => BuildLikeCondition(clause.PropertyName, clause.Value, ref paramIndex, paramList), | ||
WhereOperator.IsNull => $"{WrapIdentifier(clause.PropertyName)} IS NULL", | ||
WhereOperator.IsNotNull => $"{WrapIdentifier(clause.PropertyName)} IS NOT NULL", | ||
_ => throw new NotSupportedException($"Operator '{clause.Operator}' is not supported") | ||
}; | ||
|
||
conditions.Add(condition); | ||
} | ||
|
||
return " WHERE " + string.Join(" AND ", conditions); | ||
} | ||
|
foreach (var whereClause in components.WhereClauses) | ||
{ | ||
var condition = TranslateWhereClause(whereClause, paramList); | ||
sql.AppendLine($" AND {condition}"); | ||
} |
Check notice
Code scanning / CodeQL
Missed opportunity to use Select Note
maps its iteration variable to another variable
foreach (var clause in components.WhereClauses) | ||
{ | ||
string condition = clause.Operator switch | ||
{ | ||
WhereOperator.Equal => BuildEqualityCondition(clause.PropertyName, clause.Value, ref paramIndex, paramList), | ||
WhereOperator.NotEqual => BuildInequalityCondition(clause.PropertyName, clause.Value, ref paramIndex, paramList), | ||
WhereOperator.GreaterThan => BuildComparisonCondition(clause.PropertyName, ">", clause.Value, ref paramIndex, paramList), | ||
WhereOperator.GreaterThanOrEqual => BuildComparisonCondition(clause.PropertyName, ">=", clause.Value, ref paramIndex, paramList), | ||
WhereOperator.LessThan => BuildComparisonCondition(clause.PropertyName, "<", clause.Value, ref paramIndex, paramList), | ||
WhereOperator.LessThanOrEqual => BuildComparisonCondition(clause.PropertyName, "<=", clause.Value, ref paramIndex, paramList), | ||
WhereOperator.Like => BuildLikeCondition(clause.PropertyName, clause.Value, ref paramIndex, paramList), | ||
WhereOperator.IsNull => $"{WrapIdentifier(clause.PropertyName)} IS NULL", | ||
WhereOperator.IsNotNull => $"{WrapIdentifier(clause.PropertyName)} IS NOT NULL", | ||
_ => throw new NotSupportedException($"Operator '{clause.Operator}' is not supported") | ||
}; | ||
|
||
conditions.Add(condition); | ||
} |
Check notice
Code scanning / CodeQL
Missed opportunity to use Select Note
maps its iteration variable to another variable
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 days ago
To fix this issue, replace the foreach
loop on line 90—which produces a new list by mapping each item but does not otherwise need the iteration variable—with a LINQ expression that explicitly maps the input sequence to the output using .Select(...)
. Specifically, the list conditions
can be initialized directly with the results of Select
. Because paramIndex
and paramList
are mutated as before (including byref for paramIndex
), the refactoring will be functionally equivalent. Only lines 87, 90–107 of BuildWhereClause
in FAnsi.Oracle/Queryable/OracleQueryBuilder.cs
need to be changed. No additional imports are required since System.Linq
is already present.
-
Copy modified lines R88-R89 -
Copy modified lines R100-R101
@@ -84,12 +84,9 @@ | ||
if (!components.WhereClauses.Any()) | ||
return string.Empty; | ||
|
||
var conditions = new System.Collections.Generic.List<string>(); | ||
int paramIndex = 0; | ||
|
||
foreach (var clause in components.WhereClauses) | ||
{ | ||
string condition = clause.Operator switch | ||
var conditions = components.WhereClauses.Select(clause => | ||
clause.Operator switch | ||
{ | ||
WhereOperator.Equal => BuildEqualityCondition(clause.PropertyName, clause.Value, ref paramIndex, paramList), | ||
WhereOperator.NotEqual => BuildInequalityCondition(clause.PropertyName, clause.Value, ref paramIndex, paramList), | ||
@@ -101,11 +97,9 @@ | ||
WhereOperator.IsNull => $"{WrapIdentifier(clause.PropertyName)} IS NULL", | ||
WhereOperator.IsNotNull => $"{WrapIdentifier(clause.PropertyName)} IS NOT NULL", | ||
_ => throw new NotSupportedException($"Operator '{clause.Operator}' is not supported") | ||
}; | ||
} | ||
).ToList(); | ||
|
||
conditions.Add(condition); | ||
} | ||
|
||
return " WHERE " + string.Join(" AND ", conditions); | ||
} | ||
|
foreach (var whereClause in components.WhereClauses) | ||
{ | ||
var condition = TranslateWhereClause(whereClause, paramList); | ||
sql.AppendLine($" AND {condition}"); | ||
} |
Check notice
Code scanning / CodeQL
Missed opportunity to use Select Note
maps its iteration variable to another variable
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 days ago
The loop at lines 95-100 iterates over components.WhereClauses
, transforms each whereClause
by calling TranslateWhereClause(whereClause, paramList)
, and then appends a line to the SQL string. The best fix is to use LINQ's Select
method to perform this transformation up front, obtaining an enumerable of condition
values, and then iterate over those for the appending operation. The edited block would replace the foreach (var whereClause in ...) { ... }
lines with a foreach (var condition in ...) { ... }
block, using .Select(...)
. No additional imports or methods are required since System.Linq
is already imported.
Modify lines 95–100 in FAnsi.PostgreSql/Queryable/PostgreSqlQueryBuilder.cs as follows:
- Replace the loop variable from
whereClause
tocondition
. - Replace the loop input from
components.WhereClauses
tocomponents.WhereClauses.Select(whereClause => TranslateWhereClause(whereClause, paramList))
. - Remove the local variable assignment inside the loop, as each
condition
is already mapped.
-
Copy modified line R95
@@ -92,9 +92,8 @@ | ||
// Add user-defined WHERE clauses | ||
if (components.WhereClauses?.Count > 0) | ||
{ | ||
foreach (var whereClause in components.WhereClauses) | ||
foreach (var condition in components.WhereClauses.Select(whereClause => TranslateWhereClause(whereClause, paramList))) | ||
{ | ||
var condition = TranslateWhereClause(whereClause, paramList); | ||
sql.AppendLine($" AND {condition}"); | ||
} | ||
} |
foreach (var whereClause in components.WhereClauses) | ||
{ | ||
var condition = TranslateWhereClause(whereClause, paramList); | ||
sql.AppendLine($" AND {condition}"); | ||
} |
Check notice
Code scanning / CodeQL
Missed opportunity to use Select Note
maps its iteration variable to another variable
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 days ago
To fix the problem, we should replace the foreach loop (lines 168–172) that translates each where-clause into a condition and appends it to the SQL, with LINQ's Select
to create a sequence of translated conditions and then append them all at once. The most idiomatic and efficient way would be to use Select
to produce the SQL fragments, and then either append each to sql
inside another loop, or—since all are being appended as " AND {condition}"
—combine them into a single string with line breaks and append once.
In this case, since the current code appends each with sql.AppendLine($" AND {condition}");
, we can simply use string.Join(Environment.NewLine, ...)
with the mapped collection, and append all at once to sql
. You may use .AppendLine(...)
or .Append(...)
as appropriate.
No new imports are required because System.Linq
is already imported.
Only lines 168–172 will be affected. All other context should be preserved.
-
Copy modified lines R168-R170
@@ -165,11 +165,9 @@ | ||
// Add user-defined WHERE clauses | ||
if (components.WhereClauses?.Count > 0) | ||
{ | ||
foreach (var whereClause in components.WhereClauses) | ||
{ | ||
var condition = TranslateWhereClause(whereClause, paramList); | ||
sql.AppendLine($" AND {condition}"); | ||
} | ||
var whereConditions = components.WhereClauses | ||
.Select(whereClause => $" AND {TranslateWhereClause(whereClause, paramList)}"); | ||
sql.AppendLine(string.Join(Environment.NewLine, whereConditions)); | ||
} | ||
|
||
// Add ORDER BY if specified |
foreach (var whereClause in components.WhereClauses) | ||
{ | ||
var condition = TranslateWhereClause(whereClause, paramList); | ||
if (!hasWhere) | ||
{ | ||
sql.AppendLine($"WHERE {condition}"); | ||
hasWhere = true; | ||
} | ||
else | ||
{ | ||
sql.AppendLine($" AND {condition}"); | ||
} | ||
} |
Check notice
Code scanning / CodeQL
Missed opportunity to use Select Note
maps its iteration variable to another variable
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 days ago
To correct the "missed opportunity to use Select," refactor the foreach
loop at line 221 into a LINQ-based projection using .Select()
to build up a list of condition strings, and then process them for SQL clause insertion. Since side effects (calls to TranslateWhereClause
) are preserved in order within .Select()
, we can safely change the logic.
However, because the SQL-building logic inside the loop is more complex than just string concatenation (it needs to emit a WHERE
for the first clause and AND
for the rest), the most idiomatic pattern is to first create the collection of conditions, then emit one with WHERE
and the rest with AND
. This ensures the improved clarity and separation of transformation from emission, as per recommendation.
Edit only the code inside the affected method, replacing the current foreach
block (lines 221–233) and appropriately adjusting the context.
-
Copy modified lines R221-R224 -
Copy modified line R226 -
Copy modified line R228 -
Copy modified line R233
@@ -218,17 +218,19 @@ | ||
// Add user-defined WHERE clauses | ||
if (components.WhereClauses?.Count > 0) | ||
{ | ||
foreach (var whereClause in components.WhereClauses) | ||
var conditions = components.WhereClauses | ||
.Select(whereClause => TranslateWhereClause(whereClause, paramList)) | ||
.ToList(); | ||
for (int i = 0; i < conditions.Count; i++) | ||
{ | ||
var condition = TranslateWhereClause(whereClause, paramList); | ||
if (!hasWhere) | ||
if (i == 0 && !hasWhere) | ||
{ | ||
sql.AppendLine($"WHERE {condition}"); | ||
sql.AppendLine($"WHERE {conditions[i]}"); | ||
hasWhere = true; | ||
} | ||
else | ||
{ | ||
sql.AppendLine($" AND {condition}"); | ||
sql.AppendLine($" AND {conditions[i]}"); | ||
} | ||
} | ||
} |
- Combined nested if statements in FAnsiExpressionVisitor.cs for cleaner logic flow - Replaced if-else block with ternary operator in FAnsiQueryProvider.cs for more concise code 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Summary
This PR addresses 8 CodeQL alerts for missing XML documentation summaries by adding explicit
<summary>
tags to methods that were using only<include>
tags.Changes
Added
<summary>
tags to the following files:FAnsi.Core/Discovery/IDiscoveredServerHelper.cs
- GetCommand methodFAnsi.Core/Discovery/DiscoveredServerHelper.cs
- GetCommand, GetDataAdapter, GetCommandBuilder, GetParameter methodsFAnsi.Core/Discovery/DiscoveredServer.cs
- GetCommand methodFAnsi.Core/Discovery/DiscoveredTable.cs
- GetTopXSql methodFAnsi.Core/Discovery/IDiscoveredTableHelper.cs
- GetTopXSqlForTable methodCodeQL Alerts Analysis
Of the 40 open CodeQL alerts:
Addressed (8 alerts - HicServices#33-40)
<include>
tags but CodeQL requires explicit<summary>
tags<include>
documentationNot Addressed (32 alerts - #11-32)
catch (Exception)
for:Testing
Impact
🤖 Generated with Claude Code