11using System . IO ;
2+ using System . Linq ;
23using Microsoft . CodeAnalysis ;
34using Microsoft . CodeAnalysis . CSharp . Syntax ;
45using 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