Skip to content

Commit

Permalink
Merge 'main' into features/FirstClassSpan (#74406)
Browse files Browse the repository at this point in the history
  • Loading branch information
jjonescz authored Jul 17, 2024
2 parents bcb24fb + 71470a7 commit cd9cb9d
Show file tree
Hide file tree
Showing 1,320 changed files with 27,413 additions and 13,798 deletions.
3 changes: 2 additions & 1 deletion Directory.Build.rsp
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
# This file intentionally left blank to avoid accidental import during build.
# Workaround for https://github.com/dotnet/sdk/issues/41791
-p:_IsDisjointMSBuildVersion=false
11 changes: 9 additions & 2 deletions docs/Language Feature Status.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,25 @@ efforts behind them.

| Feature | Branch | State | Developer | Reviewer | IDE Buddy | LDM Champ |
| ------- | ------ | ----- | --------- | -------- | --------- | --------- |
| [Overload Resolution Priority](https://github.com/dotnet/csharplang/issues/7706) | PR not yet available | [In Progress](https://github.com/dotnet/roslyn/issues/74131) | [333fred](https://github.com/333fred) | [jcouv](https://github.com/jcouv), [cston](https://github.com/cston) | Not yet assigned | [333fred](https://github.com/333fred) |
| [First-class Span Types](https://github.com/dotnet/csharplang/issues/7905) | [FirstClassSpan](https://github.com/dotnet/roslyn/tree/features/FirstClassSpan) | [In Progress](https://github.com/dotnet/roslyn/issues/73445) | [jjonescz](https://github.com/jjonescz) | [cston](https://github.com/cston), [333fred](https://github.com/333fred) | | [333fred](https://github.com/333fred), [stephentoub](https://github.com/stephentoub) |
| [Semi-auto-properties](https://github.com/dotnet/csharplang/issues/140) | [semi-auto-props](https://github.com/dotnet/roslyn/tree/features/semi-auto-props) | [In Progress](https://github.com/dotnet/roslyn/issues/57012) | [Youssef1313](https://github.com/Youssef1313) | [333fred](https://github.com/333fred), [RikkiGibson](https://github.com/RikkiGibson) | [CyrusNajmabadi](https://github.com/CyrusNajmabadi) | [CyrusNajmabadi](https://github.com/CyrusNajmabadi) |
| [Default in deconstruction](https://github.com/dotnet/roslyn/pull/25562) | [decon-default](https://github.com/dotnet/roslyn/tree/features/decon-default) | [In Progress](https://github.com/dotnet/roslyn/issues/25559) | [jcouv](https://github.com/jcouv) | [gafter](https://github.com/gafter) | | [jcouv](https://github.com/jcouv) |
| [Roles/Extensions](https://github.com/dotnet/csharplang/issues/5497) | [roles](https://github.com/dotnet/roslyn/tree/features/roles) | [In Progress](https://github.com/dotnet/roslyn/issues/66722) | [jcouv](https://github.com/jcouv) | [AlekseyTs](https://github.com/AlekseyTs), [jjonescz](https://github.com/jjonescz) | [CyrusNajmabadi](https://github.com/CyrusNajmabadi) | [MadsTorgersen](https://github.com/MadsTorgersen) |
| [Ref Struct Interfaces](https://github.com/dotnet/csharplang/issues/7608) | [RefStructInterfaces](https://github.com/dotnet/roslyn/tree/features/RefStructInterfaces) | [Merged into 17.11p2](https://github.com/dotnet/roslyn/issues/72124) | [AlekseyTs](https://github.com/AlekseyTs) | [cston](https://github.com/cston), [jjonescz](https://github.com/jjonescz) | [ToddGrun](https://github.com/ToddGrun) | [agocke](https://github.com/agocke), [jaredpar](https://github.com/jaredpar) |

# C# 13.0

| Feature | Branch | State | Developer | Reviewer | IDE Buddy | LDM Champ |
| ------- | ------ | ----- | --------- | -------- | --------- | --------- |
| [Escape character](https://github.com/dotnet/csharplang/issues/7400) | N/A | [Merged into 17.9p1](https://github.com/dotnet/roslyn/pull/70497) | [CyrusNajmabadi](https://github.com/CyrusNajmabadi) | [jcouv](https://github.com/jcouv), [RikkiGibson](https://github.com/RikkiGibson) | (no IDE impact) | [CyrusNajmabadi](https://github.com/CyrusNajmabadi) |
| [Method group natural type improvements](https://github.com/dotnet/csharplang/blob/main/proposals/method-group-natural-type-improvements.md) | main | [Merged into 17.9p2](https://github.com/dotnet/roslyn/issues/69432) | [jcouv](https://github.com/jcouv) | [AlekseyTs](https://github.com/AlekseyTs), [cston](https://github.com/cston) | (no IDE impact) | [jcouv](https://github.com/jcouv) |
| [`Lock` object](https://github.com/dotnet/csharplang/issues/7104) | [LockObject](https://github.com/dotnet/roslyn/tree/features/LockObject) | [Merged into 17.10p2](https://github.com/dotnet/roslyn/issues/71888) | [jjonescz](https://github.com/jjonescz) | [cston](https://github.com/cston), [RikkiGibson](https://github.com/RikkiGibson) | [CyrusNajmabadi](https://github.com/CyrusNajmabadi) (needs IDE fixer) | [stephentoub](https://github.com/stephentoub) |
| Implicit indexer access in object initializers | main | [Merged into 17.9p3](https://github.com/dotnet/roslyn/pull/70649) | [jcouv](https://github.com/jcouv) | [AlekseyTs](https://github.com/AlekseyTs), [cston](https://github.com/cston) | (no IDE impact) | |
| [Params-collections](https://github.com/dotnet/csharplang/issues/7700) | main | [Merged to 17.10p3](https://github.com/dotnet/roslyn/issues/71137) | [AlekseyTs](https://github.com/AlekseyTs) | [RikkiGibson](https://github.com/RikkiGibson), [333fred](https://github.com/333fred) | [akhera99](https://github.com/akhera99) (needs IDE fixer) | [MadsTorgersen](https://github.com/MadsTorgersen), [AlekseyTs](https://github.com/AlekseyTs) |
| [Ref/unsafe in iterators/async](https://github.com/dotnet/csharplang/blob/main/proposals/ref-unsafe-in-iterators-async.md) | [RefInAsync](https://github.com/dotnet/roslyn/tree/features/RefInAsync) | [Merged into 17.11p2](https://github.com/dotnet/roslyn/issues/72662) | [jjonescz](https://github.com/jjonescz) | [AlekseyTs](https://github.com/AlekseyTs), [cston](https://github.com/cston) | (no IDE impact) | |
| [Ref Struct Interfaces](https://github.com/dotnet/csharplang/issues/7608) | [RefStructInterfaces](https://github.com/dotnet/roslyn/tree/features/RefStructInterfaces) | [Merged into 17.11p2](https://github.com/dotnet/roslyn/issues/72124) | [AlekseyTs](https://github.com/AlekseyTs) | [cston](https://github.com/cston), [jjonescz](https://github.com/jjonescz) | [ToddGrun](https://github.com/ToddGrun) | [agocke](https://github.com/agocke), [jaredpar](https://github.com/jaredpar) |
| [Overload Resolution Priority](https://github.com/dotnet/csharplang/issues/7706) | PR not yet available | [In Progress](https://github.com/dotnet/roslyn/issues/74131) | [333fred](https://github.com/333fred) | [jcouv](https://github.com/jcouv), [cston](https://github.com/cston) | Not yet assigned | [333fred](https://github.com/333fred) |
| [`allows ref struct` constraint](https://github.com/dotnet/csharplang/issues/7608) | [RefStructInterfaces](https://github.com/dotnet/roslyn/tree/features/RefStructInterfaces) | [Merged into 17.11p2](https://github.com/dotnet/roslyn/issues/72124) | [AlekseyTs](https://github.com/AlekseyTs) | [cston](https://github.com/cston), [jjonescz](https://github.com/jjonescz) | [ToddGrun](https://github.com/ToddGrun) | [agocke](https://github.com/agocke), [jaredpar](https://github.com/jaredpar) |
| [Overload Resolution Priority](https://github.com/dotnet/csharplang/issues/7706) | main | [Merged to 17.12p1](https://github.com/dotnet/roslyn/issues/74131) | [333fred](https://github.com/333fred) | [jcouv](https://github.com/jcouv), [cston](https://github.com/cston) | Not yet assigned | [333fred](https://github.com/333fred) |
| [Partial properties](https://github.com/dotnet/csharplang/issues/6420) | [partial-properties](https://github.com/dotnet/roslyn/tree/features/partial-properties) | [Merged into 17.11p3](https://github.com/dotnet/roslyn/issues/73090) | [RikkiGibson](https://github.com/RikkiGibson) | [jcouv](https://github.com/jcouv), [333fred](https://github.com/333fred) | [Cosifne](https://github.com/Cosifne) | [333fred](https://github.com/333fred), [RikkiGibson](https://github.com/RikkiGibson) |

# C# 12.0
Expand Down
1 change: 1 addition & 0 deletions docs/contributing/Compiler Test Plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ This document provides guidance for thinking about language interactions and tes
- Conversions (boxing/unboxing)
- Nullable (wrapping, unwrapping)
- Overload resolution, override/hide/implement (OHI)
- OverloadResolutionPriorityAttribute
- Inheritance (virtual, override, abstract, new)
- Anonymous types
- Tuple types and literals (elements with explicit or inferred names, long tuples), tuple equality
Expand Down
187 changes: 185 additions & 2 deletions docs/features/incremental-generators.cookbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ For example, to turn your generator project into a NuGet package at build, add t

Any *runtime* dependencies, that is, code that the end users program will need to rely on, can simply be added as a dependency of the generator NuGet package via the usual referencing mechanism.

For example, consider a generator that creates code that relies on `Newtonsoft.Json`. The generator does not directly use the dependency, it just emits code that relies on the library being referenced in the users compilation. The author would add a reference to `Newtonsoft.Json` as a public dependency, and when the user adds the generator package it will referenced automatically.
For example, consider a generator that creates code that relies on `Newtonsoft.Json`. The generator does not directly use the dependency, it just emits code that relies on the library being referenced in the users compilation. The author would add a reference to `Newtonsoft.Json` as a public dependency, and when the user adds the generator package it will be referenced automatically.

```xml
<Project>
Expand Down Expand Up @@ -636,7 +636,190 @@ TODO: https://github.com/dotnet/roslyn/issues/72149
### Auto interface implementation

TODO: https://github.com/dotnet/roslyn/issues/72149
**User scenario:** As a generator author I want to be able to implement the properties of interfaces passed as arguments to a decorator of a class automatically for a user

**Solution:** Require the user to decorate the class with the `[AutoImplement]` Attribute and pass as arguments the types of the interfaces they want to self-implement themselves; The classes that implement the attribute have to be `partial class`.
Provide that attribute in a `RegisterPostInitializationOutput` step. Register for callbacks on the classes with
`ForAttributeWithMetadataName` using the fullyQualifiedMetadataName `FullyQualifiedAttributeName`, and use tuples (or create an equatable model) to pass along that information.
The attribute could work for structs too, the example was kept simple on purpose for the workbook sample.

**Example:**

```csharp
public interface IUserInterface
{
int InterfaceProperty { get; set; }
}

public interface IUserInterface2
{
float InterfacePropertyOnlyGetter { get; }
}

[AutoImplementProperties(typeof(IUserInterface), typeof(IUserInterface2))]
public partial class UserClass
{
public string UserProp { get; set; }
}
```

```csharp
#nullable enable
[Generator]
public class AutoImplementGenerator : IIncrementalGenerator
{
private const string AttributeNameSpace = "AttributeGenerator";
private const string AttributeName = "AutoImplementProperties";
private const string AttributeClassName = $"{AttributeName}Attribute";
private const string FullyQualifiedAttributeName = $"{AttributeNameSpace}.{AttributeClassName}";

public void Initialize(IncrementalGeneratorInitializationContext context)
{
context.RegisterPostInitializationOutput(ctx =>
{
//Generate the AutoImplementProperties Attribute
const string autoImplementAttributeDeclarationCode = $$"""
// <auto-generated/>
using System;
namespace {{AttributeNameSpace}};
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
sealed class {{AttributeClassName}} : Attribute
{
public Type[] InterfacesTypes { get; }
public {{AttributeClassName}}(params Type[] interfacesTypes)
{
InterfacesTypes = interfacesTypes;
}
}
""";
ctx.AddSource($"{AttributeClassName}.g.cs", autoImplementAttributeDeclarationCode);
});

IncrementalValuesProvider<ClassModel> provider = context.SyntaxProvider.ForAttributeWithMetadataName(
fullyQualifiedMetadataName: FullyQualifiedAttributeName,
predicate: static (node, cancellationToken_) => node is ClassDeclarationSyntax,
transform: static (ctx, cancellationToken) =>
{
ISymbol classSymbol = ctx.TargetSymbol;

return new ClassModel(
classSymbol.Name,
classSymbol.ContainingNamespace.ToDisplayString(),
GetInterfaceModels(ctx.Attributes[0])
);
});

context.RegisterSourceOutput(provider, static (context, classModel) =>
{
foreach (InterfaceModel interfaceModel in classModel.Interfaces)
{
StringBuilder sourceBuilder = new($$"""
// <auto-generated/>
namespace {{classModel.NameSpace}};
public partial class {{classModel.Name}} : {{interfaceModel.FullyQualifiedName}}
{
""");

foreach (string property in interfaceModel.Properties)
{
sourceBuilder.AppendLine(property);
}

sourceBuilder.AppendLine("""
}
""");

//Concat class name and interface name to have unique file name if a class implements two interfaces with AutoImplement Attribute
string generatedFileName = $"{classModel.Name}_{interfaceModel.FullyQualifiedName}.g.cs";
context.AddSource(generatedFileName, sourceBuilder.ToString());
}
});
}

private static EquatableList<InterfaceModel> GetInterfaceModels(AttributeData attribute)
{
EquatableList<InterfaceModel> ret = [];

if (attribute.ConstructorArguments.Length == 0)
return ret;

foreach(TypedConstant constructorArgumentValue in attribute.ConstructorArguments[0].Values)
{
if (constructorArgumentValue.Value is INamedTypeSymbol { TypeKind: TypeKind.Interface } interfaceSymbol)
{
EquatableList<string> properties = new();

foreach (IPropertySymbol interfaceProperty in interfaceSymbol
.GetMembers()
.OfType<IPropertySymbol>())
{
string type = interfaceProperty.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);

//Check if property has a setter
string setter = interfaceProperty.SetMethod is not null
? "set; "
: string.Empty;

properties.Add($$"""
public {{type}} {{interfaceProperty.Name}} { get; {{setter}}}
""");
}

ret.Add(new InterfaceModel(interfaceSymbol.ToDisplayString(), properties));
}
}

return ret;
}

private record ClassModel(string Name, string NameSpace, EquatableList<InterfaceModel> Interfaces);
private record InterfaceModel(string FullyQualifiedName, EquatableList<string> Properties);

private class EquatableList<T> : List<T>, IEquatable<EquatableList<T>>
{
public bool Equals(EquatableList<T>? other)
{
// If the other list is null or a different size, they're not equal
if (other is null || Count != other.Count)
{
return false;
}

// Compare each pair of elements for equality
for (int i = 0; i < Count; i++)
{
if (!EqualityComparer<T>.Default.Equals(this[i], other[i]))
{
return false;
}
}

// If we got this far, the lists are equal
return true;
}
public override bool Equals(object obj)
{
return Equals(obj as EquatableList<T>);
}
public override int GetHashCode()
{
return this.Select(item => item?.GetHashCode() ?? 0).Aggregate((x, y) => x ^ y);
}
public static bool operator ==(EquatableList<T> list1, EquatableList<T> list2)
{
return ReferenceEquals(list1, list2)
|| list1 is not null && list2 is not null && list1.Equals(list2);
}
public static bool operator !=(EquatableList<T> list1, EquatableList<T> list2)
{
return !(list1 == list2);
}
}
}
```

## Breaking Changes:

Expand Down
4 changes: 2 additions & 2 deletions docs/wiki/Roslyn-Overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Each phase of this pipeline is now a separate component. First the parse phase,

![compiler pipeline api](images/compiler-pipeline-api.png)

Corresponding to each of those phases, an object model is surfaced that allows access to the information at that phase. The parsing phase is exposed as a syntax tree, the declaration phase as a hierarchical symbol table, the binding phase as a model that exposes the result of the compiler’s semantic analysis and the emit phase as an API that produces IL byte codes.
Corresponding to each of those phases, an object model that allows access to the information at that phase is surfaced. The parsing phase is exposed as a syntax tree, the declaration phase as a hierarchical symbol table, the binding phase as a model that exposes the result of the compiler’s semantic analysis and the emit phase as an API that produces IL byte codes.

![compiler api lang service](images/compiler-pipeline-lang-svc.png)

Expand All @@ -69,7 +69,7 @@ The compiler layer contains the object models that correspond with information e

#### Diagnostic APIs

As part of their analysis the compiler may produce a set of diagnostics covering everything from syntax, semantic, and definite assignment errors to various warnings and informational diagnostics. The Compiler API layer exposes diagnostics through an extensible API allowing for user-defined analyzers to be plugged into a Compilation and user-defined diagnostics, such as those produced by tools like StyleCop or FxCop, to be produced alongside compiler-defined diagnostics. Producing diagnostics in this way has the benefit of integrating naturally with tools such as MSBuild and Visual Studio which depend on diagnostics for experiences such as halting a build based on policy and showing live squiggles in the editor and suggesting code fixes.
As part of their analysis the compiler may produce a set of diagnostics covering everything from syntax, semantic, and definite assignment errors to various warnings and informational diagnostics. The Compiler API layer exposes diagnostics through an extensible API allowing for user-defined analyzers to be plugged into a Compilation and user-defined diagnostics, such as those produced by tools like StyleCop or FxCop, to be produced alongside compiler-defined diagnostics. Producing diagnostics in this way has the benefit of integrating naturally with tools such as MSBuild and Visual Studio which depend on diagnostics for experiences such as halting a build based on policy, showing live squiggles in the editor and suggesting code fixes.

#### Scripting APIs

Expand Down
2 changes: 1 addition & 1 deletion eng/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<!-- Versions used by several individual references below -->
<RoslynDiagnosticsNugetPackageVersion>3.11.0-beta1.24081.1</RoslynDiagnosticsNugetPackageVersion>
<MicrosoftCodeAnalysisNetAnalyzersVersion>8.0.0-preview.23468.1</MicrosoftCodeAnalysisNetAnalyzersVersion>
<MicrosoftCodeAnalysisTestingVersion>1.1.2-beta1.24121.1</MicrosoftCodeAnalysisTestingVersion>
<MicrosoftCodeAnalysisTestingVersion>1.1.3-beta1.24319.1</MicrosoftCodeAnalysisTestingVersion>
<MicrosoftVisualStudioExtensibilityTestingVersion>0.1.187-beta</MicrosoftVisualStudioExtensibilityTestingVersion>
<_BasicReferenceAssembliesVersion>1.7.2</_BasicReferenceAssembliesVersion>
<!-- CodeStyleAnalyzerVersion should we updated together with version of dotnet-format in dotnet-tools.json -->
Expand Down
Loading

0 comments on commit cd9cb9d

Please sign in to comment.