Skip to content

C#: Extract .Slice method call when using a span in conjunction with a range.#21877

Draft
michaelnebel wants to merge 13 commits into
github:mainfrom
michaelnebel:csharp/spanaccessrange
Draft

C#: Extract .Slice method call when using a span in conjunction with a range.#21877
michaelnebel wants to merge 13 commits into
github:mainfrom
michaelnebel:csharp/spanaccessrange

Conversation

@michaelnebel
Copy link
Copy Markdown
Contributor

@michaelnebel michaelnebel commented May 21, 2026

Improves the extraction of span access with range expressions (such as a[1..3]).

Roslyn translates a[1..3] into a.Slice(1,3 - 1) for spans (and something similar for strings).
In this PR we introduce some special handling in the extractor for such cases

  • Instead of extracting an indexer access on a we extract a a.Slice method call.
  • Instead of extracting the range expression, we use the range expression to synthesize call arguments for a.Slice.

Roslyn translates as follows

  • a[x..y] is translated to a.Slice(x, y - x).
  • a[..y] is translated to a.Slice(0, y)
  • a[x..] is translated to a.Slice(x, a.Length - x).
  • a[..] is translated to a.Slice(0, a.Length).

It is also possible to use read from the end as well (e.g. ^2).

  • a[x..^y] translates into a.Slice(x, a.Length - y - x).

Furthermore, it is worth noting that the range endpoints could be the result of a method call.
This means that if we want to fully synthesize var a = f()[m() .. ^3], we would need to synthesize

var q = f();
var x = m();
var a = q.Slice(x, q.Length - 3 - x);

For simplicity reasons, we choose to extract as follows

  • a[x..y] is translated to a.Slice(x, y).
  • a[..y] is translated to a.Slice(0, y)
  • a[x..] is translated to a.Slice(x, ^0).
  • a[..] is translated to a.Slice(0, ^0).

This will make it possible to calculate the correct start index and length arguments in the QL side (if needed).

Similar to span access with range expressions, it is also possible to use range expressions in conjunction with strings. If s is a string, then s[1..3] translates into s.Substring(1, 3 - 1). This is also handled in this PR.

@michaelnebel michaelnebel force-pushed the csharp/spanaccessrange branch from 4eec760 to 9167814 Compare May 28, 2026 10:36
@michaelnebel michaelnebel marked this pull request as ready for review May 28, 2026 11:52
@michaelnebel michaelnebel requested a review from a team as a code owner May 28, 2026 11:52
Copilot AI review requested due to automatic review settings May 28, 2026 11:52
@michaelnebel michaelnebel requested a review from hvitved May 28, 2026 11:52
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves the C# extractor’s handling of element-access expressions that use range syntax (for example, a[0..3]) when Roslyn lowers them into method calls (for example, Slice(...)). The goal is to preserve the source-level “indexer access” shape by still recording an indexer as the call target, improving database-quality telemetry.

Changes:

  • Added extractor special-casing to recover an indexer symbol even when Roslyn binds the element access to a method symbol.
  • Updated the Telemetry/DatabaseQuality query test inputs and expected outputs to reflect the improved extraction.
  • Added a C# library change note documenting the analysis-impacting extraction improvement.
Show a summary per file
File Description
csharp/ql/test/query-tests/Telemetry/DatabaseQuality/Quality.cs Updates test code to treat range element access as properly-targeted indexer calls.
csharp/ql/test/query-tests/Telemetry/DatabaseQuality/NoTarget.expected Removes expected “missing call target” results now that targets are extracted.
csharp/ql/test/query-tests/Telemetry/DatabaseQuality/IsNotOkayCall.expected Eliminates expected “not ok” call-target results for the fixed cases.
csharp/ql/lib/change-notes/2026-05-21-spanaccess-range.md Documents the extraction change as a minor analysis improvement.
csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ElementAccess.cs Implements the new symbol recovery logic for range-based element access.

Copilot's findings

  • Files reviewed: 5/5 changed files
  • Comments generated: 1

Comment thread csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ElementAccess.cs Outdated
Copy link
Copy Markdown
Contributor

@hvitved hvitved left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not convinced that extracting the indexer is what we want; what about extracting the Roslyn-resolved targets instead and treating the index expressions as ordinary method calls?

@michaelnebel
Copy link
Copy Markdown
Contributor Author

michaelnebel commented May 29, 2026

I'm not convinced that extracting the indexer is what we want; what about extracting the Roslyn-resolved targets instead and treating the index expressions as ordinary method calls?

Yes, I also considered that, but thought it would be better to extract something that more closely resembles the syntax instead of what it is being translated into. If I were to query our code and asking for uses of indexers, then I would expect cases like a[1..3] to show up. Otherwise I would need to know that for spans, then a[1..3] translates into a.Slice(1,3-1) and for strings it would translate into a.Substring(1,3-1).
If you prefer that we extract the actual methods calls, then we can definitely do that instead?

@michaelnebel michaelnebel self-assigned this Jun 1, 2026
@michaelnebel michaelnebel marked this pull request as draft June 2, 2026 13:48
@michaelnebel michaelnebel force-pushed the csharp/spanaccessrange branch from 9167814 to ee734c9 Compare June 2, 2026 14:05
Comment thread csharp/ql/test/library-tests/spans/slice.expected Outdated
Comment thread csharp/ql/test/library-tests/spans/slice.expected Outdated
Comment thread csharp/ql/test/library-tests/spans/slice.expected Outdated
@michaelnebel michaelnebel force-pushed the csharp/spanaccessrange branch from ee734c9 to 8d0575c Compare June 3, 2026 09:41
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 8/8 changed files
  • Comments generated: 3

Comment thread csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ElementAccess.cs Outdated
Comment thread csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ElementAccess.cs Outdated
Comment thread csharp/ql/lib/change-notes/2026-05-21-spanaccess-range.md Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 8/8 changed files
  • Comments generated: 2

Comment thread csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ElementAccess.cs Outdated
@michaelnebel michaelnebel changed the title C#: Extract indexer when accessing a span with a range. C#: Extract .Slice method call when using a span in conjunction with a range. Jun 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants