Skip to content

Commit

Permalink
Compare arrow expression clauses when they are children of properties…
Browse files Browse the repository at this point in the history
… or indexers (#57624)
  • Loading branch information
davidwengier authored Nov 9, 2021
1 parent 196e953 commit 8cfddbf
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,29 @@ class C
Diagnostic(RudeEditKind.DeleteActiveStatement, "get", FeaturesResources.code));
}

[Fact]
public void Property_ExpressionBody_NonLeaf()
{
var src1 = @"
class C
{
int P => <AS:1>M()</AS:1>;
int M() { <AS:0>return 1;</AS:0> }
}
";
var src2 = @"
class C
{
int P => <AS:1>M()</AS:1>;
int M() { <AS:0>return 2;</AS:0> }
}
";
var edits = GetTopEdits(src1, src2);
var active = GetActiveStatements(src1, src2);

edits.VerifyRudeDiagnostics(active);
}

[Fact]
public void Property_BlockBodyToExpressionBody1()
{
Expand Down Expand Up @@ -664,6 +687,29 @@ public void Indexer_BlockBodyToExpressionBody2()
Diagnostic(RudeEditKind.Delete, "int this[int a]", DeletedSymbolDisplay(CSharpFeaturesResources.indexer_setter, "this[int a].set")));
}

[Fact]
public void Indexer_ExpressionBody_NonLeaf()
{
var src1 = @"
class C
{
int this[int index] => <AS:1>M()</AS:1>;
int M() { <AS:0>return 1;</AS:0> }
}
";
var src2 = @"
class C
{
int this[int index] => <AS:1>M()</AS:1>;
int M() { <AS:0>return 2;</AS:0> }
}
";
var edits = GetTopEdits(src1, src2);
var active = GetActiveStatements(src1, src2);

edits.VerifyRudeDiagnostics(active);
}

[Fact]
public void Update_Leaf_Indexers1()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12601,7 +12601,9 @@ public void Property_ExpressionBody_Update()

var edits = GetTopEdits(src1, src2);

edits.VerifyEdits("Update [int P => 1;]@10 -> [int P => 2;]@10");
edits.VerifyEdits(
"Update [int P => 1;]@10 -> [int P => 2;]@10",
"Update [=> 1]@16 -> [=> 2]@16");

