mirror of
https://github.com/github/codeql.git
synced 2026-04-29 18:55:14 +02:00
C#: Adjust conditional access locations
This commit is contained in:
@@ -314,24 +314,46 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given b in a?.b.c, return a.
|
||||
/// Given `b` in `a?.b.c`, return `(a?.b, a?.b)`.
|
||||
///
|
||||
/// Given `c` in `a?.b?.c.d`, return `(b?.c, a?.b?.c)`.
|
||||
/// </summary>
|
||||
/// <param name="node">A MemberBindingExpression.</param>
|
||||
/// <returns>The qualifier of the conditional access.</returns>
|
||||
protected static ExpressionSyntax FindConditionalQualifier(ExpressionSyntax node)
|
||||
/// <returns>The conditional access.</returns>
|
||||
public static (ConditionalAccessExpressionSyntax Parent, ConditionalAccessExpressionSyntax Root) FindConditionalAccessParent(ExpressionSyntax node)
|
||||
{
|
||||
for (SyntaxNode? n = node; n is not null; n = n.Parent)
|
||||
(ConditionalAccessExpressionSyntax, ConditionalAccessExpressionSyntax)? res = null;
|
||||
SyntaxNode? prev = null;
|
||||
|
||||
for (SyntaxNode? n = node; n is not null; prev = n, n = n.Parent)
|
||||
{
|
||||
if (n.Parent is ConditionalAccessExpressionSyntax conditionalAccess &&
|
||||
conditionalAccess.WhenNotNull == n)
|
||||
if (n is ConditionalAccessExpressionSyntax conditionalAccess &&
|
||||
(prev is null || conditionalAccess.WhenNotNull == prev))
|
||||
{
|
||||
return conditionalAccess.Expression;
|
||||
res = res is null ? (conditionalAccess, conditionalAccess) : (res.Value.Item1, conditionalAccess);
|
||||
}
|
||||
else if (res.HasValue)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (res.HasValue)
|
||||
{
|
||||
return res.Value;
|
||||
}
|
||||
|
||||
throw new InternalError(node, "Unable to locate a ConditionalAccessExpression");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given b in a?.b.c, return a.
|
||||
/// </summary>
|
||||
/// <param name="node">A MemberBindingExpression.</param>
|
||||
/// <returns>The qualifier of the conditional access.</returns>
|
||||
protected static ExpressionSyntax FindConditionalQualifier(ExpressionSyntax node) =>
|
||||
FindConditionalAccessParent(node).Parent.Expression;
|
||||
|
||||
public void MakeConditional(TextWriter trapFile)
|
||||
{
|
||||
trapFile.conditional_access(this);
|
||||
|
||||
@@ -125,11 +125,6 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
cachedLocation = Context.CreateLocation(CodeAnalysisLocation);
|
||||
return cachedLocation;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
cachedLocation = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ExprKind Kind { get; set; } = ExprKind.UNKNOWN;
|
||||
|
||||
@@ -79,7 +79,9 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
internal class BindingElementAccess : ElementAccess
|
||||
{
|
||||
private BindingElementAccess(ExpressionNodeInfo info)
|
||||
: base(info, FindConditionalQualifier(info.Node), ((ElementBindingExpressionSyntax)info.Node).ArgumentList) { }
|
||||
: base(info, FindConditionalQualifier(info.Node), ((ElementBindingExpressionSyntax)info.Node).ArgumentList)
|
||||
{
|
||||
}
|
||||
|
||||
public static Expression Create(ExpressionNodeInfo info) => new BindingElementAccess(info).TryPopulate();
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Semmle.Extraction.CSharp.Populators
|
||||
/// <param name="l1">The location to extend.</param>
|
||||
/// <param name="n2">The node to extend the location to.</param>
|
||||
/// <returns>Extended location.</returns>
|
||||
public static Location ExtendLocation(this Location l1, SyntaxNode n2)
|
||||
public static Location ExtendLocation(this Location l1, SyntaxNode n2, bool onlyStart = false)
|
||||
{
|
||||
if (n2 is null)
|
||||
{
|
||||
@@ -22,7 +22,7 @@ namespace Semmle.Extraction.CSharp.Populators
|
||||
|
||||
var l2 = n2.FixedLocation();
|
||||
var start = System.Math.Min(l1.SourceSpan.Start, l2.SourceSpan.Start);
|
||||
var end = System.Math.Max(l1.SourceSpan.End, l2.SourceSpan.End);
|
||||
var end = onlyStart ? l1.SourceSpan.End : System.Math.Max(l1.SourceSpan.End, l2.SourceSpan.End);
|
||||
return Location.Create(n2.SyntaxTree, new Microsoft.CodeAnalysis.Text.TextSpan(start, end - start));
|
||||
}
|
||||
|
||||
@@ -85,6 +85,17 @@ namespace Semmle.Extraction.CSharp.Populators
|
||||
return ((CatchDeclarationSyntax)node).Identifier.GetLocation();
|
||||
case SyntaxKind.LabeledStatement:
|
||||
return ((LabeledStatementSyntax)node).Identifier.GetLocation();
|
||||
case SyntaxKind.ElementBindingExpression:
|
||||
return node.GetLocation().ExtendLocation(Entities.Expression.FindConditionalAccessParent((ElementBindingExpressionSyntax)node).Root, onlyStart: true);
|
||||
case SyntaxKind.MemberBindingExpression:
|
||||
return node.GetLocation().ExtendLocation(Entities.Expression.FindConditionalAccessParent((MemberBindingExpressionSyntax)node).Root, onlyStart: true);
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
return node.GetLocation().ExtendLocation(((ElementAccessExpressionSyntax)node).Expression);
|
||||
case SyntaxKind.SimpleMemberAccessExpression:
|
||||
return node.GetLocation().ExtendLocation(((MemberAccessExpressionSyntax)node).Expression);
|
||||
case SyntaxKind.InvocationExpression:
|
||||
return node.GetLocation().ExtendLocation(((InvocationExpressionSyntax)node).Expression);
|
||||
|
||||
default:
|
||||
result = node.GetLocation();
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user