Skip to content

Commit 999e066

Browse files
committed
C#: Extract the indexer as the call target when using range expressions with spans.
1 parent 6d375b3 commit 999e066

1 file changed

Lines changed: 32 additions & 3 deletions

File tree

csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ElementAccess.cs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.IO;
2+
using System.Linq;
23
using Microsoft.CodeAnalysis;
34
using Microsoft.CodeAnalysis.CSharp.Syntax;
45
using Semmle.Extraction.Kinds;
@@ -17,6 +18,35 @@ protected ElementAccess(ExpressionNodeInfo info, ExpressionSyntax qualifier, Bra
1718
private readonly ExpressionSyntax qualifier;
1819
private readonly BracketedArgumentListSyntax argumentList;
1920

21+
22+
private IPropertySymbol? GetIndexerSymbol()
23+
{
24+
var symbol = Context.GetSymbolInfo(base.Syntax).Symbol;
25+
26+
if (symbol is IPropertySymbol { IsIndexer: true } indexer)
27+
return indexer;
28+
29+
// In some cases, Roslyn translates the use of range expressions directly into method calls.
30+
// E.g. `a[0..3]` is translated into `a.Slice(0, 3)`, if `a` is a `Span<T>`.
31+
// In this case, we want to populate the indexer access as normal (as this reflects the source code more accurately).
32+
if (symbol is IMethodSymbol method)
33+
{
34+
var indexers = method
35+
.ContainingType
36+
.GetMembers()
37+
.OfType<IPropertySymbol>()
38+
.Where(p => p.IsIndexer);
39+
40+
var intIndexer = indexers
41+
.Where(i => i.Parameters.Length == 1 && i.Parameters[0].Type.SpecialType == SpecialType.System_Int32)
42+
.FirstOrDefault();
43+
44+
return intIndexer;
45+
}
46+
47+
return null;
48+
}
49+
2050
protected override void PopulateExpression(TextWriter trapFile)
2151
{
2252
if (Kind == ExprKind.POINTER_INDIRECTION)
@@ -32,9 +62,8 @@ protected override void PopulateExpression(TextWriter trapFile)
3262
Create(Context, qualifier, this, -1);
3363
PopulateArguments(trapFile, argumentList, 0);
3464

35-
var symbolInfo = Context.GetSymbolInfo(base.Syntax);
36-
37-
if (symbolInfo.Symbol is IPropertySymbol indexer)
65+
var indexer = GetIndexerSymbol();
66+
if (indexer is not null)
3867
{
3968
trapFile.expr_access(this, Indexer.Create(Context, indexer));
4069
}

0 commit comments

Comments
 (0)