edits.VerifySemantics(ActiveStatementsDescription.Empty, new[]
{
Expand Down Expand Up @@ -12633,7 +12635,8 @@ public void Property_ExpressionBodyToBlockBody1()
edits.VerifyEdits(
"Update [int P => 1;]@10 -> [int P { get { return 2; } }]@10",
"Insert [{ get { return 2; } }]@16",
"Insert [get { return 2; }]@18");
"Insert [get { return 2; }]@18",
"Delete [=> 1]@16");

edits.VerifySemantics(ActiveStatementsDescription.Empty, new[]
{
Expand All @@ -12653,7 +12656,8 @@ public void Property_ExpressionBodyToBlockBody2()
"Update [int P => 1;]@10 -> [int P { get { return 2; } set { } }]@10",
"Insert [{ get { return 2; } set { } }]@16",
"Insert [get { return 2; }]@18",
"Insert [set { }]@36");
"Insert [set { }]@36",
"Delete [=> 1]@16");

edits.VerifySemantics(ActiveStatementsDescription.Empty, new[]
{
Expand All @@ -12672,6 +12676,7 @@ public void Property_BlockBodyToExpressionBody1()

edits.VerifyEdits(
"Update [int P { get { return 2; } }]@10 -> [int P => 1;]@10",
"Insert [=> 1]@16",
"Delete [{ get { return 2; } }]@16",
"Delete [get { return 2; }]@18");

Expand All @@ -12691,6 +12696,7 @@ public void Property_BlockBodyToExpressionBody2()

edits.VerifyEdits(
"Update [int P { get { return 2; } set { } }]@10 -> [int P => 1;]@10",
"Insert [=> 1]@16",
"Delete [{ get { return 2; } set { } }]@16",
"Delete [get { return 2; }]@18",
"Delete [set { }]@36");
Expand All @@ -12709,7 +12715,8 @@ public void Property_ExpressionBodyToGetterExpressionBody()
edits.VerifyEdits(
"Update [int P => 1;]@10 -> [int P { get => 2; }]@10",
"Insert [{ get => 2; }]@16",
"Insert [get => 2;]@18");
"Insert [get => 2;]@18",
"Delete [=> 1]@16");

edits.VerifySemantics(ActiveStatementsDescription.Empty, new[]
{
Expand All @@ -12726,6 +12733,7 @@ public void Property_GetterExpressionBodyToExpressionBody()
var edits = GetTopEdits(src1, src2);
edits.VerifyEdits(
"Update [int P { get => 2; }]@10 -> [int P => 1;]@10",
"Insert [=> 1]@16",
"Delete [{ get => 2; }]@16",
"Delete [get => 2;]@18");

Expand Down Expand Up @@ -13697,7 +13705,8 @@ public void IndexerWithExpressionBody_Update()
var edits = GetTopEdits(src1, src2);

edits.VerifyEdits(
"Update [int this[int a] => 1;]@10 -> [int this[int a] => 2;]@10");
"Update [int this[int a] => 1;]@10 -> [int this[int a] => 2;]@10",
"Update [=> 1]@26 -> [=> 2]@26");

edits.VerifySemantics(ActiveStatementsDescription.Empty, new[]
{
Expand Down Expand Up @@ -13727,7 +13736,8 @@ class C
var edits = GetTopEdits(src1, src2);

edits.VerifyEdits(
"Update [int this[int a] => new Func<int>(() => a + 1)() + 10;]@35 -> [int this[int a] => new Func<int>(() => 2)() + 11;]@35");
"Update [int this[int a] => new Func<int>(() => a + 1)() + 10;]@35 -> [int this[int a] => new Func<int>(() => 2)() + 11;]@35",
"Update [=> new Func<int>(() => a + 1)() + 10]@51 -> [=> new Func<int>(() => 2)() + 11]@51");

edits.VerifyRudeDiagnostics(
Diagnostic(RudeEditKind.NotCapturingVariable, "a", "a"));
Expand Down Expand Up @@ -13755,7 +13765,8 @@ class C
var edits = GetTopEdits(src1, src2);

edits.VerifyEdits(
"Update [int this[int a] => new Func<int>(() => a + 1)();]@35 -> [int this[int a] => new Func<int>(() => 2)();]@35");
"Update [int this[int a] => new Func<int>(() => a + 1)();]@35 -> [int this[int a] => new Func<int>(() => 2)();]@35",
"Update [=> new Func<int>(() => a + 1)()]@51 -> [=> new Func<int>(() => 2)()]@51");

edits.VerifyRudeDiagnostics(
Diagnostic(RudeEditKind.NotCapturingVariable, "a", "a"));
Expand Down Expand Up @@ -13783,7 +13794,8 @@ class C
var edits = GetTopEdits(src1, src2);

edits.VerifyEdits(
"Update [int this[int a] => new Func<int>(() => { return a + 1; })();]@35 -> [int this[int a] => new Func<int>(() => { return 2; })();]@35");
"Update [int this[int a] => new Func<int>(() => { return a + 1; })();]@35 -> [int this[int a] => new Func<int>(() => { return 2; })();]@35",
"Update [=> new Func<int>(() => { return a + 1; })()]@51 -> [=> new Func<int>(() => { return 2; })()]@51");

edits.VerifyRudeDiagnostics(
Diagnostic(RudeEditKind.NotCapturingVariable, "a", "a"));
Expand Down Expand Up @@ -13811,7 +13823,8 @@ class C
var edits = GetTopEdits(src1, src2);

edits.VerifyEdits(
"Update [int this[int a] => new Func<int>(delegate { return a + 1; })();]@35 -> [int this[int a] => new Func<int>(delegate { return 2; })();]@35");
"Update [int this[int a] => new Func<int>(delegate { return a + 1; })();]@35 -> [int this[int a] => new Func<int>(delegate { return 2; })();]@35",
"Update [=> new Func<int>(delegate { return a + 1; })()]@51 -> [=> new Func<int>(delegate { return 2; })()]@51");

edits.VerifyRudeDiagnostics(
Diagnostic(RudeEditKind.NotCapturingVariable, "a", "a"));
Expand All @@ -13828,7 +13841,8 @@ public void Indexer_ExpressionBodyToBlockBody()
edits.VerifyEdits(
"Update [int this[int a] => 1;]@10 -> [int this[int a] { get { return 1; } }]@10",
"Insert [{ get { return 1; } }]@26",
"Insert [get { return 1; }]@28");
"Insert [get { return 1; }]@28",
"Delete [=> 1]@26");

