diff --git a/src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs b/src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs index 741cb2f524f5d..16d3ce94a3b63 100644 --- a/src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs +++ b/src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs @@ -1166,22 +1166,18 @@ newContainingMemberOrType is IPropertySymbol newPropertySymbol && case EditKind.Reorder: Contract.ThrowIfNull(oldNode); + // When global statements are reordered, we issue an update edit for the synthesized main method, which is what + // oldSymbol and newSymbol will point to. if (IsGlobalStatement(oldNode)) { - // When global statements are reordered, we issue an update edit for the synthesized main method, which is what - // oldSymbol and newSymbol will point to result.Add((oldSymbol, newSymbol, EditKind.Update)); return; } - // Otherwise, we don't do any semantic checks for reordering - // and we don't need to report them to the compiler either. - // Consider: Currently symbol ordering changes are not reflected in metadata (Reflection will report original order). + // Reordering of data members is only allowed if the layout of the type doesn't change. + // Reordering of other members is a no-op, although the new order won't be reflected in metadata (Reflection will report original order). + result.Add((oldSymbol, newSymbol, EditKind.Reorder)); - // Consider: Reordering of fields is not allowed since it changes the layout of the type. - // This ordering should however not matter unless the type has explicit layout so we might want to allow it. - // We do not check changes to the order if they occur across multiple documents (the containing type is partial). - Debug.Assert(!IsDeclarationWithInitializer(oldNode!) && !IsDeclarationWithInitializer(newNode!)); return; case EditKind.Update: @@ -2391,14 +2387,6 @@ private void ClassifyReorder(SyntaxNode newNode) switch (newNode.Kind()) { - case SyntaxKind.PropertyDeclaration: - case SyntaxKind.FieldDeclaration: - case SyntaxKind.EventFieldDeclaration: - case SyntaxKind.VariableDeclarator: - // Maybe we could allow changing order of field declarations unless the containing type layout is sequential. - ReportError(RudeEditKind.Move); - return; - case SyntaxKind.EnumMemberDeclaration: // To allow this change we would need to check that values of all fields of the enum // are preserved, or make sure we can update all method bodies that accessed those that changed. diff --git a/src/Features/CSharpTest/EditAndContinue/ActiveStatementTests.cs b/src/Features/CSharpTest/EditAndContinue/ActiveStatementTests.cs index 39649800085d0..ca9091ad4a272 100644 --- a/src/Features/CSharpTest/EditAndContinue/ActiveStatementTests.cs +++ b/src/Features/CSharpTest/EditAndContinue/ActiveStatementTests.cs @@ -3126,7 +3126,6 @@ public C() {} var active = GetActiveStatements(src1, src2); edits.VerifySemanticDiagnostics(active, - Diagnostic(RudeEditKind.Move, "int c", GetResource("field")), Diagnostic(RudeEditKind.DeleteActiveStatement, "class C", GetResource("field", "C.a")), Diagnostic(RudeEditKind.Delete, "class C", GetResource("field", "a"))); } diff --git a/src/Features/CSharpTest/EditAndContinue/LineEditTests.cs b/src/Features/CSharpTest/EditAndContinue/LineEditTests.cs index e844f7b8631ad..2cb7654e06f2c 100644 --- a/src/Features/CSharpTest/EditAndContinue/LineEditTests.cs +++ b/src/Features/CSharpTest/EditAndContinue/LineEditTests.cs @@ -69,12 +69,12 @@ public void Method_Reorder1() var src1 = @" class C { - static void Goo() + static void G() { Console.ReadLine(1); } - static void Bar() + static void F() { Console.ReadLine(2); } @@ -83,76 +83,83 @@ static void Bar() var src2 = @" class C { - static void Bar() + static void F() { Console.ReadLine(2); } - static void Goo() + static void G() { Console.ReadLine(1); } }"; var edits = GetTopEdits(src1, src2); + + // Consider: we could detect that the body of the method hasn't changed and avoid creating an update. edits.VerifyLineEdits( new[] { new SourceLineUpdate(4, 9), new SourceLineUpdate(7, 7), new SourceLineUpdate(9, 4) - }); + }, + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"))]); } [Fact] public void Method_Reorder2() { var src1 = @" -class Program +class C { static void Main() { - Goo(); - Bar(); + F(); + G(); } - static int Goo() + static int G() { return 1; } - static int Bar() + static int F() { return 2; } }"; var src2 = @" -class Program +class C { - static int Goo() + static int F() { return 1; } static void Main() { - Goo(); - Bar(); + F(); + G(); } - static int Bar() + static int G() { return 2; } }"; var edits = GetTopEdits(src1, src2); + + // Consider: we could detect that the body of the method hasn't changed and create line edits instead of an update. edits.VerifyLineEdits( new[] { new SourceLineUpdate(4, 9), - new SourceLineUpdate(8, 8), - new SourceLineUpdate(10, 4), - new SourceLineUpdate(13, 13), - }); + }, + semanticEdits: + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")), + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.G")) + ]); } [Fact] @@ -758,13 +765,19 @@ public C(int a) } }"; var edits = GetTopEdits(src1, src2); + + // Consider: we could detect that the body of the method hasn't changed and avoid creating an update. edits.VerifyLineEdits( new[] { new SourceLineUpdate(3, 7), new SourceLineUpdate(6, 6), new SourceLineUpdate(7, 3) - }); + }, + semanticEdits: + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(c => c.Parameters is [{ Type.SpecialType: SpecialType.System_Boolean }]), preserveLocalVariables: true) + ]); } [Fact] @@ -1357,13 +1370,13 @@ class C var src2 = @" class C { - static int Bar = 2; - static int Goo = 1; + static int Bar = 1; + static int Goo = 2; }"; var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - diagnostics: [Diagnostic(RudeEditKind.Move, "static int Bar = 2", FeaturesResources.field)]); + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), preserveLocalVariables: true)]); } [Fact] diff --git a/src/Features/CSharpTest/EditAndContinue/TopLevelEditingTests.cs b/src/Features/CSharpTest/EditAndContinue/TopLevelEditingTests.cs index b09c53ff6a0df..960cd5c325a9d 100644 --- a/src/Features/CSharpTest/EditAndContinue/TopLevelEditingTests.cs +++ b/src/Features/CSharpTest/EditAndContinue/TopLevelEditingTests.cs @@ -10,6 +10,7 @@ using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.UnitTests; +using Microsoft.CodeAnalysis.Differencing; using Microsoft.CodeAnalysis.EditAndContinue; using Microsoft.CodeAnalysis.EditAndContinue.UnitTests; using Microsoft.CodeAnalysis.Emit; @@ -3018,7 +3019,7 @@ record struct C(int X) var edits = GetTopEdits(src1, src2); edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.InsertIntoStruct, "_y = 0", FeaturesResources.field, CSharpFeaturesResources.record_struct)); + Diagnostic(RudeEditKind.InsertOrMoveStructMember, "_y = 0", FeaturesResources.field, CSharpFeaturesResources.record_struct)); } [Fact] @@ -3037,7 +3038,7 @@ record struct C(int X) var edits = GetTopEdits(src1, src2); edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.InsertIntoStruct, "public int Y", GetResource("auto-property"), GetResource("record struct"))); + Diagnostic(RudeEditKind.InsertOrMoveStructMember, "public int Y", GetResource("auto-property"), GetResource("record struct"))); } [Fact] @@ -3376,6 +3377,27 @@ public void Record_Field_Insert_WithInitializer() capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } + [Fact] + public void Record_EventField_Insert_WithInitializer() + { + var src1 = "record C(int X) { }"; + var src2 = "record C(int X) { event System.Action E = null; }"; + var syntaxMap = GetSyntaxMap(src1, src2); + + var edits = GetTopEdits(src1, src2); + + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), + SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), + SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), + SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.E")), + SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true) + ], + capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType | EditAndContinueCapabilities.AddMethodToExistingType); + } + [Fact] public void Record_Field_Insert_WithExistingInitializer() { @@ -3856,7 +3878,7 @@ public void Record_Property_Delete_ReplacingCustomWithSynthesized_TypeLayoutChan var edits = GetTopEdits(src1, src2); edits.VerifySemanticDiagnostics( - [Diagnostic(RudeEditKind.InsertIntoStruct, "int P", GetResource("auto-property"), GetResource("record struct"))], + [Diagnostic(RudeEditKind.InsertOrMoveStructMember, "int P", GetResource("auto-property"), GetResource("record struct"))], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType | EditAndContinueCapabilities.AddMethodToExistingType); } @@ -8390,17 +8412,161 @@ class C } [Fact] - public void MethodReorder1() + public void Method_Reorder() + { + var src1 = """ + class C + { + + void F() {} + void G() {} + void H() {} + } + """; + + var src2 = """ + class C + { + void H() {} + void F() {} + void G() {} + + } + """; + + var edits = GetTopEdits(src1, src2); + + edits.VerifyEdits(EditKind.Reorder); + + edits.VerifySemantics([SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.H"))]); + } + + [Theory] + [CombinatorialData] + public void Method_Reorder_Interface(bool isStatic) + { + var (modifier, body) = isStatic ? ("static", ";") : ("", " {}"); + + var src1 = $$""" + interface I + { + {{modifier}} void F(){{body}} + {{modifier}} void G(){{body}} + {{modifier}} void H(){{body}} + } + """; + + var src2 = $$""" + interface I + { + {{modifier}} void H(){{body}} + {{modifier}} void F(){{body}} + {{modifier}} void G(){{body}} + } + """; + + var edits = GetTopEdits(src1, src2); + + edits.VerifyEdits(EditKind.Reorder); + + edits.VerifySemantics([SemanticEdit(SemanticEditKind.Update, c => c.GetMember("I.H"))]); + } + + [Theory] + [InlineData("static extern ")] // static method must be extern in COM interface + [InlineData("")] + public void Method_Reorder_Interface_ComImport(string modifier) + { + var src1 = $$""" + using System.Runtime.InteropServices; + [ComImport] + [Guid("DBE8A85B-7883-4657-83FD-1FA27A9561EB")] + interface I + { + {{modifier}}void F(); + {{modifier}}void G(); + {{modifier}}void H(); + } + """; + + var src2 = $$""" + using System.Runtime.InteropServices; + [ComImport] + [Guid("DBE8A85B-7883-4657-83FD-1FA27A9561EB")] + interface I + { + {{modifier}}void H(); + {{modifier}}void F(); + {{modifier}}void G(); + } + """; + + var edits = GetTopEdits(src1, src2); + + edits.VerifyEdits(EditKind.Reorder); + + edits.VerifySemanticDiagnostics( + Diagnostic(RudeEditKind.InsertOrMoveComInterfaceMember, modifier + "void H()", GetResource("method"))); + } + + [Fact] + public void Method_Insert_Interface_ComImport() { - var src1 = "class C { void f(int a, int b) { a = b; } void g() { } }"; - var src2 = "class C { void g() { } void f(int a, int b) { a = b; } }"; + var src1 = $$""" + using System.Runtime.InteropServices; + [ComImport] + [Guid("DBE8A85B-7883-4657-83FD-1FA27A9561EB")] + interface I + { + } + """; + + var src2 = $$""" + using System.Runtime.InteropServices; + [ComImport] + [Guid("DBE8A85B-7883-4657-83FD-1FA27A9561EB")] + interface I + { + void F(); + } + """; var edits = GetTopEdits(src1, src2); - edits.VerifyEdits("Reorder [void g() { }]@42 -> @10"); + + edits.VerifySemanticDiagnostics( + Diagnostic(RudeEditKind.InsertVirtual, "void F()", GetResource("method")), + Diagnostic(RudeEditKind.InsertOrMoveComInterfaceMember, "void F()", GetResource("method"))); } [Fact] - public void MethodInsertDelete1() + public void Method_Insert_Interface_ComImport_Static() + { + var src1 = $$""" + [System.Runtime.InteropServices.ComImport] + [Guid("DBE8A85B-7883-4657-83FD-1FA27A9561EB")] + interface I + { + } + """; + + var src2 = $$""" + [System.Runtime.InteropServices.ComImport] + [Guid("DBE8A85B-7883-4657-83FD-1FA27A9561EB")] + interface I + { + extern static void F(); + } + """; + + var edits = GetTopEdits(src1, src2); + + edits.VerifySemanticDiagnostics( + Diagnostic(RudeEditKind.InsertExtern, "extern static void F()", GetResource("method")), + Diagnostic(RudeEditKind.InsertOrMoveComInterfaceMember, "extern static void F()", GetResource("method"))); + } + + [Fact] + public void Method_InsertDelete() { var src1 = "class C { class D { } void f(int a, int b) { a = b; } }"; var src2 = "class C { class D { void f(int a, int b) { a = b; } } }"; @@ -10936,7 +11102,7 @@ public void Constructor_Parameter_Update_Type_Record_TypeLayout() var edits = GetTopEdits(src1, src2); edits.VerifySemanticDiagnostics( - [Diagnostic(RudeEditKind.InsertIntoStruct, "int x", GetResource("auto-property"), GetResource("record struct"))], + [Diagnostic(RudeEditKind.InsertOrMoveStructMember, "int x", GetResource("auto-property"), GetResource("record struct"))], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11431,7 +11597,7 @@ public void Constructor_Parameter_Insert_Primary_Captured_Struct() edits.VerifySemanticDiagnostics( [ Diagnostic(RudeEditKind.CapturingPrimaryConstructorParameter, "b", GetResource("struct"), "b"), - Diagnostic(RudeEditKind.InsertIntoStruct, "int b", GetResource("parameter"), GetResource("struct")) + Diagnostic(RudeEditKind.InsertOrMoveStructMember, "int b", GetResource("parameter"), GetResource("struct")) ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11481,7 +11647,7 @@ record C(int X, int Y) { } var edits = GetTopEdits(src1, src2); edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "int Y", GetResource("auto-property"), GetResource("record"))); + Diagnostic(RudeEditKind.InsertOrMoveTypeWithLayoutMember, "int Y", GetResource("auto-property"), GetResource("record"))); } [Fact] @@ -11500,7 +11666,7 @@ record struct C(int x, int y) var edits = GetTopEdits(src1, src2); edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.InsertIntoStruct, "int y", GetResource("auto-property"), GetResource("record struct"))); + Diagnostic(RudeEditKind.InsertOrMoveStructMember, "int y", GetResource("auto-property"), GetResource("record struct"))); } [Fact] @@ -11729,7 +11895,7 @@ class C(int x, int y) edits.VerifySemanticDiagnostics( [ Diagnostic(RudeEditKind.CapturingPrimaryConstructorParameter, "y", GetResource("class with explicit or sequential layout"), "y"), - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "int y", GetResource("parameter"), GetResource("class")) + Diagnostic(RudeEditKind.InsertOrMoveTypeWithLayoutMember, "int y", GetResource("parameter"), GetResource("class")) ]); } @@ -11761,7 +11927,7 @@ class C(int x, int y) edits.VerifySemanticDiagnostics( [ Diagnostic(RudeEditKind.CapturingPrimaryConstructorParameter, "y", GetResource("class with explicit or sequential layout"), "y"), - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "int y", GetResource("parameter"), GetResource("class")) + Diagnostic(RudeEditKind.InsertOrMoveTypeWithLayoutMember, "int y", GetResource("parameter"), GetResource("class")) ]); } @@ -11791,7 +11957,7 @@ public void Constructor_Parameter_Reorder_Primary_NotLifted_Record_Struct() var edits = GetTopEdits(src1, src2); edits.VerifySemanticDiagnostics( - [Diagnostic(RudeEditKind.InsertIntoStruct, "byte y", GetResource("auto-property"), GetResource("record struct"))], + [Diagnostic(RudeEditKind.InsertOrMoveStructMember, "byte y", GetResource("auto-property"), GetResource("record struct"))], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11803,7 +11969,7 @@ public void Constructor_Parameter_Reorder_Primary_Lifted_Struct() var edits = GetTopEdits(src1, src2); edits.VerifySemanticDiagnostics( - [Diagnostic(RudeEditKind.InsertIntoStruct, "byte y", GetResource("parameter"), GetResource("struct"))], + [Diagnostic(RudeEditKind.InsertOrMoveStructMember, "byte y", GetResource("parameter"), GetResource("struct"))], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11843,11 +12009,8 @@ public void Constructor_Parameter_Reorder_Primary_Lifted_Record() SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.x")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_x")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_x")), - // TODO: y should also be updated (to update sequence points to the new location) - // https://github.com/dotnet/roslyn/issues/69894 - // SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.y")), - // SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_y")), - // SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_y")), + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_y")), + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_y")), ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); @@ -12704,7 +12867,7 @@ public void Constructor_Instance_Insert_Struct_Primary_Record() edits.VerifySemanticDiagnostics( [ - Diagnostic(RudeEditKind.InsertIntoStruct, "int X", GetResource("auto-property"), GetResource("record struct")) + Diagnostic(RudeEditKind.InsertOrMoveStructMember, "int X", GetResource("auto-property"), GetResource("record struct")) ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -14445,7 +14608,7 @@ public void MemberInitializer_Update_Field() } [Fact] - public void MemberInitializer_Update_Field_Event() + public void MemberInitializer_Update_EventField() { var src1 = "class C { event System.Action a = F(0); static System.Action F(int a) => null; }"; var src2 = "class C { event System.Action a = F(1); static System.Action F(int a) => null; }"; @@ -16485,7 +16648,7 @@ public void Field_Const_Update() } [Fact] - public void Field_Event_VariableDeclarator_Update() + public void EventField_VariableDeclarator_Update() { var src1 = "class C { event Action a; }"; var src2 = "class C { event Action a = () => { }; }"; @@ -16504,16 +16667,211 @@ public void Field_Event_VariableDeclarator_Update() [Fact] public void Field_Reorder() { - var src1 = "class C { int a = 0; int b = 1; int c = 2; }"; - var src2 = "class C { int c = 2; int a = 0; int b = 1; }"; + var src1 = """ + class C + { + + int a = 0; + int b = 1; + int c; + } + """; + + var src2 = """ + class C + { + int c; + int a = 0; + int b = 1; + + } + """; var edits = GetTopEdits(src1, src2); - edits.VerifyEdits( - "Reorder [int c = 2;]@32 -> @10"); + edits.VerifyEdits(EditKind.Reorder); + + edits.VerifySemantics(); + } + + [Fact] + public void Field_Reorder_WithInitializer() + { + var src1 = """ + class C + { + + int a = 0; + int b = 1; + int c = 2; + } + """; + + var src2 = """ + class C + { + int c = 2; + int a = 0; + int b = 1; + + } + """; + + var edits = GetTopEdits(src1, src2); + + edits.VerifyEdits(EditKind.Reorder); + + edits.VerifySemantics([SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true)]); + } + + [Theory] + [CombinatorialData] + public void Field_Reorder_WithInitializer_RemoveOrAdd(bool remove) + { + var src1 = $$""" + class C + { + + int a = 0; + int b = 1; + int c{{(remove ? " = 2" : "")}}; + } + """; + + var src2 = $$""" + class C + { + int c{{(remove ? "" : " = 2")}}; + int a = 0; + int b = 1; + + } + """; + + var edits = GetTopEdits(src1, src2); + + edits.VerifyEdits(EditKind.Reorder, EditKind.Update); + + edits.VerifySemantics([SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true)]); + } + + [Fact] + public void Field_Reorder_Modifiers_Update() + { + var src1 = """ + class C + { + + int a = 0; + int b = 1; + static int c; + } + """; + + var src2 = """ + class C + { + int c; + int a = 0; + int b = 1; + + } + """; + + var edits = GetTopEdits(src1, src2); + + edits.VerifyEdits(EditKind.Reorder, EditKind.Update); edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.Move, "int c = 2", FeaturesResources.field)); + Diagnostic(RudeEditKind.ModifiersUpdate, "int c", GetResource("field"))); + } + + [Fact] + public void Field_Reorder_Attribute_Update() + { + var attributeDecl = """ + class A : System.Attribute {} + """; + + var src1 = attributeDecl + """ + class C + { + + int a = 0; + int b = 1; + int c; + } + """; + + var src2 = attributeDecl + """ + class C + { + [A]int c; + int a = 0; + int b = 1; + + } + """; + + var edits = GetTopEdits(src1, src2); + + edits.VerifyEdits(EditKind.Reorder, EditKind.Update); + + edits.VerifySemantics( + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.c"))], + capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); + } + + [Theory] + [InlineData("", "struct", RudeEditKind.InsertOrMoveStructMember)] + [InlineData("", "record struct", RudeEditKind.InsertOrMoveStructMember)] + [InlineData("[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]", "class", RudeEditKind.InsertOrMoveTypeWithLayoutMember)] + [InlineData("[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]", "record class", RudeEditKind.InsertOrMoveTypeWithLayoutMember)] + internal void Field_Reorder_TypeLayout(string attribute, string keyword, RudeEditKind rudeEditKind) + { + var src1 = attribute + keyword + " C { int a = 0; int b = 1; int c = 2; }"; + var src2 = attribute + keyword + " C { int c = 2; int a = 0; int b = 1; }"; + + var edits = GetTopEdits(src1, src2); + + edits.VerifyEdits(EditKind.Reorder); + + edits.VerifySemanticDiagnostics( + Diagnostic(rudeEditKind, "int c = 2", GetResource("field"), GetResource(keyword))); + } + + [Fact] + public void Field_Reorder_Reloadable() + { + var src1 = ReloadableAttributeSrc + """ + [CreateNewOnMetadataUpdate] + struct C + { + + int a = 0; + int b = 1; + int c; + } + """; + + var src2 = ReloadableAttributeSrc + """ + [CreateNewOnMetadataUpdate] + struct C + { + int c; + int a = 0; + int b = 1; + + } + """; + + var edits = GetTopEdits(src1, src2); + + edits.VerifyEdits(EditKind.Reorder); + + edits.VerifySemantics( + [SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"))], + capabilities: EditAndContinueCapabilities.NewTypeDefinition); } [Fact] @@ -16564,10 +16922,10 @@ struct S var edits = GetTopEdits(src1, src2); edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.InsertIntoStruct, "b", FeaturesResources.field, CSharpFeaturesResources.struct_), - Diagnostic(RudeEditKind.InsertIntoStruct, "c", FeaturesResources.field, CSharpFeaturesResources.struct_), - Diagnostic(RudeEditKind.InsertIntoStruct, "f = 1", FeaturesResources.field, CSharpFeaturesResources.struct_), - Diagnostic(RudeEditKind.InsertIntoStruct, "d", CSharpFeaturesResources.event_field, CSharpFeaturesResources.struct_)); + Diagnostic(RudeEditKind.InsertOrMoveStructMember, "b", GetResource("field"), GetResource("struct")), + Diagnostic(RudeEditKind.InsertOrMoveStructMember, "c", GetResource("field"), GetResource("struct")), + Diagnostic(RudeEditKind.InsertOrMoveStructMember, "f = 1", GetResource("field"), GetResource("struct")), + Diagnostic(RudeEditKind.InsertOrMoveStructMember, "d", GetResource("event field"), GetResource("struct"))); } [Fact] @@ -16640,9 +16998,9 @@ class C var edits = GetTopEdits(src1, src2); edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "b", FeaturesResources.field, FeaturesResources.class_), - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "c", FeaturesResources.field, FeaturesResources.class_), - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "d", FeaturesResources.field, FeaturesResources.class_)); + Diagnostic(RudeEditKind.InsertOrMoveTypeWithLayoutMember, "b", GetResource("field"), GetResource("class")), + Diagnostic(RudeEditKind.InsertOrMoveTypeWithLayoutMember, "c", GetResource("field"), GetResource("class")), + Diagnostic(RudeEditKind.InsertOrMoveTypeWithLayoutMember, "d", GetResource("field"), GetResource("class"))); } [Fact] @@ -16673,9 +17031,9 @@ class C var edits = GetTopEdits(src1, src2); edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "b", FeaturesResources.field, FeaturesResources.class_), - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "c", FeaturesResources.field, FeaturesResources.class_), - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "d", FeaturesResources.field, FeaturesResources.class_)); + Diagnostic(RudeEditKind.InsertOrMoveTypeWithLayoutMember, "b", GetResource("field"), GetResource("class")), + Diagnostic(RudeEditKind.InsertOrMoveTypeWithLayoutMember, "c", GetResource("field"), GetResource("class")), + Diagnostic(RudeEditKind.InsertOrMoveTypeWithLayoutMember, "d", GetResource("field"), GetResource("class"))); } [Fact] @@ -17127,7 +17485,6 @@ public void Field_Type_Update_ReorderRemoveAdd() "Delete [H]@20"); edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.Move, "G", FeaturesResources.field), Diagnostic(RudeEditKind.TypeUpdate, "string G, F", FeaturesResources.field), Diagnostic(RudeEditKind.TypeUpdate, "string G, F", FeaturesResources.field), Diagnostic(RudeEditKind.TypeUpdate, "double V, U", FeaturesResources.field), @@ -17675,53 +18032,153 @@ public void PropertyAccessorDelete2() } [Fact] - public void Property_Reorder1() + public void Property_Reorder_Auto() { - var src1 = "class C { int P { get { return 1; } } int Q { get { return 1; } } }"; - var src2 = "class C { int Q { get { return 1; } } int P { get { return 1; } } }"; + var src1 = """ + class C + { + + int P { get; } = 0; + int Q { get; } = 1; + int R { get; } + } + """; + + var src2 = """ + class C + { + int R { get; } + int P { get; } = 0; + int Q { get; } = 1; + + } + """; var edits = GetTopEdits(src1, src2); - edits.VerifyEdits( - "Reorder [int Q { get { return 1; } }]@38 -> @10"); + edits.VerifyEdits(EditKind.Reorder); - // TODO: we can allow the move since the property doesn't have a backing field - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.Move, "int Q", FeaturesResources.property_)); + edits.VerifySemantics(); } [Fact] - public void Property_Reorder_Auto_Class() + public void Property_Reorder_Auto_WithInitializer() { - var src1 = "class C { int P { get; set; } int Q { get; set; } }"; - var src2 = "class C { int Q { get; set; } int P { get; set; } }"; + var src1 = """ + class C + { + + int P { get; } = 0; + int Q { get; } = 1; + int R { get; } = 2; + } + """; + + var src2 = """ + class C + { + int R { get; } = 2; + int P { get; } = 0; + int Q { get; } = 1; + + } + """; var edits = GetTopEdits(src1, src2); - edits.VerifyEdits( - "Reorder [int Q { get; set; }]@30 -> @10"); + edits.VerifyEdits(EditKind.Reorder); + + edits.VerifySemantics([SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true)]); + } + + [Theory] + [InlineData("", "struct")] + [InlineData("", "record struct")] + [InlineData("[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]", "class")] + [InlineData("[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]", "record class")] + internal void Property_Reorder_TypeLayout(string attribute, string keyword) + { + var src1 = attribute + keyword + """ + C + { + + int P => 0; + int Q => 1; + int R => 2; + } + """; + + var src2 = attribute + keyword + """ + C + { + int R => 2; + int P => 0; + int Q => 1; + + } + """; + + var edits = GetTopEdits(src1, src2); + + edits.VerifyEdits(EditKind.Reorder); + + edits.VerifySemantics(); + } + + [Theory] + [InlineData("", "struct", RudeEditKind.InsertOrMoveStructMember)] + [InlineData("", "record struct", RudeEditKind.InsertOrMoveStructMember)] + [InlineData("[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]", "class", RudeEditKind.InsertOrMoveTypeWithLayoutMember)] + [InlineData("[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]", "record class", RudeEditKind.InsertOrMoveTypeWithLayoutMember)] + internal void Property_Reorder_Auto_TypeLayout(string attribute, string keyword, RudeEditKind rudeEditKind) + { + var src1 = attribute + keyword + " C { int P { get; } int Q { get; } int R { get; } }"; + var src2 = attribute + keyword + " C { int R { get; } int P { get; } int Q { get; } }"; + + var edits = GetTopEdits(src1, src2); + + edits.VerifyEdits(EditKind.Reorder); edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.Move, "int Q", FeaturesResources.auto_property)); + Diagnostic(rudeEditKind, "int R", GetResource("auto-property"), GetResource(keyword))); } [Fact] - public void Property_Reorder_Auto_Struct() + public void Property_Reorder_Auto_Reloadable() { - var src1 = "struct C { int P { get; set; } byte Q { get; set; } }"; - var src2 = "struct C { byte Q { get; set; } int P { get; set; } }"; + var src1 = ReloadableAttributeSrc + """ + [CreateNewOnMetadataUpdate] + struct C + { + + int P { get; } = 0; + int Q { get; } = 1; + int R { get; } + } + """; + + var src2 = ReloadableAttributeSrc + """ + [CreateNewOnMetadataUpdate] + struct C + { + int R { get; } + int P { get; } = 0; + int Q { get; } = 1; + + } + """; var edits = GetTopEdits(src1, src2); - edits.VerifyEdits( - "Reorder [byte Q { get; set; }]@31 -> @11"); + edits.VerifyEdits(EditKind.Reorder); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.Move, "byte Q", FeaturesResources.auto_property)); + edits.VerifySemantics( + [SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"))], + capabilities: EditAndContinueCapabilities.NewTypeDefinition); } [Fact] - public void PropertyAccessorReorder_GetSet() + public void PropertyAccessor_Reorder_GetSet() { var src1 = "class C { int P { get { return 1; } set { } } }"; var src2 = "class C { int P { set { } get { return 1; } } }"; @@ -17735,7 +18192,7 @@ public void PropertyAccessorReorder_GetSet() } [Fact] - public void PropertyAccessorReorder_GetInit() + public void PropertyAccessor_Reorder_GetInit() { var src1 = "class C { int P { get { return 1; } init { } } }"; var src2 = "class C { int P { init { } get { return 1; } } }"; @@ -17824,7 +18281,7 @@ public void Property_Update_Type_TypeLayout() var edits = GetTopEdits(src1, src2); edits.VerifySemanticDiagnostics( - [Diagnostic(RudeEditKind.InsertIntoStruct, "long P", GetResource("auto-property"), GetResource("struct"))], + [Diagnostic(RudeEditKind.InsertOrMoveStructMember, "long P", GetResource("auto-property"), GetResource("struct"))], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -17987,8 +18444,44 @@ class C Diagnostic(RudeEditKind.InsertExtern, "private static extern int P3", FeaturesResources.property_)); } + [Theory] + [InlineData("", "struct", RudeEditKind.InsertOrMoveStructMember)] + [InlineData("[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]", "class", RudeEditKind.InsertOrMoveTypeWithLayoutMember)] + internal void Property_Insert_TypeLayout(string attribute, string type, RudeEditKind rudeEditKind) + { + var src1 = attribute + type + """ + S + { + public int a; + + public S(int z) { a = z; } + } + """; + var src2 = attribute + type + """ + S + { + public int a; + int c { get; set; } + int e { get { return 0; } set { } } + int g { get; } = 1; + int i { get; set; } = 1; + int k => 1; + int l { get => 1; set {} } + int m { get => 1; set => k; } + public S(int z) { a = z; } + } + """; + + var edits = GetTopEdits(src1, src2); + + edits.VerifySemanticDiagnostics( + Diagnostic(rudeEditKind, "int c", GetResource("auto-property"), GetResource(type)), + Diagnostic(rudeEditKind, "int g", GetResource("auto-property"), GetResource(type)), + Diagnostic(rudeEditKind, "int i", GetResource("auto-property"), GetResource(type))); + } + [Fact] - public void Property_Insert_IntoStruct() + public void Property_Insert_IntoStruct_Static() { var src1 = @" struct S @@ -18002,13 +18495,13 @@ struct S struct S { public int a; - private static int c { get; set; } - private static int e { get { return 0; } set { } } - private static int g { get; } = 1; - private static int i { get; set; } = 1; - private static int k => 1; - private static int l { get => 1; set {} } - private static int m { get => 1; set => k; } + static int c { get; set; } + static int e { get { return 0; } set { } } + static int g { get; } = 1; + static int i { get; set; } = 1; + static int k => 1; + static int l { get => 1; set {} } + static int m { get => 1; set => k; } public S(int z) { a = z; } } "; @@ -18016,56 +18509,9 @@ struct S var edits = GetTopEdits(src1, src2); edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.InsertIntoStruct, "private static int c", GetResource("auto-property"), GetResource("struct")), - Diagnostic(RudeEditKind.InsertIntoStruct, "private static int g", GetResource("auto-property"), GetResource("struct")), - Diagnostic(RudeEditKind.InsertIntoStruct, "private static int i", GetResource("auto-property"), GetResource("struct"))); - } - - [Fact] - public void Property_Insert_IntoLayoutClass_Sequential() - { - var src1 = @" -using System.Runtime.InteropServices; - -[StructLayoutAttribute(LayoutKind.Sequential)] -class C -{ - private int a; -} -"; - var src2 = @" -using System.Runtime.InteropServices; - -[StructLayoutAttribute(LayoutKind.Sequential)] -class C -{ - private int a; - private int b { get; set; } - private static int c { get; set; } - private int d { get { return 0; } set { } } - private static int e { get { return 0; } set { } } - private int f { get; } = 1; - private static int g { get; } = 1; - private int h { get; set; } = 1; - private static int i { get; set; } = 1; - private int j => 1; - private static int k => 1; - private int l { get => 1; set { } } - private static int m { get => 1; set { } } - private int n { get { return 1; } set => a; } - private static int o { get { return 1; } set => a; } -} -"; - - var edits = GetTopEdits(src1, src2); - - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "private int b", GetResource("auto-property"), GetResource("class")), - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "private static int c", GetResource("auto-property"), GetResource("class")), - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "private int f", GetResource("auto-property"), GetResource("class")), - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "private static int g", GetResource("auto-property"), GetResource("class")), - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "private int h", GetResource("auto-property"), GetResource("class")), - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "private static int i", GetResource("auto-property"), GetResource("class"))); + Diagnostic(RudeEditKind.InsertOrMoveStructMember, "static int c", GetResource("auto-property"), GetResource("struct")), + Diagnostic(RudeEditKind.InsertOrMoveStructMember, "static int g", GetResource("auto-property"), GetResource("struct")), + Diagnostic(RudeEditKind.InsertOrMoveStructMember, "static int i", GetResource("auto-property"), GetResource("struct"))); } [Fact] @@ -20359,7 +20805,7 @@ public void Event_Insert() } [Fact] - public void Event_Delete_CustomAccessors() + public void Event_Delete() { var src1 = "class C { event int E { remove { } add { } } }"; var src2 = "class C { }"; @@ -20376,7 +20822,7 @@ public void Event_Delete_CustomAccessors() } [Fact] - public void Event_Delete_SynthesizedAccessors() + public void EventField_Delete() { var src1 = "class C { event System.Action E; }"; var src2 = "class C { }"; @@ -20389,7 +20835,7 @@ public void Event_Delete_SynthesizedAccessors() } [Fact] - public void Event_Insert_TypeLayout_CustomAccessors() + public void Event_Insert_TypeLayout() { var src1 = @" using System; @@ -20417,7 +20863,7 @@ private event Action c { add { } remove { } } } [Fact] - public void Event_Insert_TypeLayout_SynthesizedAccessors() + public void EventField_Insert_TypeLayout() { var src1 = @" using System; @@ -20442,7 +20888,7 @@ class C var edits = GetTopEdits(src1, src2); edits.VerifySemanticDiagnostics( - [Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "c", GetResource("event field"), GetResource("class"))], + [Diagnostic(RudeEditKind.InsertOrMoveTypeWithLayoutMember, "c", GetResource("event field"), GetResource("class"))], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -20574,7 +21020,7 @@ public readonly event Action E } [Fact] - public void Event_Attribute_Add_SynthesizedAccessors() + public void EventField_Attribute_Add() { var src1 = @" class C @@ -20664,7 +21110,7 @@ event Action F { add {} [System.Obsolete]remove {} } } [Fact] - public void Field_Event_Attribute_Delete() + public void EventField_Attribute_Delete() { var src1 = @" class C @@ -20788,7 +21234,7 @@ public void Event_Update_Type_Stackalloc() } [Fact] - public void Event_Rename_CustomAcccessors() + public void Event_Rename() { var src1 = "class C { event System.Action E { remove { } add { } } }"; var src2 = "class C { event System.Action F { remove { } add { } } }"; @@ -20812,7 +21258,7 @@ public void Event_Rename_CustomAcccessors() } [Fact] - public void Event_Rename_SynthesizedAccessors() + public void EventField_Rename() { var src1 = "class C { event System.Action E; }"; var src2 = "class C { event System.Action F; }"; @@ -20825,7 +21271,7 @@ public void Event_Rename_SynthesizedAccessors() } [Fact] - public void Event_Update_Type_CustomAcccessors() + public void Event_Update_Type() { var src1 = "class C { event System.Action E { remove { } add { } } }"; var src2 = "class C { event System.Action E { remove { } add { } } }"; @@ -20848,7 +21294,7 @@ public void Event_Update_Type_CustomAcccessors() } [Fact] - public void Event_Update_Type_SynthesizedAcccessors_RuntimeTypeChanged() + public void EventField_Update_Type_RuntimeTypeChanged() { var src1 = "class C { event System.Action E; }"; var src2 = "class C { event System.Action E; }"; @@ -20864,7 +21310,7 @@ public void Event_Update_Type_SynthesizedAcccessors_RuntimeTypeChanged() [InlineData("string", "string?")] [InlineData("object", "dynamic")] [InlineData("(int a, int b)", "(int a, int c)")] - public void Event_Update_Type_SynthesizedAcccessors_RuntimeTypeUnchanged(string oldType, string newType) + public void EventField_Update_Type_RuntimeTypeUnchanged(string oldType, string newType) { var src1 = "class C { event System.Action<" + oldType + "> F, G; }"; var src2 = "class C { event System.Action<" + newType + "> F, G; }"; @@ -20877,22 +21323,142 @@ public void Event_Update_Type_SynthesizedAcccessors_RuntimeTypeUnchanged(string } [Fact] - public void Event_Reorder_SynthesizedAccessors() + public void EventField_Reorder() { - var src1 = "class C { int a = 0; int b = 1; event System.Action c = 2; }"; - var src2 = "class C { event System.Action c = 2; int a = 0; int b = 1; }"; + var src1 = """ + using System; + class C + { + + event Action a = null; + event Action b = null; + event Action c; + } + """; + + var src2 = """ + using System; + class C + { + event Action c; + event Action a = null; + event Action b = null; + + } + """; var edits = GetTopEdits(src1, src2); - edits.VerifyEdits( - "Reorder [event System.Action c = 2;]@32 -> @10"); + edits.VerifyEdits(EditKind.Reorder); + + edits.VerifySemantics(); + } + + [Fact] + public void EventField_Reorder_WithInitializer() + { + var src1 = """ + using System; + class C + { + + event Action a = null; + event Action b = null; + event Action c = null; + } + """; + + var src2 = """ + using System; + class C + { + event Action c = null; + event Action a = null; + event Action b = null; + + } + """; + + var edits = GetTopEdits(src1, src2); + + edits.VerifyEdits(EditKind.Reorder); + + edits.VerifySemantics([SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true)]); + } + + [Theory] + [InlineData("", "struct", RudeEditKind.InsertOrMoveStructMember)] + [InlineData("", "record struct", RudeEditKind.InsertOrMoveStructMember)] + [InlineData("[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]", "class", RudeEditKind.InsertOrMoveTypeWithLayoutMember)] + [InlineData("[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]", "record class", RudeEditKind.InsertOrMoveTypeWithLayoutMember)] + internal void EventField_Reorder_TypeLayout(string attribute, string keyword, RudeEditKind rudeEditKind) + { + var src1 = $$""" + using System; + {{attribute}}{{keyword}} C + { + + event Action a; + event Action b; + event Action c; + } + """; + + var src2 = $$""" + using System; + {{attribute}}{{keyword}} C + { + event Action c; + event Action a; + event Action b; + + } + """; + + var edits = GetTopEdits(src1, src2); + + edits.VerifyEdits(EditKind.Reorder); edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.Move, "event System.Action c = 2", CSharpFeaturesResources.event_field)); + Diagnostic(rudeEditKind, "event Action c", GetResource("event field"), GetResource(keyword))); + } + + [Fact] + public void EventField_Reorder_Reloadable() + { + var src1 = "using System;" + ReloadableAttributeSrc + """ + [CreateNewOnMetadataUpdate] + class C + { + + event Action a = null; + event Action b = null; + event Action c; + } + """; + + var src2 = "using System;" + ReloadableAttributeSrc + """ + [CreateNewOnMetadataUpdate] + class C + { + event Action c; + event Action a = null; + event Action b = null; + + } + """; + + var edits = GetTopEdits(src1, src2); + + edits.VerifyEdits(EditKind.Reorder); + + edits.VerifySemantics( + [SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"))], + capabilities: EditAndContinueCapabilities.NewTypeDefinition); } [Fact] - public void Event_Partial_InsertDelete_SynthesizedAccessors() + public void EventField_Partial_InsertDelete() { var srcA1 = "partial class C { static void F() {} }"; var srcB1 = "partial class C { event System.Action E = F; }"; @@ -21137,10 +21703,8 @@ public void Parameter_Reorder_UpdateBody() "Reorder [int b]@31 -> @24"); edits.VerifySemantics( - [ - SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M")) - ], - capabilities: EditAndContinueCapabilities.UpdateParameters); + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M"))], + capabilities: EditAndContinueCapabilities.UpdateParameters); edits.VerifySemanticDiagnostics( [Diagnostic(RudeEditKind.RenamingNotSupportedByRuntime, "int b", FeaturesResources.parameter)], diff --git a/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs b/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs index 0f1e60584b510..b5242a5245b4b 100644 --- a/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs +++ b/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs @@ -3002,9 +3002,17 @@ newSymbol is IPropertySymbol newProperty && break; case EditKind.Reorder: + Contract.ThrowIfNull(oldModel); + Contract.ThrowIfNull(newModel); Contract.ThrowIfNull(oldSymbol); Contract.ThrowIfNull(newSymbol); + // Reordering fields in a type in source doesn't actually result in + // a metadata update that would reoder them in the runtime type representation. + // The runtime does not allow us to communicate such change in the delta. + // If we allowed reodering fields of a type with sequential/explicit layout + // it might be confusing because after the change the order of the fields + // in the runtime type may not match the source anymore. ReportTypeLayoutUpdateRudeEdits(diagnosticContext, oldSymbol, cancellationToken); if (oldSymbol is IParameterSymbol && @@ -3012,9 +3020,12 @@ newSymbol is IPropertySymbol newProperty && !capabilities.Grant(EditAndContinueCapabilities.UpdateParameters)) { diagnosticContext.Report(RudeEditKind.RenamingNotSupportedByRuntime, cancellationToken); + continue; } - continue; + // The member may also be updated (modifiers, attributes, body, etc.). Continue processing as an update. + editKind = SemanticEditKind.Update; + break; default: throw ExceptionUtilities.UnexpectedValue(edit.Kind); @@ -4989,7 +5000,7 @@ public void ReportTypeLayoutUpdateRudeEdits(CancellationToken cancellationToken) Debug.Assert(newSymbol != null); Report( - (newSymbol.ContainingType.TypeKind == TypeKind.Struct) ? RudeEditKind.InsertIntoStruct : RudeEditKind.InsertIntoClassWithLayout, + (newSymbol.ContainingType.TypeKind == TypeKind.Struct) ? RudeEditKind.InsertOrMoveStructMember : RudeEditKind.InsertOrMoveTypeWithLayoutMember, cancellationToken, arguments: [ @@ -5009,6 +5020,15 @@ private DiagnosticContext CreateDiagnosticContext(ArrayBuilder private static bool SymbolPresenceAffectsSynthesizedRecordMembers(ISymbol symbol) => symbol is { IsStatic: false, ContainingType.IsRecord: true } and - (IPropertySymbol { GetMethod.IsImplicitlyDeclared: false, SetMethod: null or { IsImplicitlyDeclared: false } } or IFieldSymbol); + (IPropertySymbol { GetMethod.IsImplicitlyDeclared: false, SetMethod: null or { IsImplicitlyDeclared: false } } or + IFieldSymbol or + // event field: + IEventSymbol { AddMethod.IsImplicitlyDeclared: true }); /// /// True if a syntactic delete edit of an in diff --git a/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticDescriptors.cs b/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticDescriptors.cs index d68a41ce4349f..c4f134f6bbc50 100644 --- a/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticDescriptors.cs +++ b/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticDescriptors.cs @@ -91,8 +91,8 @@ void AddGeneralDiagnostic(EditAndContinueErrorCode code, string resourceName, Di AddRudeEdit(RudeEditKind.InsertExtern, nameof(FeaturesResources.Adding_an_extern_0_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.InsertDllImport, nameof(FeaturesResources.Adding_an_imported_method_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.InsertOperator, nameof(FeaturesResources.Adding_a_user_defined_0_requires_restarting_the_application)); - AddRudeEdit(RudeEditKind.InsertIntoStruct, nameof(FeaturesResources.Adding_0_into_a_1_requires_restarting_the_application)); - AddRudeEdit(RudeEditKind.InsertIntoClassWithLayout, nameof(FeaturesResources.Adding_0_into_a_class_with_explicit_or_sequential_layout_requires_restarting_the_application)); + AddRudeEdit(RudeEditKind.InsertOrMoveStructMember, nameof(FeaturesResources.Adding_or_moving_0_of_1_requires_restarting_the_application)); + AddRudeEdit(RudeEditKind.InsertOrMoveTypeWithLayoutMember, nameof(FeaturesResources.Adding_or_moving_0_of_1_with_explicit_or_sequential_layout_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.Move, nameof(FeaturesResources.Moving_0_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.Delete, nameof(FeaturesResources.Deleting_0_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.GenericMethodUpdate, nameof(FeaturesResources.Modifying_a_generic_method_requires_restarting_the_application)); @@ -149,6 +149,7 @@ void AddGeneralDiagnostic(EditAndContinueErrorCode code, string resourceName, Di AddRudeEdit(RudeEditKind.ChangingNameOrSignatureOfActiveMember, nameof(FeaturesResources.Changing_name_or_signature_of_0_that_contains_an_active_statement_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.UpdateMightNotHaveAnyEffect, nameof(FeaturesResources.Changing_0_might_not_have_any_effect_until_the_application_is_restarted), DiagnosticSeverity.Warning); AddRudeEdit(RudeEditKind.TypeUpdateAroundActiveStatement, nameof(FeaturesResources.Updating_a_0_around_an_active_statement_requires_restarting_the_application)); + AddRudeEdit(RudeEditKind.InsertOrMoveComInterfaceMember, nameof(FeaturesResources.Adding_or_moving_0_of_a_COM_interface_requires_restarting_the_application)); // VB specific AddRudeEdit(RudeEditKind.HandlesClauseUpdate, nameof(FeaturesResources.Updating_the_Handles_clause_of_0_requires_restarting_the_application)); diff --git a/src/Features/Core/Portable/EditAndContinue/RudeEditKind.cs b/src/Features/Core/Portable/EditAndContinue/RudeEditKind.cs index 3f985f9080329..ad21348734f9b 100644 --- a/src/Features/Core/Portable/EditAndContinue/RudeEditKind.cs +++ b/src/Features/Core/Portable/EditAndContinue/RudeEditKind.cs @@ -41,8 +41,8 @@ internal enum RudeEditKind : ushort // InsertNonPublicConstructor = 27, // InsertGenericMethod = 28, InsertDllImport = 29, - InsertIntoStruct = 30, - InsertIntoClassWithLayout = 31, + InsertOrMoveStructMember = 30, + InsertOrMoveTypeWithLayoutMember = 31, Move = 32, Delete = 33, // MethodBodyAdd = 34, @@ -144,4 +144,5 @@ internal enum RudeEditKind : ushort ChangingNameOrSignatureOfActiveMember = 117, UpdateMightNotHaveAnyEffect = 118, TypeUpdateAroundActiveStatement = 119, + InsertOrMoveComInterfaceMember = 120, } diff --git a/src/Features/Core/Portable/FeaturesResources.resx b/src/Features/Core/Portable/FeaturesResources.resx index 5cec87490ebac..0c9edac5be335 100644 --- a/src/Features/Core/Portable/FeaturesResources.resx +++ b/src/Features/Core/Portable/FeaturesResources.resx @@ -354,8 +354,8 @@ Changing the declaration scope of a captured variable '{0}' requires restarting the application. - - Adding {0} into a {1} requires restarting the application. + + Adding or moving {0} of {1} requires restarting the application. Adding {0} into an interface requires restarting the application. @@ -363,8 +363,11 @@ Adding {0} into an interface method requires restarting the application. - - Adding {0} into a class with explicit or sequential layout requires restarting the application. + + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + + + Adding or moving {0} of a COM interface requires restarting the application. Updating the modifiers of {0} requires restarting the application. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf index 141f5cb7cc223..7e1015fd27637 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf @@ -85,16 +85,6 @@ Ujistěte se, že specifikátor tt použijete pro jazyky, pro které je nezbytn Přidání {0} kolem aktivního příkazu vyžaduje restartování aplikace. - - Adding {0} into a {1} requires restarting the application. - Přidání {0} do {1} vyžaduje restartování aplikace. - - - - Adding {0} into a class with explicit or sequential layout requires restarting the application. - Přidání {0} do třídy s explicitním nebo sekvenčním rozložením vyžaduje restartování aplikace. - - Adding {0} into an interface method requires restarting the application. Přidání {0} do metody rozhraní vyžaduje restartování aplikace. @@ -155,6 +145,21 @@ Ujistěte se, že specifikátor tt použijete pro jazyky, pro které je nezbytn Přidání importované metody vyžaduje restartování aplikace. + + Adding or moving {0} of {1} requires restarting the application. + Adding or moving {0} of {1} requires restarting the application. + + + + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + + + + Adding or moving {0} of a COM interface requires restarting the application. + Adding or moving {0} of a COM interface requires restarting the application. + + Align wrapped arguments Zarovnat zalomené argumenty diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf index cbaff3cab2b0b..1ed73b6c96936 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf @@ -85,16 +85,6 @@ Stellen Sie sicher, dass Sie den Bezeichner "tt" für Sprachen verwenden, für d Das Hinzufügen von {0} um eine aktive Anweisung erfordert einen Neustart der Anwendung. - - Adding {0} into a {1} requires restarting the application. - Das Hinzufügen von {0} zu einer {1} erfordert einen Neustart der Anwendung. - - - - Adding {0} into a class with explicit or sequential layout requires restarting the application. - Das Hinzufügen von {0} zu einer Klasse mit explizitem oder sequenziellem Layout erfordert einen Neustart der Anwendung. - - Adding {0} into an interface method requires restarting the application. Das Hinzufügen von {0} zu einer Schnittstellenmethode erfordert einen Neustart der Anwendung. @@ -155,6 +145,21 @@ Stellen Sie sicher, dass Sie den Bezeichner "tt" für Sprachen verwenden, für d Das Hinzufügen einer importierten Methode erfordert einen Neustart der Anwendung. + + Adding or moving {0} of {1} requires restarting the application. + Adding or moving {0} of {1} requires restarting the application. + + + + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + + + + Adding or moving {0} of a COM interface requires restarting the application. + Adding or moving {0} of a COM interface requires restarting the application. + + Align wrapped arguments Umschlossene Argumente ausrichten diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf index 06bfae45d8fa0..b9286ae1a3c91 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf @@ -85,16 +85,6 @@ Asegúrese de usar el especificador "tt" para los idiomas para los que es necesa Para agregar {0} alrededor de una instrucción de acción es necesario reiniciar la aplicación. - - Adding {0} into a {1} requires restarting the application. - Para agregar {0} a un {1} es necesario reiniciar la aplicación. - - - - Adding {0} into a class with explicit or sequential layout requires restarting the application. - Para agregar {0} en una clase con un diseño secuencial o explícito es necesario reiniciar la aplicación. - - Adding {0} into an interface method requires restarting the application. Para agregar {0} en un método de interfaz es necesario reiniciar la aplicación. @@ -155,6 +145,21 @@ Asegúrese de usar el especificador "tt" para los idiomas para los que es necesa Para agregar un método importado es necesario reiniciar la aplicación. + + Adding or moving {0} of {1} requires restarting the application. + Adding or moving {0} of {1} requires restarting the application. + + + + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + + + + Adding or moving {0} of a COM interface requires restarting the application. + Adding or moving {0} of a COM interface requires restarting the application. + + Align wrapped arguments Alinear argumentos ajustados diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf index 1430f68580ad3..23e9ffd7d1948 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf @@ -85,16 +85,6 @@ Veillez à utiliser le spécificateur "tt" pour les langues où il est nécessai L’ajout de {0} autour d’une instruction active requiert le redémarrage de l’application. - - Adding {0} into a {1} requires restarting the application. - L’ajout de {0} dans un {1} requiert le redémarrage de l’application. - - - - Adding {0} into a class with explicit or sequential layout requires restarting the application. - L’ajout de {0} dans une classe avec une disposition explicite ou séquentielle requiert le redémarrage de l’application. - - Adding {0} into an interface method requires restarting the application. L’ajout de {0} dans une méthode d’interface requiert le redémarrage de l’application. @@ -155,6 +145,21 @@ Veillez à utiliser le spécificateur "tt" pour les langues où il est nécessai L’ajout d’une méthode importée requiert le redémarrage de l’application. + + Adding or moving {0} of {1} requires restarting the application. + Adding or moving {0} of {1} requires restarting the application. + + + + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + + + + Adding or moving {0} of a COM interface requires restarting the application. + Adding or moving {0} of a COM interface requires restarting the application. + + Align wrapped arguments Aligner les arguments enveloppés diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf index 60a5f84dce4be..6bb8dd3d96c3c 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf @@ -85,16 +85,6 @@ Assicurarsi di usare l'identificatore "tt" per le lingue per le quali è necessa Se si aggiunge {0} all'inizio di un'istruzione attiva, è necessario riavviare l'applicazione. - - Adding {0} into a {1} requires restarting the application. - Se si aggiunge {0} in un elemento {1}, è necessario riavviare l'applicazione. - - - - Adding {0} into a class with explicit or sequential layout requires restarting the application. - Se si aggiunge {0} in una classe con layout esplicito o sequenziale, è necessario riavviare l'applicazione. - - Adding {0} into an interface method requires restarting the application. Se si aggiunge {0} in un metodo di interfaccia, è necessario riavviare l'applicazione. @@ -155,6 +145,21 @@ Assicurarsi di usare l'identificatore "tt" per le lingue per le quali è necessa Se si aggiunge un metodo importato, è necessario riavviare l'applicazione. + + Adding or moving {0} of {1} requires restarting the application. + Adding or moving {0} of {1} requires restarting the application. + + + + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + + + + Adding or moving {0} of a COM interface requires restarting the application. + Adding or moving {0} of a COM interface requires restarting the application. + + Align wrapped arguments Allinea gli argomenti con ritorno a capo diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf index d06d1b1d967a4..dd5559fc36b49 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf @@ -85,16 +85,6 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma アクティブ ステートメントの前後に {0} を追加するには、アプリケーションを再起動する必要があります。 - - Adding {0} into a {1} requires restarting the application. - {0} を {1} に追加するには、アプリケーションを再起動する必要があります。 - - - - Adding {0} into a class with explicit or sequential layout requires restarting the application. - 明示的またはシーケンシャルなレイアウトのクラスに {0} を追加するには、アプリケーションを再起動する必要があります。 - - Adding {0} into an interface method requires restarting the application. インターフェイス メソッドに {0} を追加するには、アプリケーションを再起動する必要があります。 @@ -155,6 +145,21 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma インポートされたメソッドを追加するには、アプリケーションを再起動する必要があります。 + + Adding or moving {0} of {1} requires restarting the application. + Adding or moving {0} of {1} requires restarting the application. + + + + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + + + + Adding or moving {0} of a COM interface requires restarting the application. + Adding or moving {0} of a COM interface requires restarting the application. + + Align wrapped arguments 折り返された引数を揃える diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf index 4b7d83a1b8623..2dc354351b933 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf @@ -85,16 +85,6 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 활성 문 주위에 {0}을(를) 추가하려면 응용 프로그램을 다시 시작해야 합니다. - - Adding {0} into a {1} requires restarting the application. - {0}을(를) {1}에 추가하려면 응용 프로그램을 다시 시작해야 합니다. - - - - Adding {0} into a class with explicit or sequential layout requires restarting the application. - 명시적 또는 순차 레이아웃이 있는 클래스에 {0}을(를) 추가하려면 응용 프로그램을 다시 시작해야 합니다. - - Adding {0} into an interface method requires restarting the application. 인터페이스 메소드에 {0}을(를) 추가하려면 응용 프로그램을 다시 시작해야 합니다. @@ -155,6 +145,21 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 가져온 메서드를 추가하려면 응용 프로그램을 다시 시작해야 합니다. + + Adding or moving {0} of {1} requires restarting the application. + Adding or moving {0} of {1} requires restarting the application. + + + + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + + + + Adding or moving {0} of a COM interface requires restarting the application. + Adding or moving {0} of a COM interface requires restarting the application. + + Align wrapped arguments 래핑된 인수 맞춤 diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf index 8088a42b9ee73..055583a50262f 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf @@ -85,16 +85,6 @@ Pamiętaj, aby nie używać specyfikatora „tt” dla wszystkich języków, w k Dodawanie elementu {0} wokół aktywnej instrukcji wymaga ponownego uruchomienia aplikacji. - - Adding {0} into a {1} requires restarting the application. - Dodanie elementu {0} do {1} wymaga ponownego uruchomienia aplikacji. - - - - Adding {0} into a class with explicit or sequential layout requires restarting the application. - Dodawanie elementu {0} do klasy za pomocą jawnego lub sekwencyjnego układu wymaga ponownego uruchomienia aplikacji. - - Adding {0} into an interface method requires restarting the application. Dodanie elementu {0} do metody interfejsu wymaga ponownego uruchomienia aplikacji. @@ -155,6 +145,21 @@ Pamiętaj, aby nie używać specyfikatora „tt” dla wszystkich języków, w k Dodawanie zaimportowanej metody wymaga ponownego uruchomienia aplikacji. + + Adding or moving {0} of {1} requires restarting the application. + Adding or moving {0} of {1} requires restarting the application. + + + + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + + + + Adding or moving {0} of a COM interface requires restarting the application. + Adding or moving {0} of a COM interface requires restarting the application. + + Align wrapped arguments Wyrównaj zawinięte argumenty diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf index 57a0aee48ddc3..57b63326b5c4f 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf @@ -85,16 +85,6 @@ Verifique se o especificador "tt" foi usado para idiomas para os quais é necess Adicionar {0} em torno de uma instrução ativa requer a reinicialização do aplicativo. - - Adding {0} into a {1} requires restarting the application. - Adicionar {0} a um {1} requer a reinicialização do aplicativo. - - - - Adding {0} into a class with explicit or sequential layout requires restarting the application. - Adicionar {0} a uma classe com layout explícito ou sequencial requer a reinicialização do aplicativo. - - Adding {0} into an interface method requires restarting the application. Adicionar {0} a um método de interface requer a reinicialização do aplicativo. @@ -155,6 +145,21 @@ Verifique se o especificador "tt" foi usado para idiomas para os quais é necess Adicionar um método importado requer a reinicialização do aplicativo. + + Adding or moving {0} of {1} requires restarting the application. + Adding or moving {0} of {1} requires restarting the application. + + + + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + + + + Adding or moving {0} of a COM interface requires restarting the application. + Adding or moving {0} of a COM interface requires restarting the application. + + Align wrapped arguments Alinhar argumentos encapsulados diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf index 88c293e68681c..b5fb73b44bf19 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf @@ -85,16 +85,6 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Для добавления {0} вокруг активного оператора требуется перезапустить приложение. - - Adding {0} into a {1} requires restarting the application. - Для добавления {0} в {1} требуется перезапустить приложение. - - - - Adding {0} into a class with explicit or sequential layout requires restarting the application. - Для добавления {0} в класс с явным или последовательным макетом требуется перезапустить приложение. - - Adding {0} into an interface method requires restarting the application. Для добавления {0} в метод интерфейса требуется перезапустить приложение. @@ -155,6 +145,21 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Для добавления импортированного метода требуется перезапустить приложение. + + Adding or moving {0} of {1} requires restarting the application. + Adding or moving {0} of {1} requires restarting the application. + + + + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + + + + Adding or moving {0} of a COM interface requires restarting the application. + Adding or moving {0} of a COM interface requires restarting the application. + + Align wrapped arguments Выровнять свернутые аргументы diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf index 7ed7c945e655d..2b409d687a5b9 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf @@ -85,16 +85,6 @@ AM ve PM arasındaki farkın korunmasının gerekli olduğu diller için "tt" be Etkin bir deyim etrafında bir {0} öğesinin eklenmesi, uygulamanın yeniden başlatılmasını gerektirir. - - Adding {0} into a {1} requires restarting the application. - {1} öğesine {0} eklemek, uygulamanın yeniden başlatılmasını gerektir. - - - - Adding {0} into a class with explicit or sequential layout requires restarting the application. - Açık veya sıralı düzene sahip bir sınıfa {0} eklemek, uygulamanın yeniden başlatılmasını gerektirir. - - Adding {0} into an interface method requires restarting the application. Bir arabirim yöntemine {0} eklemek, uygulamanın yeniden başlatılmasını gerektirir. @@ -155,6 +145,21 @@ AM ve PM arasındaki farkın korunmasının gerekli olduğu diller için "tt" be İçeri aktarılan bir yöntemin eklenmesi uygulamanın yeniden başlatılmasını gerektiriyor. + + Adding or moving {0} of {1} requires restarting the application. + Adding or moving {0} of {1} requires restarting the application. + + + + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + + + + Adding or moving {0} of a COM interface requires restarting the application. + Adding or moving {0} of a COM interface requires restarting the application. + + Align wrapped arguments Sarmalanan bağımsız değişkenleri hizala diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf index c04f03e36f371..03533f977762a 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf @@ -85,16 +85,6 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 在活动语句周围添加 {0} 需要重新启动应用程序。 - - Adding {0} into a {1} requires restarting the application. - 将 {0} 添加进 {1} 中需要重新启动应用程序。 - - - - Adding {0} into a class with explicit or sequential layout requires restarting the application. - 将 {0} 添加到具有显式或顺序布局的类中需要重新启动应用程序。 - - Adding {0} into an interface method requires restarting the application. 将 {0} 添加到接口方法中需要重新启动应用程序。 @@ -155,6 +145,21 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 添加导入的方法需要重新启动应用程序。 + + Adding or moving {0} of {1} requires restarting the application. + Adding or moving {0} of {1} requires restarting the application. + + + + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + + + + Adding or moving {0} of a COM interface requires restarting the application. + Adding or moving {0} of a COM interface requires restarting the application. + + Align wrapped arguments 对齐包装的参数 diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf index 0f4e175d52336..ee02eac9cef45 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf @@ -85,16 +85,6 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 新增作用中陳述式前後的 {0} 需要重新啟動應用程式。 - - Adding {0} into a {1} requires restarting the application. - 新增 {0} 到 {1} 需要重新啟動應用程式。 - - - - Adding {0} into a class with explicit or sequential layout requires restarting the application. - 在具有明確或循序配置的類別中新增 {0} 需要重新啟動應用程式。 - - Adding {0} into an interface method requires restarting the application. 在介面方法中新增 {0} 需要重新啟動應用程式。 @@ -155,6 +145,21 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 新增匯入的方法需要重新啟動應用程式。 + + Adding or moving {0} of {1} requires restarting the application. + Adding or moving {0} of {1} requires restarting the application. + + + + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + Adding or moving {0} of {1} with explicit or sequential layout requires restarting the application. + + + + Adding or moving {0} of a COM interface requires restarting the application. + Adding or moving {0} of a COM interface requires restarting the application. + + Align wrapped arguments 對齊包裝的引數 diff --git a/src/Features/Test/EditAndContinue/RudeEditDiagnosticTests.cs b/src/Features/Test/EditAndContinue/RudeEditDiagnosticTests.cs index c5fdc1551a471..04f4c36afcd54 100644 --- a/src/Features/Test/EditAndContinue/RudeEditDiagnosticTests.cs +++ b/src/Features/Test/EditAndContinue/RudeEditDiagnosticTests.cs @@ -55,15 +55,15 @@ public void ToDiagnostic() var arg2 = new HashSet() { - RudeEditKind.InsertIntoStruct, - RudeEditKind.InsertIntoStruct, + RudeEditKind.InsertOrMoveStructMember, + RudeEditKind.InsertOrMoveTypeWithLayoutMember, RudeEditKind.ChangingCapturedVariableType, RudeEditKind.RenamingCapturedVariable, RudeEditKind.ChangingStateMachineShape, RudeEditKind.InternalError, RudeEditKind.MemberBodyInternalError, RudeEditKind.ChangingNonCustomAttribute, - RudeEditKind.NotCapturingPrimaryConstructorParameter, + RudeEditKind.NotCapturingPrimaryConstructorParameter }; var arg3 = new HashSet() diff --git a/src/Features/TestUtilities/EditAndContinue/EditAndContinueTestVerifier.cs b/src/Features/TestUtilities/EditAndContinue/EditAndContinueTestVerifier.cs index 6bc6fba2cb68a..7a3b064a24196 100644 --- a/src/Features/TestUtilities/EditAndContinue/EditAndContinueTestVerifier.cs +++ b/src/Features/TestUtilities/EditAndContinue/EditAndContinueTestVerifier.cs @@ -521,7 +521,13 @@ public static void SetDocumentsState(DebuggingSession session, Solution solution internal static class EditScriptTestUtils { + public static void VerifyEdits(this EditScript actual) + => VerifyEdits(actual, Array.Empty()); + public static void VerifyEdits(this EditScript actual, params string[] expected) => AssertEx.Equal(expected, actual.Edits.Select(e => e.GetDebuggerDisplay()), itemSeparator: ",\r\n", itemInspector: s => $"\"{s}\""); + + public static void VerifyEdits(this EditScript actual, params EditKind[] expected) + => AssertEx.Equal(expected, actual.Edits.Select(e => e.Kind)); } } diff --git a/src/Features/VisualBasic/Portable/EditAndContinue/VisualBasicEditAndContinueAnalyzer.vb b/src/Features/VisualBasic/Portable/EditAndContinue/VisualBasicEditAndContinueAnalyzer.vb index 109cee82f9651..5b72758a44be3 100644 --- a/src/Features/VisualBasic/Portable/EditAndContinue/VisualBasicEditAndContinueAnalyzer.vb +++ b/src/Features/VisualBasic/Portable/EditAndContinue/VisualBasicEditAndContinueAnalyzer.vb @@ -809,7 +809,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue Return End If - result.Add((oldSymbol.ContainingSymbol, newSymbol.ContainingSymbol, EditKind.Update)) + ' Reordering of data members is only allowed if the layout of the type doesn't change. + ' Reordering of other members is a no-op, although the new order won't be reflected in metadata (Reflection will report original order). + result.Add((oldSymbol, newSymbol, EditKind.Reorder)) Case EditKind.Delete result.Add((oldSymbol, Nothing, editKind)) @@ -913,7 +915,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue Case SyntaxKind.FieldDeclaration ' Attribute or modifier update - If editKind = EditKind.Update Then + If editKind = EditKind.Update OrElse editKind = EditKind.Reorder Then Dim field = CType(node, FieldDeclarationSyntax) If field.Declarators.Count = 1 AndAlso field.Declarators(0).Names.Count = 1 Then node = field.Declarators(0).Names(0) @@ -1796,55 +1798,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue Private Sub ClassifyReorder(oldNode As SyntaxNode, newNode As SyntaxNode) Select Case newNode.Kind - Case SyntaxKind.OptionStatement, - SyntaxKind.ImportsStatement, - SyntaxKind.AttributesStatement, - SyntaxKind.NamespaceBlock, - SyntaxKind.ClassBlock, - SyntaxKind.StructureBlock, - SyntaxKind.InterfaceBlock, - SyntaxKind.ModuleBlock, - SyntaxKind.EnumBlock, - SyntaxKind.DelegateFunctionStatement, - SyntaxKind.DelegateSubStatement, - SyntaxKind.SubBlock, - SyntaxKind.FunctionBlock, - SyntaxKind.DeclareSubStatement, - SyntaxKind.DeclareFunctionStatement, - SyntaxKind.ConstructorBlock, - SyntaxKind.OperatorBlock, - SyntaxKind.PropertyBlock, - SyntaxKind.EventBlock, - SyntaxKind.GetAccessorBlock, - SyntaxKind.SetAccessorBlock, - SyntaxKind.AddHandlerAccessorBlock, - SyntaxKind.RemoveHandlerAccessorBlock, - SyntaxKind.RaiseEventAccessorBlock, - SyntaxKind.ClassConstraint, - SyntaxKind.StructureConstraint, - SyntaxKind.NewConstraint, - SyntaxKind.TypeConstraint, - SyntaxKind.AttributeList, - SyntaxKind.Attribute, - SyntaxKind.Parameter - ' We'll ignore these edits. A general policy is to ignore edits that are only discoverable via reflection. - Return - - Case SyntaxKind.SubStatement, - SyntaxKind.FunctionStatement - ' Interface methods. We could allow reordering of non-COM interface methods. - Debug.Assert(oldNode.Parent.IsKind(SyntaxKind.InterfaceBlock) AndAlso newNode.Parent.IsKind(SyntaxKind.InterfaceBlock)) - ReportError(RudeEditKind.Move) - Return - - Case SyntaxKind.PropertyStatement, - SyntaxKind.FieldDeclaration, - SyntaxKind.EventStatement - ' Maybe we could allow changing order of field declarations unless the containing type layout is sequential, - ' and it's not a COM interface. - ReportError(RudeEditKind.Move) - Return - Case SyntaxKind.EnumMemberDeclaration ' To allow this change we would need to check that values of all fields of the enum ' are preserved, or make sure we can update all method bodies that accessed those that changed. @@ -1860,9 +1813,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue ' Identifier can be moved within the same type declaration. ' Determine validity of such change in semantic analysis. Return - - Case Else - Throw ExceptionUtilities.UnexpectedValue(newNode.Kind) End Select End Sub diff --git a/src/Features/VisualBasicTest/EditAndContinue/LineEditTests.vb b/src/Features/VisualBasicTest/EditAndContinue/LineEditTests.vb index 32c515d18bda0..48948bf401f1d 100644 --- a/src/Features/VisualBasicTest/EditAndContinue/LineEditTests.vb +++ b/src/Features/VisualBasicTest/EditAndContinue/LineEditTests.vb @@ -47,11 +47,11 @@ End Class Public Sub Method_Reorder1() Dim src1 = " Class C - Shared Sub Goo() + Shared Sub G() Console.ReadLine(1) End Sub - Shared Sub Bar() + Shared Sub F() Console.ReadLine(2) End Sub End Class @@ -59,69 +59,76 @@ End Class Dim src2 = " Class C - Shared Sub Bar() + Shared Sub F() Console.ReadLine(2) End Sub - Shared Sub Goo() + Shared Sub G() Console.ReadLine(1) End Sub End Class " Dim edits = GetTopEdits(src1, src2) + + ' Consider: we could detect that the body of the method hasn't changed and avoid creating an update. edits.VerifyLineEdits( { New SourceLineUpdate(2, 6), New SourceLineUpdate(5, 5), New SourceLineUpdate(6, 2) - }, {}) + }, {SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"))}) End Sub Public Sub Method_Reorder2() Dim src1 = " -Class Program +Class C Shared Sub Main() - Goo() - Bar() + G() + F() End Sub - Shared Function Goo() As Integer + Shared Function G() As Integer Return 1 End Function - Shared Function Bar() As Integer + Shared Function F() As Integer Return 2 End Function End Class " Dim src2 = " -Class Program - Shared Function Goo() As Integer +Class C + Shared Function G() As Integer Return 1 End Function Shared Sub Main() - Goo() - Bar() + G() + F() End Sub - Shared Function Bar() As Integer + Shared Function F() As Integer Return 2 End Function End Class " Dim edits = GetTopEdits(src1, src2) + + ' Consider: we could detect that the body of the method hasn't changed and create line edits instead of an update. edits.VerifyLineEdits( { New SourceLineUpdate(2, 6), New SourceLineUpdate(6, 6), New SourceLineUpdate(7, 2), New SourceLineUpdate(10, 10) - }, {}) + }, + { + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.G")) + }) End Sub @@ -556,8 +563,8 @@ End Class " Dim edits = GetTopEdits(src1, src2) edits.VerifyLineEdits( - Array.Empty(Of SequencePointUpdates), - diagnostics:={Diagnostic(RudeEditKind.Move, "Shared Bar As Integer = 2", FeaturesResources.field)}) + {New SourceLineUpdate(2, 3), New SourceLineUpdate(3, 2)}, + {SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember(Of NamedTypeSymbol)("C").SharedConstructors.Single(), preserveLocalVariables:=True)}) End Sub @@ -576,8 +583,8 @@ End Class " Dim edits = GetTopEdits(src1, src2) edits.VerifyLineEdits( - Array.Empty(Of SequencePointUpdates), - diagnostics:={Diagnostic(RudeEditKind.Move, "Shared c As New C()", FeaturesResources.field)}) + {New SourceLineUpdate(2, 3), New SourceLineUpdate(3, 2)}, + {SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember(Of NamedTypeSymbol)("C").SharedConstructors.Single(), preserveLocalVariables:=True)}) End Sub @@ -598,8 +605,8 @@ End Class Dim edits = GetTopEdits(src1, src2) edits.VerifyLineEdits( - Array.Empty(Of SequencePointUpdates), - diagnostics:={Diagnostic(RudeEditKind.Move, "Shared c, d As New C()", FeaturesResources.field)}) + {New SourceLineUpdate(2, 3), New SourceLineUpdate(3, 2)}, + {SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember(Of NamedTypeSymbol)("C").SharedConstructors.Single(), preserveLocalVariables:=True)}) End Sub diff --git a/src/Features/VisualBasicTest/EditAndContinue/TopLevelEditingTests.vb b/src/Features/VisualBasicTest/EditAndContinue/TopLevelEditingTests.vb index ca321cab826b5..d09a8bd0b8ce5 100644 --- a/src/Features/VisualBasicTest/EditAndContinue/TopLevelEditingTests.vb +++ b/src/Features/VisualBasicTest/EditAndContinue/TopLevelEditingTests.vb @@ -2,6 +2,7 @@ ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. +Imports Microsoft.CodeAnalysis.Differencing Imports Microsoft.CodeAnalysis.EditAndContinue Imports Microsoft.CodeAnalysis.EditAndContinue.UnitTests Imports Microsoft.CodeAnalysis.Emit @@ -5090,28 +5091,114 @@ Imports System.Runtime.InteropServices End Sub - Public Sub Method_Reorder1() - Dim src1 = "Class C : " & vbLf & "Sub f(a As Integer, b As Integer)" & vbLf & "a = b : End Sub : " & vbLf & "Sub g() : End Sub : End Class" - Dim src2 = "Class C : " & vbLf & "Sub g() : End Sub : " & vbLf & "Sub f(a As Integer, b As Integer)" & vbLf & "a = b : End Sub : End Class" + Public Sub Method_Reorder() + Dim src1 = " +Class C + + + Sub F() + End Sub + Sub G() + End Sub + Sub H() + End Sub +End Class +" + + Dim src2 = " +class C + Sub H() + End Sub + Sub F() + End Sub + Sub G() + End Sub + + +End Class +" + Dim edits = GetTopEdits(src1, src2) - edits.VerifyEdits( - "Reorder [Sub g() : End Sub]@64 -> @11") + edits.VerifyEdits(EditKind.Reorder) - edits.VerifySemantics(ActiveStatementsDescription.Empty, Array.Empty(Of SemanticEditDescription)()) + edits.VerifySemantics({SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.H"))}) End Sub - Public Sub InterfaceMethod_Reorder1() - Dim src1 = "Interface I : " & vbLf & "Sub f(a As Integer, b As Integer)" & vbLf & "Sub g() : End Interface" - Dim src2 = "Interface I : " & vbLf & "Sub g() : " & vbLf & "Sub f(a As Integer, b As Integer) : End Interface" + Public Sub Method_Reorder_Interface() + Dim src1 = " +Interface I + Sub F() + Sub G() + Sub H() +End Interface +" + Dim src2 = " +Interface I + Sub H() + Sub F() + Sub G() +End Interface +" Dim edits = GetTopEdits(src1, src2) + edits.VerifyEdits(EditKind.Reorder) + edits.VerifySemantics({SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("I.H"))}) + End Sub - edits.VerifyEdits( - "Reorder [Sub g()]@49 -> @15") + + Public Sub Method_Reorder_Interface_ComImport() + Dim src1 = " +Imports System.Runtime.InteropServices + + +Interface I + Sub F() + Sub G() + Sub H() +End Interface +" + Dim src2 = " +Imports System.Runtime.InteropServices + + + +Interface I + Sub H() + Sub F() + Sub G() +End Interface +" + Dim edits = GetTopEdits(src1, src2) + edits.VerifyEdits(EditKind.Reorder) edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.Move, "Sub g()", FeaturesResources.method)) + Diagnostic(RudeEditKind.InsertOrMoveComInterfaceMember, "Sub H()", GetResource("method"))) + End Sub + + + Public Sub Method_Insert_Interface_ComImport() + Dim src1 = " +Imports System.Runtime.InteropServices + + + +Interface I +End Interface +" + Dim src2 = " +Imports System.Runtime.InteropServices + + + +Interface I + Sub F() +End Interface +" + Dim edits = GetTopEdits(src1, src2) + edits.VerifySemanticDiagnostics( + Diagnostic(RudeEditKind.InsertVirtual, "Sub F()", GetResource("method")), + Diagnostic(RudeEditKind.InsertOrMoveComInterfaceMember, "Sub F()", GetResource("method"))) End Sub @@ -7605,7 +7692,30 @@ End Class End Sub - Public Sub Field_VariableMove6() + Public Sub Field_Reorder1() + Dim src1 = " +Class C + + Dim a = 0 + Dim b = 1 + Dim c +End Class" + Dim src2 = " +Class C + Dim c + Dim a = 0 + Dim b = 1 + +End Class" + Dim edits = GetTopEdits(src1, src2) + + edits.VerifyEdits(EditKind.Reorder) + + edits.VerifySemantics() + End Sub + + + Public Sub Field_Reorder2() Dim src1 = "Class C : Dim a As Object, b As Object : End Class" Dim src2 = "Class C : Dim b As Object, a As Object : End Class" Dim edits = GetTopEdits(src1, src2) @@ -7617,7 +7727,7 @@ End Class End Sub - Public Sub Field_VariableMove7() + Public Sub Field_Reorder3() Dim src1 = "Class C : Dim a As Object, b, c As Object : End Class" Dim src2 = "Class C : Dim b, c As Object, a As Object : End Class" Dim edits = GetTopEdits(src1, src2) @@ -7628,6 +7738,149 @@ End Class edits.VerifySemantics() End Sub + + Public Sub Field_Reorder_WithInitializer() + Dim src1 = " +Class C + + Dim a = 0 + Dim b = 1 + Dim c = 2 +End Class" + Dim src2 = " +Class C + Dim c = 2 + Dim a = 0 + Dim b = 1 + +End Class" + Dim edits = GetTopEdits(src1, src2) + + edits.VerifyEdits(EditKind.Reorder) + + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember(Of NamedTypeSymbol)("C").InstanceConstructors.Single(), preserveLocalVariables:=True)) + End Sub + + + Public Sub Field_Reorder_WithEvents() + Dim src1 = " +Class C + + Dim a As Integer = 0 + Dim b As Integer = 1 + Dim WithEvents WE As Object +End Class" + Dim src2 = " +Class C + Dim WithEvents WE As Object + Dim a As Integer = 0 + Dim b As Integer = 1 + +End Class" + Dim edits = GetTopEdits(src1, src2) + + edits.VerifyEdits(EditKind.Reorder) + + edits.VerifySemantics() + End Sub + + + Friend Sub Field_Reorder_WithEvents_TypeLayout1() + Dim src1 = " +Imports System.Runtime.InteropServices + +Class C + Dim a As Integer + Dim WithEvents WE As Object +End Class" + + Dim src2 = " +Imports System.Runtime.InteropServices + +Class C + Dim WithEvents WE As Object + Dim a As Integer +End Class" + + Dim edits = GetTopEdits(src1, src2) + edits.VerifyEdits(EditKind.Reorder) + edits.VerifySemanticDiagnostics( + Diagnostic(RudeEditKind.InsertOrMoveTypeWithLayoutMember, "Dim WithEvents WE As Object", GetResource("WithEvents field"), GetResource("class"))) + End Sub + + + Friend Sub Field_Reorder_WithEvents_TypeLayout2() + Dim src1 = " +Imports System.Runtime.InteropServices + +Class C + Dim WithEvents WE1, WE2 As Object +End Class" + + Dim src2 = " +Imports System.Runtime.InteropServices + +Class C + Dim WithEvents WE2, WE1 As Object +End Class" + + Dim edits = GetTopEdits(src1, src2) + edits.VerifyEdits(EditKind.Reorder) + edits.VerifySemanticDiagnostics( + Diagnostic(RudeEditKind.InsertOrMoveTypeWithLayoutMember, "WE2", GetResource("WithEvents field"), GetResource("class"))) + End Sub + + + Public Sub Field_Reorder_Reloadable() + Dim src1 = ReloadableAttributeSrc & " + +Structure C + + Dim a = 0 + Dim b = 1 + Dim c +End Structure" + Dim src2 = ReloadableAttributeSrc & " + +Structure C + Dim c + Dim a = 0 + Dim b = 1 + +End Structure" + Dim edits = GetTopEdits(src1, src2) + + edits.VerifyEdits(EditKind.Reorder) + + edits.VerifySemantics( + {SemanticEdit(SemanticEditKind.Replace, Function(c) c.GetMember("C"))}, + capabilities:=EditAndContinueCapabilities.NewTypeDefinition) + End Sub + + + Public Sub EventField_Reorder() + Dim src1 = " +Class C + + Dim a As Integer = 0 + Dim b As Integer = 1 + Event c As Action +End Class" + Dim src2 = " +Class C + Event c As Action + Dim a As Integer = 0 + Dim b As Integer = 1 + +End Class" + Dim edits = GetTopEdits(src1, src2) + + edits.VerifyEdits(EditKind.Reorder) + + edits.VerifySemantics() + End Sub + Public Sub Field_VariableMove_TypeChange() Dim src1 = "Class C : Dim a As Object, b, c As Object : End Class" @@ -7824,29 +8077,6 @@ End Class Diagnostic(RudeEditKind.ModifiersUpdate, "Dim a As WE", GetResource("WithEvents field"))) End Sub - - Public Sub FieldReorder() - Dim src1 = "Class C : Dim a = 0 : Dim b = 1 : Dim c = 2 : End Class" - Dim src2 = "Class C : Dim c = 2 : Dim a = 0 : Dim b = 1 : End Class" - Dim edits = GetTopEdits(src1, src2) - - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.Move, "Dim c = 2", FeaturesResources.field)) - End Sub - - - Public Sub EventFieldReorder() - Dim src1 = "Class C : Dim a As Integer = 0 : Dim b As Integer = 1 : Event c As Action : End Class" - Dim src2 = "Class C : Event c As Action : Dim a As Integer = 0 : Dim b As Integer = 1 : End Class" - Dim edits = GetTopEdits(src1, src2) - - edits.VerifyEdits( - "Reorder [Event c As Action]@56 -> @10") - - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.Move, "Event c", FeaturesResources.event_)) - End Sub - Public Sub EventField_Partial_InsertDelete() Dim srcA1 = "Partial Class C : End Class" @@ -7874,7 +8104,7 @@ End Class End Sub - Public Sub FieldInsert_WithEvents1() + Public Sub Field_Insert_WithEvents() Dim src1 = "Class C : End Class" Dim src2 = "Class C : WithEvents F As C : End Class" Dim edits = GetTopEdits(src1, src2) @@ -7884,7 +8114,7 @@ End Class End Sub - Public Sub FieldInsert_WithEvents2() + Public Sub Field_Insert_WithEvents2() Dim src1 = "Class C : WithEvents F As C : End Class" Dim src2 = "Class C : WithEvents F, G As C : End Class" Dim edits = GetTopEdits(src1, src2) @@ -7894,7 +8124,7 @@ End Class End Sub - Public Sub FieldInsert_WithEvents3() + Public Sub Field_Insert_WithEvents3() Dim src1 = "Class C : WithEvents F As C : End Class" Dim src2 = "Class C : WithEvents F As C, G As C : End Class" Dim edits = GetTopEdits(src1, src2) @@ -7904,25 +8134,23 @@ End Class End Sub - Public Sub FieldInsert_IntoStruct() + Public Sub Field_Insert_IntoStruct() Dim src1 = "Structure S : Private a As Integer : End Structure" Dim src2 = " Structure S Private a As Integer Private b As Integer - Private Shared c As Integer Private Event d As System.Action End Structure " Dim edits = GetTopEdits(src1, src2) edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.InsertIntoStruct, "Private Event d", GetResource("event"), GetResource("structure")), - Diagnostic(RudeEditKind.InsertIntoStruct, "b As Integer", GetResource("field"), GetResource("structure")), - Diagnostic(RudeEditKind.InsertIntoStruct, "c As Integer", GetResource("field"), GetResource("structure"))) + Diagnostic(RudeEditKind.InsertOrMoveStructMember, "Private Event d", GetResource("event"), GetResource("structure")), + Diagnostic(RudeEditKind.InsertOrMoveStructMember, "b As Integer", GetResource("field"), GetResource("structure"))) End Sub - Public Sub FieldInsert_IntoLayoutClass_Auto() + Public Sub Field_Insert_IntoLayoutClass_Auto() Dim src1 = " Imports System.Runtime.InteropServices @@ -7983,9 +8211,9 @@ End Class Dim edits = GetTopEdits(src1, src2) edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "b As Integer", FeaturesResources.field, FeaturesResources.class_), - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "c As Integer", FeaturesResources.field, FeaturesResources.class_), - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "d As Integer", FeaturesResources.field, FeaturesResources.class_)) + Diagnostic(RudeEditKind.InsertOrMoveTypeWithLayoutMember, "b As Integer", GetResource("field"), GetResource("class")), + Diagnostic(RudeEditKind.InsertOrMoveTypeWithLayoutMember, "c As Integer", GetResource("field"), GetResource("class")), + Diagnostic(RudeEditKind.InsertOrMoveTypeWithLayoutMember, "d As Integer", GetResource("field"), GetResource("class"))) End Sub @@ -8013,9 +8241,9 @@ End Class Dim edits = GetTopEdits(src1, src2) edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "b As Integer", FeaturesResources.field, FeaturesResources.class_), - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "c As Integer", FeaturesResources.field, FeaturesResources.class_), - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "d As Integer", FeaturesResources.field, FeaturesResources.class_)) + Diagnostic(RudeEditKind.InsertOrMoveTypeWithLayoutMember, "b As Integer", GetResource("field"), GetResource("class")), + Diagnostic(RudeEditKind.InsertOrMoveTypeWithLayoutMember, "c As Integer", GetResource("field"), GetResource("class")), + Diagnostic(RudeEditKind.InsertOrMoveTypeWithLayoutMember, "d As Integer", GetResource("field"), GetResource("class"))) End Sub @@ -8047,7 +8275,7 @@ End Class ' TODO: We don't compare the ordering currently. We could allow this edit if the ordering is preserved. edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "b As Integer", FeaturesResources.field, FeaturesResources.class_)) + Diagnostic(RudeEditKind.InsertOrMoveTypeWithLayoutMember, "b As Integer", FeaturesResources.field, FeaturesResources.class_)) End Sub @@ -8077,7 +8305,7 @@ End Class Dim edits = GetTopEdits(src1, src2) edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "a As Integer", FeaturesResources.field, FeaturesResources.class_)) + Diagnostic(RudeEditKind.InsertOrMoveTypeWithLayoutMember, "a As Integer", FeaturesResources.field, FeaturesResources.class_)) End Sub @@ -8348,36 +8576,173 @@ End Class End Sub - Public Sub PropertyReorder1() - Dim src1 = "Class C : ReadOnly Property P" & vbLf & "Get" & vbLf & "Return 1 : End Get : End Property : " & - "ReadOnly Property Q" & vbLf & "Get" & vbLf & "Return 1 : End Get : End Property : End Class" - Dim src2 = "Class C : ReadOnly Property Q" & vbLf & "Get" & vbLf & "Return 1 : End Get : End Property : " & - "ReadOnly Property P" & vbLf & "Get" & vbLf & "Return 1 : End Get : End Property : End Class" + Public Sub Property_Reorder1() + Dim src1 = " +Class C + ReadOnly Property P + Get + Return 1 + End Get + End Property + ReadOnly Property Q + Get + Return 1 + End Get + End Property +End Class" + Dim src2 = " +Class C + ReadOnly Property Q + Get + Return 1 + End Get + End Property + ReadOnly Property P + Get + Return 1 + End Get + End Property +End Class" Dim edits = GetTopEdits(src1, src2) + edits.VerifyEdits(EditKind.Reorder) + edits.VerifySemantics() + End Sub - edits.VerifyEdits( - "Reorder [ReadOnly Property Q" & vbLf & "Get" & vbLf & "Return 1 : End Get : End Property]@70 -> @10") + + Public Sub Property_Reorder_Auto() + Dim src1 = " +Class C - edits.VerifySemanticDiagnostics() + Property P As Integer = 0 + Property Q As Integer = 1 + Property R As Integer +End Class" + Dim src2 = " +Class C + Property R As Integer + Property P As Integer = 0 + Property Q As Integer = 1 + +End Class" + + Dim edits = GetTopEdits(src1, src2) + edits.VerifyEdits(EditKind.Reorder) + edits.VerifySemantics() End Sub - Public Sub PropertyReorder2() - Dim src1 = "Class C : Property P As Integer : Property Q As Integer : End Class" - Dim src2 = "Class C : Property Q As Integer : Property P As Integer : End Class" + Public Sub Property_Reorder_Auto_WithInitializer() + Dim src1 = " +Class C + + Property P As Integer = 0 + Property Q As Integer = 1 + Property R As Integer = 2 +End Class" + Dim src2 = " +Class C + Property R As Integer = 2 + Property P As Integer = 0 + Property Q As Integer = 1 + +End Class" Dim edits = GetTopEdits(src1, src2) + edits.VerifyEdits(EditKind.Reorder) + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember(Of NamedTypeSymbol)("C").InstanceConstructors.Single(), preserveLocalVariables:=True)) + End Sub - edits.VerifyEdits( - "Reorder [Property Q As Integer]@34 -> @10") + + + ", "Class")> + Public Sub Property_Reorder_TypeLayout(attribute As String, keyword As String) + Dim src1 = attribute & keyword & " C + ReadOnly Property Q + Get + Return 1 + End Get + End Property + ReadOnly Property P + Get + Return 1 + End Get + End Property +End " & keyword + + Dim src2 = attribute & keyword & " C + ReadOnly Property P + Get + Return 1 + End Get + End Property + ReadOnly Property Q + Get + Return 1 + End Get + End Property +End " & keyword + + Dim edits = GetTopEdits(src1, src2) + edits.VerifyEdits(EditKind.Reorder) + edits.VerifySemantics() + End Sub + + + + ", "Class", RudeEditKind.InsertOrMoveTypeWithLayoutMember)> + Friend Sub Property_Reorder_Auto_TypeLayout(attribute As String, keyword As String, rudeEditKind As RudeEditKind) + Dim src1 = attribute & keyword & " C + + Property P As Integer = 0 + Property Q As Integer = 1 + Property R As Integer = 2 +End " & keyword + + Dim src2 = attribute & keyword & " C + Property R As Integer = 2 + Property P As Integer = 0 + Property Q As Integer = 1 + +End " & keyword + + Dim edits = GetTopEdits(src1, src2) + edits.VerifyEdits(EditKind.Reorder) edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.Move, "Property Q", FeaturesResources.auto_property)) + Diagnostic(rudeEditKind, "Property R", GetResource("auto-property"), GetResource(keyword))) End Sub - Public Sub PropertyAccessorReorder() + Friend Sub Property_Reorder_Auto_Reloadable() + Dim src1 = ReloadableAttributeSrc & " + +Structure C + Property P As Integer = 0 + Property Q As Integer = 1 + Property R As Integer +End Structure" + + Dim src2 = ReloadableAttributeSrc & " + +Structure C + Property R As Integer + Property P As Integer = 0 + Property Q As Integer = 1 + +End Structure" + + Dim edits = GetTopEdits(src1, src2) + edits.VerifyEdits(EditKind.Reorder) + + edits.VerifySemantics( + {SemanticEdit(SemanticEditKind.Replace, Function(c) c.GetMember(Of NamedTypeSymbol)("C"))}, + capabilities:=EditAndContinueCapabilities.NewTypeDefinition) + End Sub + + + Public Sub PropertyAccessor_Reorder() Dim src1 = "Class C : Property P As Integer" & vbLf & "Get" & vbLf & "Return 1 : End Get" & vbLf & "Set : End Set : End Property : End Class" Dim src2 = "Class C : Property P As Integer" & vbLf & "Set : End Set" & vbLf & "Get" & vbLf & "Return 1 : End Get : End Property : End Class" Dim edits = GetTopEdits(src1, src2) @@ -8389,7 +8754,7 @@ End Class End Sub - Public Sub PropertyTypeUpdate() + Public Sub Property_Update_Type() Dim src1 = "Class C : Property P As Integer : End Class" Dim src2 = "Class C : Property P As Char : End Class" Dim edits = GetTopEdits(src1, src2) @@ -8411,7 +8776,7 @@ End Class End Sub - Public Sub PropertyInsert() + Public Sub Property_Insert() Dim src1 = "Class C : End Class" Dim src2 = " Class C @@ -8572,7 +8937,7 @@ End Class" End Sub - Public Sub PropertyRename1() + Public Sub Property_Rename1() Dim src1 = "Class C : ReadOnly Property P As Integer" & vbLf & "Get : End Get : End Property : End Class" Dim src2 = "Class C : ReadOnly Property Q As Integer" & vbLf & "Get : End Get : End Property : End Class" Dim edits = GetTopEdits(src1, src2) @@ -8592,7 +8957,7 @@ End Class" End Sub - Public Sub PropertyRename2() + Public Sub Property_Rename2() Dim src1 = "Class C : ReadOnly Property P As Integer : End Class" Dim src2 = "Class C : ReadOnly Property Q As Integer : End Class" Dim edits = GetTopEdits(src1, src2) @@ -8611,14 +8976,15 @@ End Class" capabilities:=EditAndContinueCapabilities.AddMethodToExistingType Or EditAndContinueCapabilities.AddInstanceFieldToExistingType) End Sub - - Public Sub PropertyInsert_IntoStruct() - Dim src1 = "Structure S : Private a As Integer : End Structure" - Dim src2 = " -Structure S - Private a As Integer + + + ", "Class", RudeEditKind.InsertOrMoveTypeWithLayoutMember)> + Friend Sub Property_Insert_TypeLayout(attribute As String, type As String, rudeEditKind As RudeEditKind) + Dim src1 = attribute & type & " S +End " & type + + Dim src2 = attribute & type & " S Private Property b As Integer - Private Shared Property c As Integer Private Property d As Integer Get @@ -8629,15 +8995,6 @@ Structure S End Set End Property - Private Shared Property e As Integer - Get - Return 0 - End Get - - Set - End Set - End Property - Private ReadOnly Property f As Integer Get Return 0 @@ -8648,46 +9005,24 @@ Structure S Set End Set End Property - - Private Shared ReadOnly Property h As Integer - Get - Return 0 - End Get - End Property - - Private Shared WriteOnly Property i As Integer - Set - End Set - End Property -End Structure" +End " & type Dim edits = GetTopEdits(src1, src2) edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.InsertIntoStruct, "Private Property b", GetResource("auto-property"), GetResource("structure")), - Diagnostic(RudeEditKind.InsertIntoStruct, "Private Shared Property c", GetResource("auto-property"), GetResource("structure"))) + Diagnostic(rudeEditKind, "Private Property b", GetResource("auto-property"), GetResource(type))) End Sub - - Public Sub PropertyInsert_IntoLayoutClass_Sequential() - Dim src1 = " -Imports System.Runtime.InteropServices - - -Class C - Private a As Integer -End Class -" - - Dim src2 = " -Imports System.Runtime.InteropServices + + + ", "Class", RudeEditKind.InsertOrMoveTypeWithLayoutMember)> + Friend Sub Property_Insert_TypeLayout_Shared(attribute As String, type As String, rudeEditKind As RudeEditKind) + Dim src1 = attribute & type & " S +End " & type - -Class C - Private a As Integer - Private Property b As Integer + Dim src2 = attribute & type & " S Private Shared Property c As Integer - Private Property d As Integer + Private Shared Property e As Integer Get Return 0 End Get @@ -8696,20 +9031,22 @@ Class C End Set End Property - Private Shared Property e As Integer + Private Shared ReadOnly Property h As Integer Get Return 0 End Get + End Property + Private Shared WriteOnly Property i As Integer Set End Set End Property -End Class -" +End " & type Dim edits = GetTopEdits(src1, src2) + edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "Private Property b", GetResource("auto-property"), GetResource("class")), - Diagnostic(RudeEditKind.InsertIntoClassWithLayout, "Private Shared Property c", GetResource("auto-property"), GetResource("class"))) + {Diagnostic(rudeEditKind, "Private Shared Property c", GetResource("auto-property"), GetResource(type))}, + capabilities:=EditAndContinueCapabilities.AddMethodToExistingType Or EditAndContinueCapabilities.AddStaticFieldToExistingType) End Sub @@ -9637,7 +9974,7 @@ End Class - Public Sub Field_Insert(modifiers As String) + Public Sub Field_Insert_Accessibility(modifiers As String) Dim src1 = "Class C : End Class" Dim src2 = "Class C : " & modifiers & " a As Integer = 1 : End Class" Dim edits = GetTopEdits(src1, src2) @@ -9658,7 +9995,7 @@ End Class - Public Sub Property_Insert(accessibility As String) + Public Sub Property_Insert_Accessibility(accessibility As String) Dim src1 = "Class C : End Class" Dim src2 = "Class C : " & accessibility & " Property a As Integer = 1 : End Class" Dim edits = GetTopEdits(src1, src2)