-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Add public API to determine if a call is being intercepted #72093
Comments
See: #72070 It will allow you to be fast about finding attributes. Also, since the invocation expression is being passed in, you can use that to prefilter potential attributes syntactically to those that reference the file/line/col of that invocation expression. No need to bind if they couldn't possibly match. |
That's sounds bad, unless you can guarantee that this will be fast/cheap. We don't want getting operations to fall off a perf cliff. |
i'm not a huge fan of this being typed to InvocationExpression. What happens when we expand interceptors to constructors, operators, indexers, etc. I do like tying this to IOperation only, but behind a cancellable call. |
How do we intend to mark this experimental btw? An attribute on the api? |
This is a fair concern. I outlined my view on this question in the linked csharplang proposal. Pasting here:
|
Yes, if we want to ship this as experimental, we can definitely just put |
Don't we also need an API for generators that maps a |
InvocationExpression seems like the wrong type. Consider:
When this is intercepted I won't have an invite invocation to pass in to her the info on. The interceptor is on a token span-start. That's what should be passed in. |
1 similar comment
InvocationExpression seems like the wrong type. Consider:
When this is intercepted I won't have an invite invocation to pass in to her the info on. The interceptor is on a token span-start. That's what should be passed in. |
I personally don't like this. It doesn't work that way for GetSymbolInfo/GetTypeInfo/GetConstantValue. This feels like over indexing on a spike. The spike is to demonstrate viability. But the API should be designed against the general concept. Put another way, imagine we added constants to the language, but initially in a prototype where it was just integer literals. Having the API only allow that would just box us in when doing the natural and expected expansion later. |
The more I think about this, the more this should be an iop API. I don't see how things like intercepting an implicit operator would work here. Iop properly represents the semantic tree, and is the modern way to get all the info we just to try to have to jam in with specialized helpers on semanticmodel |
I personally would be fine with the following shape: namespace Microsoft.CodeAnalysis.Operations;
public interface IInvocationOperation : IOperation
{
IMethodSymbol TargetMethod { get; }
+ /// <summary>Gets the method which is intercepting this call, if any.</summary>
+ IMethodSymbol? GetInterceptorMethod(CancellationToken token = default);
} the above indicating that calling it may cause work to be done, which can be canceled with a token if desired. |
Per offline feedback, I have edited issue title and description to include the proposal for the full set of public APIs we want for the interceptors feature. |
Tagging @captainsafia @agocke for visibility |
Broken out second part of the API request into #72133 |
API Review
Conclusion: We approved the |
Background and Motivation
As we work to stabilize the interceptors feature, we have public API additions which are needed in order to deliver a fully coherent and usable feature experience.
Need for interceptor semantic info in IDE
See also https://github.com/dotnet/csharplang/blob/interceptors-2024-01/proposals/interceptors-issues-2024-01.md#need-for-interceptor-semantic-info-in-ide
Currently, the Roslyn public APIs provide no indication of whether a method call is being intercepted. After shipping the interceptors experimental feature, we found that some analyzers had a need to know when a call is being intercepted, in order to produce correct diagnostics.
In the above sample, the ILLinker analyzer will warn about use of a method marked with
[RequiresUnreferencedCode]
. If it knew that the call was intercepted, and could inspect the interceptor method instead, then it would be able to give more accurate diagnostics (i.e., it would know that it does not need to warn on the above call.)In .NET 8, we worked around the spurious warning in the above sample by having the generator author ship a diagnostic suppressor. We think this is problematic as a practice because it requires the generator author to understand the semantics of the warning deeply enough to be able to claim "actually, this doesn't apply to me". If, for example, the interceptor method also had
[RequiresUnreferencedCode]
, we wouldn't want the warning to be suppressed, and it seems like a layering violation for the source generator to need to know these kinds of in-depth details about another component.Proposed API
This API shape is intended to reflect the fact that the first time an analyzer asks about interceptors, a certain amount of fixed-overhead work will need to be done and cached on the compilation. Specifically, we will need to search declarations in the compilation for any attributes which might be
[InterceptsLocation]
(taking aliases into account), and bind them. We expect a quite small subset of attributes on methods to be bound in this process.Usage Examples
Alternative Designs
We rejected a design which added a member to
IInvocationOperation
to get the interceptor--either a method which takes CancellationToken or a property accessor.Risks
This API adds complexity to analyzers: they need to decide if they care about intercepted calls or not. In most cases, we believe analyzers do not need to care about intercepted calls. Looking at the original call should be good enough.
The essential case where an analyzer may need to look at the interceptor of a call is when legal signature differences between the interceptor and original methods might influence the analyzer's behavior. In the ILLinker analyzer case, its behavior differs based on presence or absence of the
[RequiresUnreferencedCode]
attribute. This makes interceptors of interest to that analyzer.The text was updated successfully, but these errors were encountered: