From fa5a5bbfc024f0b45a73964f9587d54e28687f30 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Fri, 14 May 2021 10:08:56 +1000 Subject: [PATCH] EnC - Support record structs (#52989) --- .../CSharpEditAndContinueAnalyzerTests.cs | 3 + .../EditAndContinue/TopLevelEditingTests.cs | 87 ++++++++++++++++++- .../Portable/CSharpFeaturesResources.resx | 3 + .../CSharpEditAndContinueAnalyzer.cs | 11 ++- .../EditAndContinue/SyntaxComparer.cs | 4 +- .../xlf/CSharpFeaturesResources.cs.xlf | 5 ++ .../xlf/CSharpFeaturesResources.de.xlf | 5 ++ .../xlf/CSharpFeaturesResources.es.xlf | 5 ++ .../xlf/CSharpFeaturesResources.fr.xlf | 5 ++ .../xlf/CSharpFeaturesResources.it.xlf | 5 ++ .../xlf/CSharpFeaturesResources.ja.xlf | 5 ++ .../xlf/CSharpFeaturesResources.ko.xlf | 5 ++ .../xlf/CSharpFeaturesResources.pl.xlf | 5 ++ .../xlf/CSharpFeaturesResources.pt-BR.xlf | 5 ++ .../xlf/CSharpFeaturesResources.ru.xlf | 5 ++ .../xlf/CSharpFeaturesResources.tr.xlf | 5 ++ .../xlf/CSharpFeaturesResources.zh-Hans.xlf | 5 ++ .../xlf/CSharpFeaturesResources.zh-Hant.xlf | 5 ++ 18 files changed, 169 insertions(+), 4 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/CSharpEditAndContinueAnalyzerTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/CSharpEditAndContinueAnalyzerTests.cs index c9170321bc2cf..4bcaf73ea5dd3 100644 --- a/src/EditorFeatures/CSharpTest/EditAndContinue/CSharpEditAndContinueAnalyzerTests.cs +++ b/src/EditorFeatures/CSharpTest/EditAndContinue/CSharpEditAndContinueAnalyzerTests.cs @@ -126,6 +126,9 @@ public void ErrorSpans_TopLevel() [A, B] /**/public abstract partial record R/**/ { } +[A, B] +/**/public abstract partial record struct R/**/ { } + /**/interface I/**/ : J, K, L { } [A] diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/TopLevelEditingTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/TopLevelEditingTests.cs index 93b7da92cc7da..b33641df6a7cd 100644 --- a/src/EditorFeatures/CSharpTest/EditAndContinue/TopLevelEditingTests.cs +++ b/src/EditorFeatures/CSharpTest/EditAndContinue/TopLevelEditingTests.cs @@ -587,6 +587,21 @@ public void TypeKindUpdate2() Diagnostic(RudeEditKind.TypeKindUpdate, "record C", CSharpFeaturesResources.record_)); } + [Fact] + public void TypeKindUpdate3() + { + var src1 = "record C { }"; + var src2 = "record struct C { }"; + + var edits = GetTopEdits(src1, src2); + + edits.VerifyEdits( + "Update [record C { }]@0 -> [record struct C { }]@0"); + + edits.VerifyRudeDiagnostics( + Diagnostic(RudeEditKind.TypeKindUpdate, "record struct C", CSharpFeaturesResources.record_struct)); + } + [Fact] public void Class_Modifiers_Update() { @@ -1693,6 +1708,55 @@ public void Record_Name_Update() Diagnostic(RudeEditKind.Renamed, "record D", CSharpFeaturesResources.record_)); } + [Fact] + public void RecordStruct_NoModifiers_Insert() + { + var src1 = ""; + var src2 = "record struct C { }"; + + var edits = GetTopEdits(src1, src2); + + edits.VerifyRudeDiagnostics(); + } + + [Fact] + public void RecordStruct_AddField() + { + var src1 = @" +record struct C(int X) +{ +}"; + var src2 = @" +record struct C(int X) +{ + private int _y = 0; +}"; + + var edits = GetTopEdits(src1, src2); + + edits.VerifySemanticDiagnostics( + Diagnostic(RudeEditKind.InsertIntoStruct, "_y = 0", FeaturesResources.field, CSharpFeaturesResources.record_struct)); + } + + [Fact] + public void RecordStruct_AddProperty() + { + var src1 = @" +record struct C(int X) +{ +}"; + var src2 = @" +record struct C(int X) +{ + public int Y { get; set; } = 0; +}"; + + var edits = GetTopEdits(src1, src2); + + edits.VerifySemanticDiagnostics( + Diagnostic(RudeEditKind.InsertIntoStruct, "public int Y { get; set; } = 0;", FeaturesResources.auto_property, CSharpFeaturesResources.record_struct)); + } + [Fact] public void Record_NoModifiers_Insert() { @@ -1824,7 +1888,28 @@ public void Record_ImplementSynthesized_PrintMembers() var src2 = @" record C { - protected virtual bool PrintMembers(System.Text.StringBuilder builder) + protected bool PrintMembers(System.Text.StringBuilder builder) + { + return true; + } +}"; + + var edits = GetTopEdits(src1, src2); + + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers"))); + + edits.VerifyRudeDiagnostics(); + } + + [Fact] + public void RecordStruct_ImplementSynthesized_PrintMembers() + { + var src1 = "record struct C { }"; + var src2 = @" +record struct C +{ + private bool PrintMembers(System.Text.StringBuilder builder) { return true; } diff --git a/src/Features/CSharp/Portable/CSharpFeaturesResources.resx b/src/Features/CSharp/Portable/CSharpFeaturesResources.resx index 019ca0f85ca72..209f102173c6c 100644 --- a/src/Features/CSharp/Portable/CSharpFeaturesResources.resx +++ b/src/Features/CSharp/Portable/CSharpFeaturesResources.resx @@ -621,4 +621,7 @@ record + + record struct + \ No newline at end of file diff --git a/src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs b/src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs index 3e3553ca8018d..ffac8f47f627a 100644 --- a/src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs +++ b/src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs @@ -1100,7 +1100,7 @@ internal override bool IsInterfaceDeclaration(SyntaxNode node) => node.IsKind(SyntaxKind.InterfaceDeclaration); internal override bool IsRecordDeclaration(SyntaxNode node) - => node.IsKind(SyntaxKind.RecordDeclaration); + => node.IsKind(SyntaxKind.RecordDeclaration, SyntaxKind.RecordStructDeclaration); internal override SyntaxNode? TryGetContainingTypeDeclaration(SyntaxNode node) => node.Parent!.FirstAncestorOrSelf(); @@ -1426,6 +1426,7 @@ private static bool GroupBySignatureComparer(ImmutableArray ol case SyntaxKind.StructDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.RecordDeclaration: + case SyntaxKind.RecordStructDeclaration: var typeDeclaration = (TypeDeclarationSyntax)node; return GetDiagnosticSpan(typeDeclaration.Modifiers, typeDeclaration.Keyword, typeDeclaration.TypeParameterList ?? (SyntaxNodeOrToken)typeDeclaration.Identifier); @@ -1777,6 +1778,9 @@ internal override TextSpan GetLambdaParameterDiagnosticSpan(SyntaxNode lambda, i case SyntaxKind.RecordDeclaration: return CSharpFeaturesResources.record_; + case SyntaxKind.RecordStructDeclaration: + return CSharpFeaturesResources.record_struct; + case SyntaxKind.EnumDeclaration: return FeaturesResources.enum_; @@ -2136,6 +2140,7 @@ private void ClassifyReorder(SyntaxNode newNode) case SyntaxKind.StructDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.RecordDeclaration: + case SyntaxKind.RecordStructDeclaration: case SyntaxKind.EnumDeclaration: case SyntaxKind.DelegateDeclaration: case SyntaxKind.VariableDeclaration: @@ -2209,6 +2214,7 @@ private void ClassifyInsert(SyntaxNode node) case SyntaxKind.ClassDeclaration: case SyntaxKind.StructDeclaration: case SyntaxKind.RecordDeclaration: + case SyntaxKind.RecordStructDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.EnumDeclaration: case SyntaxKind.DelegateDeclaration: @@ -2299,6 +2305,7 @@ private void ClassifyDelete(SyntaxNode oldNode) case SyntaxKind.StructDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.RecordDeclaration: + case SyntaxKind.RecordStructDeclaration: case SyntaxKind.MethodDeclaration: case SyntaxKind.PropertyDeclaration: case SyntaxKind.IndexerDeclaration: @@ -2387,6 +2394,7 @@ private void ClassifyUpdate(SyntaxNode oldNode, SyntaxNode newNode) case SyntaxKind.StructDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.RecordDeclaration: + case SyntaxKind.RecordStructDeclaration: ClassifyUpdate((TypeDeclarationSyntax)oldNode, (TypeDeclarationSyntax)newNode); return; @@ -3183,6 +3191,7 @@ protected override List GetExceptionHandlingAncestors(SyntaxNode nod case SyntaxKind.ClassDeclaration: case SyntaxKind.StructDeclaration: case SyntaxKind.RecordDeclaration: + case SyntaxKind.RecordStructDeclaration: return result; } diff --git a/src/Features/CSharp/Portable/EditAndContinue/SyntaxComparer.cs b/src/Features/CSharp/Portable/EditAndContinue/SyntaxComparer.cs index de9ae560a58f4..11a4bfd82d71f 100644 --- a/src/Features/CSharp/Portable/EditAndContinue/SyntaxComparer.cs +++ b/src/Features/CSharp/Portable/EditAndContinue/SyntaxComparer.cs @@ -563,11 +563,11 @@ private static Label ClassifyTopSyntax(SyntaxKind kind, out bool isLeaf) case SyntaxKind.NamespaceDeclaration: return Label.NamespaceDeclaration; - // Need to add support for record structs (tracked by https://github.com/dotnet/roslyn/issues/44877) case SyntaxKind.ClassDeclaration: case SyntaxKind.StructDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.RecordDeclaration: + case SyntaxKind.RecordStructDeclaration: return Label.TypeDeclaration; case SyntaxKind.MethodDeclaration: @@ -1343,11 +1343,11 @@ private static double CombineOptional( case SyntaxKind.NamespaceDeclaration: return ((NamespaceDeclarationSyntax)node).Name; - // Need to add support for record structs (tracked by https://github.com/dotnet/roslyn/issues/44877) case SyntaxKind.ClassDeclaration: case SyntaxKind.StructDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.RecordDeclaration: + case SyntaxKind.RecordStructDeclaration: return ((TypeDeclarationSyntax)node).Identifier; case SyntaxKind.EnumDeclaration: diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf index c2a819d8bc8f8..cb3924c998502 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf @@ -417,6 +417,11 @@ record + + record struct + record struct + + switch statement příkaz switch diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.de.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.de.xlf index 4b95649bede12..362e6013d5ec6 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.de.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.de.xlf @@ -417,6 +417,11 @@ record + + record struct + record struct + + switch statement switch-Anweisung diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.es.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.es.xlf index f775b17afcf35..8ba4b0bbcd0fe 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.es.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.es.xlf @@ -417,6 +417,11 @@ record + + record struct + record struct + + switch statement instrucción switch diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf index 4c5916b74e553..7b0fd88ccbc97 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf @@ -417,6 +417,11 @@ record + + record struct + record struct + + switch statement instruction switch diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.it.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.it.xlf index 94688d112ab3a..db03039583bab 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.it.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.it.xlf @@ -417,6 +417,11 @@ record + + record struct + record struct + + switch statement istruzione switch diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf index 70ac45620b7f1..2055d9cd7312b 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf @@ -417,6 +417,11 @@ record + + record struct + record struct + + switch statement switch ステートメント diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ko.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ko.xlf index f8f5c44cd8f87..c01f7065707ef 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ko.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ko.xlf @@ -417,6 +417,11 @@ record + + record struct + record struct + + switch statement switch 문 diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf index f98de496503d0..ce0387fd1d2b9 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf @@ -417,6 +417,11 @@ record + + record struct + record struct + + switch statement instrukcja switch diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf index 8a1031efa4b6a..e315e6cfbe6c7 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf @@ -417,6 +417,11 @@ record + + record struct + record struct + + switch statement instrução switch diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf index c6846379a30d8..1266be34a1002 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf @@ -417,6 +417,11 @@ record + + record struct + record struct + + switch statement оператор switch diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf index a8901cab24888..8ed1229424eb5 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf @@ -417,6 +417,11 @@ record + + record struct + record struct + + switch statement switch deyimi diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hans.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hans.xlf index d0dcc2b43c5da..feda06d416e22 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hans.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hans.xlf @@ -417,6 +417,11 @@ record + + record struct + record struct + + switch statement switch 语句 diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf index 43be8381fa6dd..8107ba89eefa3 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf @@ -417,6 +417,11 @@ record + + record struct + record struct + + switch statement switch 陳述式