edits.VerifySemantics(ActiveStatementsDescription.Empty, new[]
{
Expand All @@ -13846,6 +13860,7 @@ public void Indexer_BlockBodyToExpressionBody()

edits.VerifyEdits(
"Update [int this[int a] { get { return 1; } }]@10 -> [int this[int a] => 1;]@10",
"Insert [=> 1]@26",
"Delete [{ get { return 1; } }]@26",
"Delete [get { return 1; }]@28");

Expand Down Expand Up @@ -13892,6 +13907,7 @@ public void Indexer_GetterExpressionBodyToExpressionBody()

edits.VerifyEdits(
"Update [int this[int a] { get => 1; }]@10 -> [int this[int a] => 1;]@10",
"Insert [=> 1]@26",
"Delete [{ get => 1; }]@26",
"Delete [get => 1;]@28");

Expand All @@ -13911,7 +13927,8 @@ public void Indexer_ExpressionBodyToGetterExpressionBody()
edits.VerifyEdits(
"Update [int this[int a] => 1;]@10 -> [int this[int a] { get => 1; }]@10",
"Insert [{ get => 1; }]@26",
"Insert [get => 1;]@28");
"Insert [get => 1;]@28",
"Delete [=> 1]@26");

edits.VerifySemantics(ActiveStatementsDescription.Empty, new[]
{
Expand Down Expand Up @@ -13995,6 +14012,7 @@ public void Indexer_GetterAndSetterBlockBodiesToExpressionBody()

edits.VerifyEdits(
"Update [int this[int a] { get { return 1; } set { Console.WriteLine(0); } }]@10 -> [int this[int a] => 1;]@10",
"Insert [=> 1]@26",
"Delete [{ get { return 1; } set { Console.WriteLine(0); } }]@26",
"Delete [get { return 1; }]@28",
"Delete [set { Console.WriteLine(0); }]@46");
Expand All @@ -14015,7 +14033,8 @@ public void Indexer_ExpressionBodyToGetterAndSetterBlockBodies()
"Update [int this[int a] => 1;]@10 -> [int this[int a] { get { return 1; } set { Console.WriteLine(0); } }]@10",
"Insert [{ get { return 1; } set { Console.WriteLine(0); } }]@26",
"Insert [get { return 1; }]@28",
"Insert [set { Console.WriteLine(0); }]@46");
"Insert [set { Console.WriteLine(0); }]@46",
"Delete [=> 1]@26");

edits.VerifySemantics(ActiveStatementsDescription.Empty, new[]
{
Expand Down Expand Up @@ -14297,6 +14316,7 @@ public void Indexer_ReadOnlyRef_Parameter_InsertWhole()
edits.VerifyEdits(
"Insert [int this[in int i] => throw null;]@13",
"Insert [[in int i]]@21",
"Insert [=> throw null]@32",
"Insert [in int i]@22");

edits.VerifyRudeDiagnostics();
Expand Down Expand Up @@ -14328,6 +14348,7 @@ public void Indexer_ReadOnlyRef_ReturnType_Insert()
edits.VerifyEdits(
"Insert [ref readonly int this[int i] => throw null;]@13",
"Insert [[int i]]@34",
"Insert [=> throw null]@42",
"Insert [int i]@35");

edits.VerifyRudeDiagnostics();
Expand Down
11 changes: 11 additions & 0 deletions src/Features/CSharp/Portable/EditAndContinue/SyntaxComparer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ internal enum Label
IndexerDeclaration, // tied to parent
EventDeclaration, // tied to parent
EnumMemberDeclaration, // tied to parent
ArrowExpressionClause, // tied to parent

AccessorList, // tied to parent
AccessorDeclaration, // tied to parent
Expand Down Expand Up @@ -177,6 +178,7 @@ private static int TiedToAncestor(Label label)
case Label.ConstructorDeclaration:
case Label.DestructorDeclaration:
case Label.PropertyDeclaration:
case Label.ArrowExpressionClause:
case Label.IndexerDeclaration:
case Label.EventDeclaration:
case Label.EnumMemberDeclaration:
Expand Down Expand Up @@ -605,6 +607,12 @@ private static Label ClassifyTopSyntax(SyntaxKind kind, SyntaxNode? node, out bo
case SyntaxKind.IndexerDeclaration:
return Label.IndexerDeclaration;

case SyntaxKind.ArrowExpressionClause:
if (node.IsParentKind(SyntaxKind.PropertyDeclaration, SyntaxKind.IndexerDeclaration))
return Label.ArrowExpressionClause;

break;

case SyntaxKind.EventDeclaration:
return Label.EventDeclaration;

Expand Down Expand Up @@ -1413,6 +1421,9 @@ private static double CombineOptional(
case SyntaxKind.IndexerDeclaration:
return null;

case SyntaxKind.ArrowExpressionClause:
return null;

case SyntaxKind.EventDeclaration:
return ((EventDeclarationSyntax)node).Identifier;

Expand Down

0 comments on commit 8cfddbf

Please sign in to comment.