From 05b72ebea1998be1be79f8a0f9c589acf7717017 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Wed, 28 Jun 2023 12:47:35 -0400 Subject: [PATCH 1/2] Add what's new for interceptors. --- docs/csharp/whats-new/csharp-12.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/csharp/whats-new/csharp-12.md b/docs/csharp/whats-new/csharp-12.md index d857b462601b8..0f4f15de7e084 100644 --- a/docs/csharp/whats-new/csharp-12.md +++ b/docs/csharp/whats-new/csharp-12.md @@ -10,6 +10,7 @@ Some C# 12 features have been introduced in previews. You can try these features - [Primary constructors](#primary-constructors) - Introduced in Visual Studio 17.6 preview 2. - [Optional parameters in lambda expressions](#default-lambda-parameters) - Introduced in Visual Studio 17.5 preview 2. - [Alias any type](#alias-any-type) - Introduced in Visual Studio 17.6 preview 3. +- [Interceptors](#interceptors) - *Preview feature* Introduced in Visual Studio 17.7, preview 3. ## Primary constructors @@ -29,6 +30,19 @@ You can learn more about default parameters on lambda expressions in the article You can use the `using` alias directive to alias any type, not just named types. That means you can create semantic aliases for tuple types, array types, pointer types, or other unsafe types. For more information, see the [feature specification](~/_csharplang/proposals/using-alias-types.md) +## Interceptors + +> [!WARNING] +> Interceptors are an experimental feature, available in preview mode with C# 12. The feature may be subject to breaking changes or removal in a future release. Therefore, it is not recommended for production or released applications. +> +> In order to use interceptors, you'll need to set the `` element in your project file to `preview`. + +An *interceptor* is a method which can declaratively substitute a call to an *interceptable* method with a call to itself at compile time. This substitution occurs by having the interceptor declare the source locations of the calls that it intercepts. This provides a limited facility to change the semantics of existing code by adding new code to a compilation, for example in a source generator. + +You use an *interceptor* as part of a source generator to modify, rather than add code to an existing soruce compilation. The source generator substitutes calls to an interceptable method with a call to the *interceptor* method. + +If you are interested in experimenting with interceptors, you can learn more by reading the [feature specification](https://github.com/dotnet/roslyn/blob/main/docs/features/interceptors.md). If you use the feature, make sure to stay current with any changes in the feature specification for this preview feature. Once the feature is finalized, we'll add more guidance on this site. + ## See also - [What's new in .NET 8](../../core/whats-new/dotnet-8.md) From e9b6f78b33035b7317cdc168ecde2738b92e1f1e Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Thu, 29 Jun 2023 15:30:54 -0400 Subject: [PATCH 2/2] Add information on interceptors Add what's new and error / warning information for Interceptors. Fixes #35878 This feature is experimental, so for details I'm linking to the feature spec in the roslyn repo. The feature may change. When it's finalized, I'll add more details on it in docs, and remove the warnings about its experimental status. --- .../source-generator-errors.md | 159 ++++++++++++++++++ .../compiler-messages/toc.yml | 3 + docs/csharp/whats-new/csharp-12.md | 2 +- 3 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 docs/csharp/language-reference/compiler-messages/source-generator-errors.md diff --git a/docs/csharp/language-reference/compiler-messages/source-generator-errors.md b/docs/csharp/language-reference/compiler-messages/source-generator-errors.md new file mode 100644 index 0000000000000..3924a3b149f93 --- /dev/null +++ b/docs/csharp/language-reference/compiler-messages/source-generator-errors.md @@ -0,0 +1,159 @@ +--- +title: Errors and warnings associated with source generators and interceptors +description: You may see these errors and warnings when code is compiled with source generators and interceptors. They indicate some condition where the compiler can't run the source generator, or the generate code isn't compilable. +f1_keywords: + - "CS9137" + - "CS9138" + - "CS9139" + - "CS9140" + - "CS9141" + - "CS9142" + - "CS9143" + - "CS9144" + - "CS9145" + - "CS9146" + - "CS9147" + - "CS9148" + - "CS9149" + - "CS9150" + - "CS9151" + - "CS9152" + - "CS9153" + - "CS9154" + - "CS9155" + - "CS9156" + - "CS9157" + - "CS9158" + - "CS9159" + - "CS9160" + - "CS9161" +helpviewer_keywords: + - "CS9137" + - "CS9138" + - "CS9139" + - "CS9140" + - "CS9141" + - "CS9142" + - "CS9143" + - "CS9144" + - "CS9145" + - "CS9146" + - "CS9147" + - "CS9148" + - "CS9149" + - "CS9150" + - "CS9151" + - "CS9152" + - "CS9153" + - "CS9154" + - "CS9155" + - "CS9156" + - "CS9157" + - "CS9158" + - "CS9159" + - "CS9160" + - "CS9161" +ms.date: 06/28/2023 +--- +# Errors and warnings associated with source generators and interceptors + +The following errors may be generated when source generators or interceptors are loaded during a compilation: + +- [**CS9137**](#interceptors-are-experimental): *The 'interceptors' experimental feature is not enabled. Add `InterceptorsPreview` to your project.* +- [**CS9138**](#other-failures): *Method cannot be used as an interceptor because it or its containing type has type parameters.* +- [**CS9139**](#incorrect-mapping): *Cannot intercept: compilation does not contain a file with path.* +- [**CS9140**](#incorrect-mapping): *Cannot intercept: compilation does not contain a file with path. Did you mean to use a different path?* +- [**CS9141**](#incorrect-mapping): *The provided line and character number does not refer to an interceptable method name, but rather to a token.* +- [**CS9142**](#incorrect-mapping): *The given file has `n` lines, which is fewer than the provided line number `m`.* +- [**CS9143**](#incorrect-mapping): *The given line is `c` characters long, which is fewer than the provided character number `n`.* +- [**CS9144**](#signature-mismatch): *Cannot intercept method `M` with interceptor `V` because the signatures do not match.* +- [**CS9145**](#incorrect-mapping): *Cannot intercept: Path is unmapped. Expected mapped path.* +- [**CS9146**](#other-failures): *An interceptor method must be an ordinary member method.* +- [**CS9147**](#incorrect-mapping): *The provided line and character number does not refer to the start of a token. Did you mean to use line `n` and character `c`?* +- [**CS9148**](#signature-mismatch): *Interceptor must have a `this` parameter matching parameter.* +- [**CS9149**](#signature-mismatch): *Interceptor must not have a `this` parameter because method does not have a `this` parameter.* +- [**CS9150**](#incorrect-mapping): *Interceptor cannot have a `null` file path.* +- [**CS9151**](#other-failures): *Possible method name `M` cannot be intercepted because it is not being invoked.* +- [**CS9152**](#other-failures): *Cannot intercept a call in file with this path because multiple files in the compilation have this path.* +- [**CS9153**](#other-failures): *The indicated call is intercepted multiple times.* +- [**CS9155**](#signature-mismatch): *Cannot intercept call with `M` because it is not accessible within `V`.* +- [**CS9156**](#signature-mismatch): *Cannot intercept call to `M` with `V` because of a difference in 'scoped' modifiers or `[UnscopedRef]` attributes.* +- [**CS9157**](#incorrect-mapping): *Line and character numbers provided to `InterceptsLocationAttribute` must be positive.* +- [**CS9160**](#other-failures): *A nameof operator cannot be intercepted.* +- [**CS9161**](#other-failures): *An interceptor cannot be marked with `UnmanagedCallersOnlyAttribute`.* + +The following warnings may be generated when source generators or interceptors are loaded during a compilation: + +- [**CS9154**](#signature-mismatch): *Intercepting a call to `M` with interceptor `V`, but the signatures do not match.* +- [**CS9158**](#signature-mismatch): *Nullability of reference types in return type doesn't match interceptable method.* +- [**CS9159**](#signature-mismatch): *Nullability of reference types in type of parameter doesn't match interceptable method.* + +These errors and warnings follow these themes: + +## Interceptors are experimental + +This error indicates you haven't enabled the experimental feature. + +- **CS9137**: *The 'interceptors' experimental feature is not enabled. Add `InterceptorsPreview` to your project.* + +In C# 12, interceptors are experimental. Interceptors may be subject to breaking changes or removal in a future release. Therefore, it is not recommended for production or released applications. + +In order to use interceptors, you'll need to set the `InterceptorsPreview` element in your project file. Without this flag, interceptors are disabled, even when other C# 12 features are enabled. + +## Signature mismatch + +The following errors indicate a mismatch between the interceptor method and the interceptable method, or a violation of the rules regarding interceptor method declarations: + +- **CS9144**: *Cannot intercept method `M` with interceptor `V` because the signatures do not match.* +- **CS9148**: *Interceptor must have a `this` parameter matching parameter.* +- **CS9149**: *Interceptor must not have a `this` parameter because method does not have a `this` parameter.* +- **CS9155**: *Cannot intercept call with `M` because it is not accessible within `V`.* +- **CS9156**: *Cannot intercept call to `M` with `V` because of a difference in 'scoped' modifiers or `[UnscopedRef]` attributes.* + +In addition, the following warnings indicate a mismatch in the signatures of the interceptor and and the interceptable method: + +- **CS9154**: *Intercepting a call to `M` with interceptor `V`, but the signatures do not match.* +- **CS9158**: *Nullability of reference types in return type doesn't match interceptable method.* +- **CS9159**: *Nullability of reference types in type of parameter doesn't match interceptable method.* + +The interceptor method must be compatible with the interceptable method. You must follow these rules: + +- Instance methods can intercept instance methods, not static methods. Similarly, static methods can only intercept static methods, not instance methods. +- The method signatures for the interceptor and the interceptable method must match: They must have the same parameters with the same modifiers in the same order. The return types must also match. +- The ref safe contexts must match. In other words, corresponding `ref` parameters must be either `scoped` or not `scoped`. + +## Incorrect mapping + +Interceptors require a source mapping that maps the interceptable method and the interceptor method. The following error indicate an issue with the mapping: + +- **CS9139**: *Cannot intercept: compilation does not contain a file with path.* +- **CS9140**: *Cannot intercept: compilation does not contain a file with path. Did you mean to use a different path?* +- **CS9141**: *The provided line and character number does not refer to an interceptable method name, but rather to a token.* +- **CS9142**: *The given file has `n` lines, which is fewer than the provided line number `m`.* +- **CS9143**: *The given line is `c` characters long, which is fewer than the provided character number `n`.* +- **CS9145**: *Cannot intercept: Path is unmapped. Expected mapped path.* +- **CS9147**: *The provided line and character number does not refer to the start of a token. Did you mean to use line `n` and character `c`?* +- **CS9150**: *Interceptor cannot have a `null` file path.* +- **CS9157**: *Line and character numbers provided to `InterceptsLocationAttribute` must be positive.* + +An interceptor specifies the location in the source code of the interceptable method. You specify the location by applying an `[InterceptsLocation]` attribute. You specify the line and column numbers in a remapped source file where the interceptor should be injected. These errors indicate that something in the attribute or the location doesn't match a location for a valid interceptable method. For details on the format and values for this attribute, see the [feature specification](https://github.com/dotnet/roslyn/blob/main/docs/features/interceptors.md#interceptslocationattribute). + +## Other failures + +These errors indicate other limitations for interceptors: + +- **CS9138**: *Method cannot be used as an interceptor because it or its containing type has type parameters.* +- **CS9146**: *An interceptor method must be an ordinary member method.* +- **CS9151**: *Possible method name `M` cannot be intercepted because it is not being invoked.* +- **CS9152**: *Cannot intercept a call in file with this path because multiple files in the compilation have this path.* +- **CS9153**: *The indicated call is intercepted multiple times.* +- **CS9160**: *A nameof operator cannot be intercepted.* +- **CS9161**: *An interceptor cannot be marked with `UnmanagedCallersOnlyAttribute`.* + +These errors indicate that your interceptor method violates one of the rules for interceptors: + +- Interceptors can't be generic methods, or members of generic classes. +- Interceptors must be ordinary members. They can't be operators, instance or static constructors, or finalizers. +- Interceptable methods that are never invoked can't be intercepted. +- Interceptable methods can be intercepted at most once. +- Interceptors can't be methods limited to unmanaged callers. diff --git a/docs/csharp/language-reference/compiler-messages/toc.yml b/docs/csharp/language-reference/compiler-messages/toc.yml index 6282c8a77936d..21fc83a422b74 100644 --- a/docs/csharp/language-reference/compiler-messages/toc.yml +++ b/docs/csharp/language-reference/compiler-messages/toc.yml @@ -1979,6 +1979,9 @@ items: - name: Pattern matching warnings href: pattern-matching-warnings.md displayName: CS8509 +- name: Source generators + href: source-generator-errors.md + displayName: CS9137, CS9138, CS9139, CS9140, CS9141, CS9142, CS9143, CS9144, CS9145, CS9146, CS9147, CS9148, CS9149, CS9150, CS9151, CS9152, CS9153, CS9154, CS9155, CS9156, CS9157, CS9158, CS9159, CS9160, CS9161 - name: Warning waves href: warning-waves.md displayName: CS7023, CS8073, CS8848, CS8880, CS8881, CS8882, CS8883, CS8884, CS8885, CS8886, CS8887, CS8892, CS8897, CS8898, CS8826, CS8981 diff --git a/docs/csharp/whats-new/csharp-12.md b/docs/csharp/whats-new/csharp-12.md index 0f4f15de7e084..72f0b4c72e7cc 100644 --- a/docs/csharp/whats-new/csharp-12.md +++ b/docs/csharp/whats-new/csharp-12.md @@ -35,7 +35,7 @@ You can use the `using` alias directive to alias any type, not just named types. > [!WARNING] > Interceptors are an experimental feature, available in preview mode with C# 12. The feature may be subject to breaking changes or removal in a future release. Therefore, it is not recommended for production or released applications. > -> In order to use interceptors, you'll need to set the `` element in your project file to `preview`. +> In order to use interceptors, you'll need to set the `InterceptorsPreview` element in your project file. Without this flag, interceptors are disabled, even when other C# 12 features are enabled. An *interceptor* is a method which can declaratively substitute a call to an *interceptable* method with a call to itself at compile time. This substitution occurs by having the interceptor declare the source locations of the calls that it intercepts. This provides a limited facility to change the semantics of existing code by adding new code to a compilation, for example in a source generator.