diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/InitOnlyMemberTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/InitOnlyMemberTests.cs index bbe8db601f0b8..a0826d1bebcc9 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/InitOnlyMemberTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/InitOnlyMemberTests.cs @@ -19,11 +19,6 @@ public class InitOnlyMemberTests : CompilingTestBase // Spec: https://github.com/dotnet/csharplang/blob/master/proposals/init.md // PROTOTYPE(init-only): test allowed from 'with' expression - // PROTOTYPE(init-only): public API, confirm behavior of IsInitOnly and test on each leaf type of wrapped symbol - - // PROTOTYPE(init-only): open issues: - // PROTOTYPE(init-only): queue discussion on init methods (`init void Init()`) and collection initializers (`init void Add()`) - // PROTOTYPE(init-only): test dynamic scenario // PROTOTYPE(init-only): test whether reflection use property despite modreq? // PROTOTYPE(init-only): test behavior of old compiler with modreq. For example VB @@ -603,6 +598,74 @@ public string RegularProperty2 Assert.True(property.GetPublicSymbol().SetMethod.IsInitOnly); } + [Fact(Skip = "PROTOTYPE(init-only) Not yet supported")] + public void InitOnlyPropertyAssignmentAllowedInWithInitializer() + { + string source = @" +public class C +{ + public int Property { get; init; } + + void M(C c) + { + _ = c with { Property = null }; + } + + public C Clone() => throw null; +} + +class Derived : C +{ +} + +class Derived2 : Derived +{ + void M(C c) + { + _ = c with { Property = null }; + _ = this with { Property = null }; + } +} + +class Other +{ + void M() + { + var c = new C() with { Property = 42 }; + System.Console.Write($""{c.Property}""); + } +} +"; + var comp = CreateCompilation(new[] { source, IsExternalInitTypeDefinition }, parseOptions: TestOptions.RegularPreview); + comp.VerifyDiagnostics(); + } + + [Fact(Skip = "PROTOTYPE(init-only) Not yet supported")] + public void InitOnlyPropertyAssignmentAllowedInWithInitializer_Evaluation() + { + string source = @" +public class C +{ + private int field; + public int Property { get { return field; } init { field = value; System.Console.Write(""set ""); } } + + public C Clone() { System.Console.Write(""clone ""); return this; } +} + +class Other +{ + public static void Main() + { + var c = new C() with { Property = 42 }; + System.Console.Write($""{c.Property}""); + } +} +"; + var comp = CreateCompilation(new[] { source, IsExternalInitTypeDefinition }, parseOptions: TestOptions.RegularPreview, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "clone set 42"); + } + [Fact] public void EvaluationInitOnlySetter() { @@ -2025,7 +2088,7 @@ public event System.Action Event } [Fact] - public void ConstructorsAreNotInitOnly() + public void ConstructorAndDestructorAreNotInitOnly() { string source = @" public class C @@ -2046,6 +2109,31 @@ public C() { } Assert.False(destructor.GetPublicSymbol().IsInitOnly); } + [Fact] + public void ConstructedMethodsAreNotInitOnly() + { + string source = @" +public class C +{ + void M() + { + M(); + } +} +"; + var comp = CreateCompilation(new[] { source, IsExternalInitTypeDefinition }, parseOptions: TestOptions.RegularPreview); + comp.VerifyDiagnostics(); + + var tree = comp.SyntaxTrees[0]; + var root = tree.GetCompilationUnitRoot(); + var model = comp.GetSemanticModel(tree, ignoreAccessibility: true); + + var invocation = root.DescendantNodes().OfType().Single(); + var method = (IMethodSymbol)model.GetSymbolInfo(invocation).Symbol; + Assert.Equal("void C.M()", method.ToTestDisplayString()); + Assert.False(method.IsInitOnly); + } + [Fact] public void InitOnlyOnMembersOfRecords() { diff --git a/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs b/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs index f624ba96b474c..d20c5f7ffc73b 100644 --- a/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs +++ b/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs @@ -8437,7 +8437,7 @@ interface I class C : [|I|] { - public int Property { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); } + public int Property { get => throw new System.NotImplementedException(); init => throw new System.NotImplementedException(); } }"); } diff --git a/src/VisualStudio/CSharp/Impl/EventHookup/EventHookupCommandHandler_TabKeyCommand.cs b/src/VisualStudio/CSharp/Impl/EventHookup/EventHookupCommandHandler_TabKeyCommand.cs index effd54bfad77b..13ead66e7d15c 100644 --- a/src/VisualStudio/CSharp/Impl/EventHookup/EventHookupCommandHandler_TabKeyCommand.cs +++ b/src/VisualStudio/CSharp/Impl/EventHookup/EventHookupCommandHandler_TabKeyCommand.cs @@ -265,6 +265,7 @@ private IMethodSymbol GetMethodSymbol( modifiers: new DeclarationModifiers(isStatic: eventHookupExpression.IsInStaticContext()), returnType: delegateInvokeMethod.ReturnType, refKind: delegateInvokeMethod.RefKind, + isInitOnly: false, explicitInterfaceImplementations: default, name: eventHandlerMethodName, typeParameters: default, diff --git a/src/VisualStudio/Core/Def/Implementation/Venus/ContainedLanguageCodeSupport.cs b/src/VisualStudio/Core/Def/Implementation/Venus/ContainedLanguageCodeSupport.cs index 0e775f3145a9c..094a5479462a4 100644 --- a/src/VisualStudio/Core/Def/Implementation/Venus/ContainedLanguageCodeSupport.cs +++ b/src/VisualStudio/Core/Def/Implementation/Venus/ContainedLanguageCodeSupport.cs @@ -189,6 +189,7 @@ public static Tuple EnsureEventHandler( modifiers: new DeclarationModifiers(), returnType: targetDocument.Project.GetCompilationAsync(cancellationToken).WaitAndGetResult_Venus(cancellationToken).GetSpecialType(SpecialType.System_Void), refKind: RefKind.None, + isInitOnly: false, explicitInterfaceImplementations: default, name: eventHandlerName, typeParameters: default, diff --git a/src/VisualStudio/Core/Impl/CodeModel/AbstractCodeModelObject_CodeGen.cs b/src/VisualStudio/Core/Impl/CodeModel/AbstractCodeModelObject_CodeGen.cs index 85c11c2420c11..7a57c6f9568f8 100644 --- a/src/VisualStudio/Core/Impl/CodeModel/AbstractCodeModelObject_CodeGen.cs +++ b/src/VisualStudio/Core/Impl/CodeModel/AbstractCodeModelObject_CodeGen.cs @@ -85,6 +85,7 @@ protected SyntaxNode CreateEventDeclaration(SyntaxNode containerNode, string nam modifiers: new DeclarationModifiers(), returnType: null, refKind: RefKind.None, + isInitOnly: false, explicitInterfaceImplementations: default, name: "add_" + name, typeParameters: default, @@ -96,6 +97,7 @@ protected SyntaxNode CreateEventDeclaration(SyntaxNode containerNode, string nam modifiers: new DeclarationModifiers(), returnType: null, refKind: RefKind.None, + isInitOnly: false, explicitInterfaceImplementations: default, name: "remove_" + name, typeParameters: default, @@ -143,6 +145,7 @@ protected SyntaxNode CreateMethodDeclaration(SyntaxNode containerNode, string na modifiers: new DeclarationModifiers(), returnType: returnType, refKind: RefKind.None, + isInitOnly: false, explicitInterfaceImplementations: default, name: name, typeParameters: default, @@ -174,6 +177,7 @@ protected SyntaxNode CreatePropertyDeclaration(SyntaxNode containerNode, string modifiers: new DeclarationModifiers(), returnType: null, refKind: RefKind.None, + isInitOnly: false, explicitInterfaceImplementations: default, name: "get_" + name, typeParameters: default, @@ -190,6 +194,7 @@ protected SyntaxNode CreatePropertyDeclaration(SyntaxNode containerNode, string modifiers: new DeclarationModifiers(), returnType: null, refKind: RefKind.None, + isInitOnly: false, explicitInterfaceImplementations: default, name: "set_" + name, typeParameters: default, diff --git a/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationSymbolFactory.cs b/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationSymbolFactory.cs index 307aac7fade47..6cfd347e13459 100644 --- a/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationSymbolFactory.cs +++ b/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationSymbolFactory.cs @@ -338,7 +338,8 @@ internal static IMethodSymbol CreateAccessorSymbol( accessor.TypeParameters, accessor.Parameters, statements, - returnTypeAttributes: accessor.GetReturnTypeAttributes()); + returnTypeAttributes: accessor.GetReturnTypeAttributes(), + methodKind: accessor.MethodKind); } /// @@ -478,7 +479,8 @@ internal static IMethodSymbol CreateMethodSymbol( method.TypeParameters, parameters ?? method.Parameters, statements, - returnTypeAttributes: returnTypeAttributes.HasValue ? returnTypeAttributes.Value : method.GetReturnTypeAttributes()); + returnTypeAttributes: returnTypeAttributes.HasValue ? returnTypeAttributes.Value : method.GetReturnTypeAttributes(), + methodKind: method.MethodKind); } internal static IPropertySymbol CreatePropertySymbol(