diff --git a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueClosureTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueClosureTests.cs index 003401a3770ab..16def4e4ea2af 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueClosureTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueClosureTests.cs @@ -309,7 +309,7 @@ void F() CheckEncLogDefinitions(reader1, Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(3, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); } [Fact] @@ -362,7 +362,7 @@ void F() CheckEncLogDefinitions(reader1, Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(3, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); var testData0 = new CompilationTestData(); var bytes0 = compilation0.EmitToArray(testData: testData0); @@ -477,7 +477,7 @@ void F() Row(2, TableIndex.StandAloneSig, EditAndContinueOperation.Default), Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(3, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); } [Fact] @@ -532,7 +532,7 @@ int F(int a) Row(2, TableIndex.StandAloneSig, EditAndContinueOperation.Default), Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(3, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); } [Fact] @@ -586,7 +586,7 @@ int F(int a) Row(2, TableIndex.StandAloneSig, EditAndContinueOperation.Default), Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(3, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); } [Fact] @@ -786,7 +786,7 @@ int F(int a) Row(2, TableIndex.StandAloneSig, EditAndContinueOperation.Default), Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(3, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); } [Fact] @@ -1076,8 +1076,8 @@ void F() Row(18, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(19, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(20, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(17, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(18, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(15, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(16, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); } [Fact] @@ -1153,7 +1153,7 @@ void F() Row(10, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(12, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(15, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(15, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(14, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); } [Fact] @@ -1240,9 +1240,9 @@ public void F() Row(8, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(10, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(12, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(10, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(11, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(12, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(9, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); } [Fact] @@ -1322,7 +1322,7 @@ public void F() Row(6, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(9, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(10, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); } [Fact] @@ -1399,7 +1399,7 @@ public void F() Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(6, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(9, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); } [Fact] @@ -4002,7 +4002,7 @@ .maxstack 2 Row(2, TableIndex.StandAloneSig, EditAndContinueOperation.Default), Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(3, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); } [Fact] @@ -4087,7 +4087,7 @@ .maxstack 2 Row(2, TableIndex.StandAloneSig, EditAndContinueOperation.Default), Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(3, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); } [Fact] @@ -4160,7 +4160,7 @@ .maxstack 2 CheckEncLogDefinitions(reader1, Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(3, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); } [Fact] diff --git a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueStateMachineTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueStateMachineTests.cs index 7dae6013bdcab..77d26eb3af244 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueStateMachineTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueStateMachineTests.cs @@ -536,9 +536,13 @@ static IEnumerable F() using (var md1 = diff1.GetMetadata()) { + CheckAttributes(md1.Reader, + new CustomAttributeRow(Handle(0, TableIndex.MethodDef), Handle(0, TableIndex.MemberRef))); // row id 0 == delete + CheckEncLogDefinitions(md1.Reader, Row(3, TableIndex.StandAloneSig, EditAndContinueOperation.Default), - Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default)); + Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(1, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); // Delete IteratorStateMachineAttribute } } } @@ -583,9 +587,15 @@ static Task F() using (var md1 = diff1.GetMetadata()) { + CheckAttributes(md1.Reader, + new CustomAttributeRow(Handle(0, TableIndex.MethodDef), Handle(0, TableIndex.MemberRef)), // row id 0 == delete + new CustomAttributeRow(Handle(0, TableIndex.MethodDef), Handle(0, TableIndex.MemberRef))); // row id 0 == delete + CheckEncLogDefinitions(md1.Reader, Row(3, TableIndex.StandAloneSig, EditAndContinueOperation.Default), - Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default)); + Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(1, TableIndex.CustomAttribute, EditAndContinueOperation.Default), // Delete AsyncStateMachineAttribute + Row(2, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); // Delete DebuggerStepThroughAttribute } } } @@ -674,12 +684,12 @@ static async Task F(int a) Row(6, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(9, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(12, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(16, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(17, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(18, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(19, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(20, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(21, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(1, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(2, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(8, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(9, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); } } } @@ -738,8 +748,8 @@ static IEnumerable F() Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(13, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(14, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(1, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); diff1.VerifyIL("C.d__0.System.Collections.IEnumerator.MoveNext", @" { @@ -875,8 +885,8 @@ static async Task F() Row(4, TableIndex.StandAloneSig, EditAndContinueOperation.Default), Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(8, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(9, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(1, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(2, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); diff1.VerifyIL("C.d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", @" { @@ -1146,8 +1156,8 @@ static IEnumerable F(int p) Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(13, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(14, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(1, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); diff1.VerifyIL("C.d__0.System.Collections.IEnumerator.MoveNext", @" { @@ -1250,8 +1260,8 @@ static IEnumerable F(int p) Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(13, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(14, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(1, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); diff1.VerifyIL("C.d__0.System.Collections.IEnumerator.MoveNext", @" { @@ -1361,8 +1371,8 @@ static IEnumerable F(int p) Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(13, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(14, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(1, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); diff1.VerifyIL("C.d__0.System.Collections.IEnumerator.MoveNext", @" { @@ -1469,8 +1479,8 @@ static IEnumerable F() Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(13, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(14, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(1, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); diff1.VerifyIL("C.d__0.System.Collections.IEnumerator.MoveNext", @" { @@ -1586,8 +1596,8 @@ static IEnumerable F() Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(13, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(14, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(1, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); diff1.VerifyIL("C.d__0.System.Collections.IEnumerator.MoveNext", @" { @@ -1879,10 +1889,10 @@ static async Task H() // updated Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(6, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(9, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(16, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(17, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(18, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(19, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(1, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(2, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); diff1.VerifyIL("C.d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", @" { @@ -1990,8 +2000,8 @@ .locals init (int V_0, Row(18, TableIndex.Field, EditAndContinueOperation.Default), Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(6, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(20, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(21, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(1, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(2, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); diff2.VerifyIL("C.d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", @" { @@ -2103,10 +2113,10 @@ .locals init (int V_0, Row(3, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(9, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(12, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(22, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(23, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(24, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(25, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(8, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(9, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); } [Fact] @@ -2626,10 +2636,10 @@ static async Task H() // updated Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(9, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(12, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(16, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(17, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(18, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(19, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(8, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(9, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); // Note that the new awaiter is allocated slot <>u__3 since <>u__1 and <>u__2 are taken. diff1.VerifyIL("C.d__3.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", @" @@ -2766,8 +2776,8 @@ .locals init (int V_0, Row(12, TableIndex.Field, EditAndContinueOperation.Default), Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(9, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(20, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(21, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); // Note that the new awaiters are allocated slots <>u__4, <>u__5. diff2.VerifyIL("C.d__3.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", @" @@ -2910,10 +2920,10 @@ .locals init (int V_0, Row(6, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(12, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(15, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(22, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(23, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(24, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(25, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); + Row(8, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(9, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(11, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(12, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); } [Fact] diff --git a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.cs index 0652a0d96bc13..3a6e5142eb10f 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.cs @@ -359,6 +359,692 @@ static void Main() { } Handle(2, TableIndex.AssemblyRef)); } + [Fact] + public void ModifyMethod_WithAttributes1() + { + var source0 = +@"class C +{ + static void Main() { } + [System.ComponentModel.Description(""The F method"")] + static string F() { return null; } +}"; + var source1 = +@"class C +{ + static void Main() { } + [System.ComponentModel.Description(""The F method"")] + static string F() { return string.Empty; } +}"; + var source2 = +@"[System.ComponentModel.Browsable(false)] +class C +{ + static void Main() { } + [System.ComponentModel.Description(""The F method""), System.ComponentModel.Category(""Methods"")] + static string F() { return string.Empty; } +}"; + var source3 = +@"[System.ComponentModel.Browsable(false)] +class C +{ + static void Main() { } + [System.ComponentModel.Browsable(false), System.ComponentModel.Description(""The F method""), System.ComponentModel.Category(""Methods"")] + static string F() { return string.Empty; } +}"; + + var compilation0 = CreateCompilation(source0, options: TestOptions.DebugExe, targetFramework: TargetFramework.NetStandard20); + var compilation1 = compilation0.WithSource(source1); + var compilation2 = compilation1.WithSource(source2); + var compilation3 = compilation2.WithSource(source3); + + var method0 = compilation0.GetMember("C.F"); + + // Verify full metadata contains expected rows. + var bytes0 = compilation0.EmitToArray(); + using var md0 = ModuleMetadata.CreateFromImage(bytes0); + var reader0 = md0.MetadataReader; + + CheckNames(reader0, reader0.GetTypeDefNames(), "", "C"); + CheckNames(reader0, reader0.GetMethodDefNames(), "Main", "F", ".ctor"); + CheckNames(reader0, reader0.GetMemberRefNames(), /*CompilationRelaxationsAttribute.*/".ctor", /*RuntimeCompatibilityAttribute.*/".ctor", /*Object.*/".ctor", /*DebuggableAttribute*/".ctor", /*DescriptionAttribute*/".ctor"); + + Assert.Equal(4, reader0.CustomAttributes.Count); + + var generation0 = EmitBaseline.CreateInitialBaseline( + md0, + EmptyLocalsProvider); + var method1 = compilation1.GetMember("C.F"); + + var diff1 = compilation1.EmitDifference( + generation0, + ImmutableArray.Create(SemanticEdit.Create(SemanticEditKind.Update, method0, method1))); + + // Verify delta metadata contains expected rows. + using var md1 = diff1.GetMetadata(); + var reader1 = md1.Reader; + var readers = new[] { reader0, reader1 }; + + EncValidation.VerifyModuleMvid(1, reader0, reader1); + + CheckNames(readers, reader1.GetTypeDefNames()); + CheckNames(readers, reader1.GetMethodDefNames(), "F"); + CheckNames(readers, reader1.GetMemberRefNames(), /*DescriptionAttribute*/".ctor", /*String.*/"Empty"); + + Assert.Equal(1, reader1.CustomAttributes.Count); + + CheckEncLog(reader1, + Row(2, TableIndex.AssemblyRef, EditAndContinueOperation.Default), + Row(6, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(7, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(7, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(8, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(9, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(2, TableIndex.StandAloneSig, EditAndContinueOperation.Default), + Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); // Row 4, so updating existing CustomAttribute + + CheckEncMap(reader1, + Handle(7, TableIndex.TypeRef), + Handle(8, TableIndex.TypeRef), + Handle(9, TableIndex.TypeRef), + Handle(2, TableIndex.MethodDef), + Handle(6, TableIndex.MemberRef), + Handle(7, TableIndex.MemberRef), + Handle(4, TableIndex.CustomAttribute), + Handle(2, TableIndex.StandAloneSig), + Handle(2, TableIndex.AssemblyRef)); + + var method2 = compilation2.GetMember("C.F"); + var diff2 = compilation2.EmitDifference( + diff1.NextGeneration, + ImmutableArray.Create( + SemanticEdit.Create(SemanticEditKind.Update, compilation1.GetMember("C"), compilation2.GetMember("C")), + SemanticEdit.Create(SemanticEditKind.Update, method1, method2))); + + // Verify delta metadata contains expected rows. + using var md2 = diff2.GetMetadata(); + var reader2 = md2.Reader; + readers = new[] { reader0, reader1, reader2 }; + + CheckNames(readers, reader2.GetTypeDefNames(), "C"); + CheckNames(readers, reader2.GetMethodDefNames(), "F"); + CheckNames(readers, reader2.GetMemberRefNames(), /*DescriptionAttribute*/".ctor", /*BrowsableAttribute*/".ctor", /*CategoryAttribute*/".ctor", /*String.*/"Empty"); + + Assert.Equal(3, reader2.CustomAttributes.Count); + + CheckEncLog(reader2, + Row(3, TableIndex.AssemblyRef, EditAndContinueOperation.Default), + Row(8, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(9, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(10, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(11, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(10, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(11, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(12, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(13, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(14, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(3, TableIndex.StandAloneSig, EditAndContinueOperation.Default), + Row(2, TableIndex.TypeDef, EditAndContinueOperation.Default), + Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default), // Row 4, updating the existing custom attribute + Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default), // Row 5, adding a new CustomAttribute + Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); // Row 6 adding a new CustomAttribute + + CheckEncMap(reader2, + Handle(10, TableIndex.TypeRef), + Handle(11, TableIndex.TypeRef), + Handle(12, TableIndex.TypeRef), + Handle(13, TableIndex.TypeRef), + Handle(14, TableIndex.TypeRef), + Handle(2, TableIndex.TypeDef), + Handle(2, TableIndex.MethodDef), + Handle(8, TableIndex.MemberRef), + Handle(9, TableIndex.MemberRef), + Handle(10, TableIndex.MemberRef), + Handle(11, TableIndex.MemberRef), + Handle(4, TableIndex.CustomAttribute), + Handle(5, TableIndex.CustomAttribute), + Handle(6, TableIndex.CustomAttribute), + Handle(3, TableIndex.StandAloneSig), + Handle(3, TableIndex.AssemblyRef)); + + var method3 = compilation3.GetMember("C.F"); + var diff3 = compilation3.EmitDifference( + diff2.NextGeneration, + ImmutableArray.Create(SemanticEdit.Create(SemanticEditKind.Update, method2, method3))); + + // Verify delta metadata contains expected rows. + using var md3 = diff3.GetMetadata(); + var reader3 = md3.Reader; + readers = new[] { reader0, reader1, reader2, reader3 }; + + CheckNames(readers, reader3.GetTypeDefNames()); + CheckNames(readers, reader3.GetMethodDefNames(), "F"); + CheckNames(readers, reader3.GetMemberRefNames(), /*BrowsableAttribute*/".ctor", /*DescriptionAttribute*/".ctor", /*CategoryAttribute*/".ctor", /*String.*/"Empty"); + + CheckEncLog(reader3, + Row(4, TableIndex.AssemblyRef, EditAndContinueOperation.Default), + Row(12, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(13, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(14, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(15, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(15, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(16, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(17, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(18, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(19, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(4, TableIndex.StandAloneSig, EditAndContinueOperation.Default), + Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default), // Row 4, updating the existing custom attribute + Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default), // Row 5, updating a row that was new in Generation 2 + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); // Row 7, adding a new CustomAttribute, and skipping row 6 which is not for the method being emitted + + CheckEncMap(reader3, + Handle(15, TableIndex.TypeRef), + Handle(16, TableIndex.TypeRef), + Handle(17, TableIndex.TypeRef), + Handle(18, TableIndex.TypeRef), + Handle(19, TableIndex.TypeRef), + Handle(2, TableIndex.MethodDef), + Handle(12, TableIndex.MemberRef), + Handle(13, TableIndex.MemberRef), + Handle(14, TableIndex.MemberRef), + Handle(15, TableIndex.MemberRef), + Handle(4, TableIndex.CustomAttribute), + Handle(5, TableIndex.CustomAttribute), + Handle(7, TableIndex.CustomAttribute), + Handle(4, TableIndex.StandAloneSig), + Handle(4, TableIndex.AssemblyRef)); + } + + [Fact] + public void ModifyMethod_WithAttributes2() + { + var source0 = +@"[System.ComponentModel.Browsable(false)] +class C +{ + static void Main() { } + [System.ComponentModel.Description(""The F method"")] + static string F() { return null; } +} +[System.ComponentModel.Browsable(false)] +class D +{ + [System.ComponentModel.Description(""A"")] + static string A() { return null; } +} +"; + var source1 = +@" +[System.ComponentModel.Browsable(false)] +class C +{ + static void Main() { } + [System.ComponentModel.Description(""The F method""), System.ComponentModel.Browsable(false), System.ComponentModel.Category(""Methods"")] + static string F() { return null; } +} +[System.ComponentModel.Browsable(false)] +class D +{ + [System.ComponentModel.Description(""A""), System.ComponentModel.Category(""Methods"")] + static string A() { return null; } +} +"; + + var compilation0 = CreateCompilation(source0, options: TestOptions.DebugExe, targetFramework: TargetFramework.NetStandard20); + var compilation1 = compilation0.WithSource(source1); + + var method0_1 = compilation0.GetMember("C.F"); + var method0_2 = compilation0.GetMember("D.A"); + + // Verify full metadata contains expected rows. + var bytes0 = compilation0.EmitToArray(); + using var md0 = ModuleMetadata.CreateFromImage(bytes0); + var reader0 = md0.MetadataReader; + + CheckNames(reader0, reader0.GetTypeDefNames(), "", "C", "D"); + CheckNames(reader0, reader0.GetMethodDefNames(), "Main", "F", ".ctor", "A", ".ctor"); + CheckNames(reader0, reader0.GetMemberRefNames(), /*CompilationRelaxationsAttribute.*/".ctor", /*RuntimeCompatibilityAttribute.*/".ctor", /*Object.*/".ctor", /*DebuggableAttribute*/".ctor", /*DescriptionAttribute*/".ctor", /*BrowsableAttribute*/".ctor"); + + CheckAttributes(reader0, + new CustomAttributeRow(Handle(1, TableIndex.Assembly), Handle(1, TableIndex.MemberRef)), + new CustomAttributeRow(Handle(1, TableIndex.Assembly), Handle(2, TableIndex.MemberRef)), + new CustomAttributeRow(Handle(1, TableIndex.Assembly), Handle(3, TableIndex.MemberRef)), + new CustomAttributeRow(Handle(2, TableIndex.MethodDef), Handle(5, TableIndex.MemberRef)), + new CustomAttributeRow(Handle(2, TableIndex.TypeDef), Handle(4, TableIndex.MemberRef)), + new CustomAttributeRow(Handle(3, TableIndex.TypeDef), Handle(4, TableIndex.MemberRef)), + new CustomAttributeRow(Handle(4, TableIndex.MethodDef), Handle(5, TableIndex.MemberRef))); + + var generation0 = EmitBaseline.CreateInitialBaseline( + md0, + EmptyLocalsProvider); + var method1_1 = compilation1.GetMember("C.F"); + var method1_2 = compilation1.GetMember("D.A"); + + var diff1 = compilation1.EmitDifference( + generation0, + ImmutableArray.Create( + SemanticEdit.Create(SemanticEditKind.Update, method0_1, method1_1), + SemanticEdit.Create(SemanticEditKind.Update, method0_2, method1_2))); + + // Verify delta metadata contains expected rows. + using var md1 = diff1.GetMetadata(); + var reader1 = md1.Reader; + var readers = new[] { reader0, reader1 }; + + EncValidation.VerifyModuleMvid(1, reader0, reader1); + + CheckNames(readers, reader1.GetTypeDefNames()); + CheckNames(readers, reader1.GetMethodDefNames(), "F", "A"); + CheckNames(readers, reader1.GetMemberRefNames(), /*BrowsableAttribute*/".ctor", /*CategoryAttribute*/".ctor", /*DescriptionAttribute*/".ctor"); + + CheckAttributes(reader1, + new CustomAttributeRow(Handle(2, TableIndex.MethodDef), Handle(8, TableIndex.MemberRef)), + new CustomAttributeRow(Handle(2, TableIndex.MethodDef), Handle(7, TableIndex.MemberRef)), + new CustomAttributeRow(Handle(2, TableIndex.MethodDef), Handle(9, TableIndex.MemberRef)), + new CustomAttributeRow(Handle(4, TableIndex.MethodDef), Handle(8, TableIndex.MemberRef)), + new CustomAttributeRow(Handle(4, TableIndex.MethodDef), Handle(9, TableIndex.MemberRef))); + + CheckEncLog(reader1, + Row(2, TableIndex.AssemblyRef, EditAndContinueOperation.Default), + Row(7, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(8, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(9, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(8, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(9, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(10, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(11, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(2, TableIndex.StandAloneSig, EditAndContinueOperation.Default), + Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default), // update existing row + Row(8, TableIndex.CustomAttribute, EditAndContinueOperation.Default), // add new row + Row(9, TableIndex.CustomAttribute, EditAndContinueOperation.Default), // add new row + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default), // update existing row + Row(10, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); // add new row + + CheckEncMap(reader1, + Handle(8, TableIndex.TypeRef), + Handle(9, TableIndex.TypeRef), + Handle(10, TableIndex.TypeRef), + Handle(11, TableIndex.TypeRef), + Handle(2, TableIndex.MethodDef), + Handle(4, TableIndex.MethodDef), + Handle(7, TableIndex.MemberRef), + Handle(8, TableIndex.MemberRef), + Handle(9, TableIndex.MemberRef), + Handle(4, TableIndex.CustomAttribute), + Handle(7, TableIndex.CustomAttribute), + Handle(8, TableIndex.CustomAttribute), + Handle(9, TableIndex.CustomAttribute), + Handle(10, TableIndex.CustomAttribute), + Handle(2, TableIndex.StandAloneSig), + Handle(2, TableIndex.AssemblyRef)); + } + + [Fact] + public void ModifyMethod_DeleteAttributes1() + { + var source0 = +@"class C +{ + static void Main() { } + [System.ComponentModel.Description(""The F method"")] + static string F() { return null; } +}"; + var source1 = +@"class C +{ + static void Main() { } + static string F() { return string.Empty; } +}"; + var source2 = +@"class C +{ + static void Main() { } + [System.ComponentModel.Description(""The F method"")] + static string F() { return string.Empty; } +}"; + + var compilation0 = CreateCompilation(source0, options: TestOptions.DebugExe, targetFramework: TargetFramework.NetStandard20); + var compilation1 = compilation0.WithSource(source1); + var compilation2 = compilation1.WithSource(source2); + + var method0 = compilation0.GetMember("C.F"); + + // Verify full metadata contains expected rows. + var bytes0 = compilation0.EmitToArray(); + using var md0 = ModuleMetadata.CreateFromImage(bytes0); + var reader0 = md0.MetadataReader; + + CheckNames(reader0, reader0.GetTypeDefNames(), "", "C"); + CheckNames(reader0, reader0.GetMethodDefNames(), "Main", "F", ".ctor"); + CheckNames(reader0, reader0.GetMemberRefNames(), /*CompilationRelaxationsAttribute.*/".ctor", /*RuntimeCompatibilityAttribute.*/".ctor", /*Object.*/".ctor", /*DebuggableAttribute*/".ctor", /*DescriptionAttribute*/".ctor"); + + CheckAttributes(reader0, + new CustomAttributeRow(Handle(1, TableIndex.Assembly), Handle(1, TableIndex.MemberRef)), + new CustomAttributeRow(Handle(1, TableIndex.Assembly), Handle(2, TableIndex.MemberRef)), + new CustomAttributeRow(Handle(1, TableIndex.Assembly), Handle(3, TableIndex.MemberRef)), + new CustomAttributeRow(Handle(2, TableIndex.MethodDef), Handle(4, TableIndex.MemberRef))); + + var generation0 = EmitBaseline.CreateInitialBaseline( + md0, + EmptyLocalsProvider); + var method1 = compilation1.GetMember("C.F"); + + var diff1 = compilation1.EmitDifference( + generation0, + ImmutableArray.Create(SemanticEdit.Create(SemanticEditKind.Update, method0, method1))); + + // Verify delta metadata contains expected rows. + using var md1 = diff1.GetMetadata(); + var reader1 = md1.Reader; + var readers = new[] { reader0, reader1 }; + + EncValidation.VerifyModuleMvid(1, reader0, reader1); + + CheckNames(readers, reader1.GetTypeDefNames()); + CheckNames(readers, reader1.GetMethodDefNames(), "F"); + CheckNames(readers, reader1.GetMemberRefNames(), /*String.*/"Empty"); + + CheckAttributes(reader1, + new CustomAttributeRow(Handle(0, TableIndex.MethodDef), Handle(0, TableIndex.MemberRef))); // Parent row id is 0, signifying a delete + + CheckEncLog(reader1, + Row(2, TableIndex.AssemblyRef, EditAndContinueOperation.Default), + Row(6, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(7, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(8, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(2, TableIndex.StandAloneSig, EditAndContinueOperation.Default), + Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); // Row 4, so updating existing CustomAttribute + + CheckEncMap(reader1, + Handle(7, TableIndex.TypeRef), + Handle(8, TableIndex.TypeRef), + Handle(2, TableIndex.MethodDef), + Handle(6, TableIndex.MemberRef), + Handle(4, TableIndex.CustomAttribute), + Handle(2, TableIndex.StandAloneSig), + Handle(2, TableIndex.AssemblyRef)); + + var method2 = compilation2.GetMember("C.F"); + var diff2 = compilation2.EmitDifference( + diff1.NextGeneration, + ImmutableArray.Create(SemanticEdit.Create(SemanticEditKind.Update, method1, method2))); + + // Verify delta metadata contains expected rows. + using var md2 = diff2.GetMetadata(); + var reader2 = md2.Reader; + readers = new[] { reader0, reader1, reader2 }; + + EncValidation.VerifyModuleMvid(2, reader1, reader2); + + CheckNames(readers, reader2.GetTypeDefNames()); + CheckNames(readers, reader2.GetMethodDefNames(), "F"); + CheckNames(readers, reader2.GetMemberRefNames(), /*DescriptionAttribute*/".ctor", /*String.*/"Empty"); + + CheckAttributes(reader2, + new CustomAttributeRow(Handle(2, TableIndex.MethodDef), Handle(7, TableIndex.MemberRef))); + + CheckEncLog(reader2, + Row(3, TableIndex.AssemblyRef, EditAndContinueOperation.Default), + Row(7, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(8, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(9, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(10, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(11, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(3, TableIndex.StandAloneSig, EditAndContinueOperation.Default), + Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); // Row 4, updating the original row back to a real one + + CheckEncMap(reader2, + Handle(9, TableIndex.TypeRef), + Handle(10, TableIndex.TypeRef), + Handle(11, TableIndex.TypeRef), + Handle(2, TableIndex.MethodDef), + Handle(7, TableIndex.MemberRef), + Handle(8, TableIndex.MemberRef), + Handle(4, TableIndex.CustomAttribute), + Handle(3, TableIndex.StandAloneSig), + Handle(3, TableIndex.AssemblyRef)); + } + + [Fact] + public void ModifyMethod_DeleteAttributes2() + { + var source0 = +@"class C +{ + static void Main() { } + static string F() { return null; } +}"; + var source1 = +@"class C +{ + static void Main() { } + [System.ComponentModel.Description(""The F method"")] + static string F() { return string.Empty; } +}"; + var source2 = source0; // Remove the attribute we just added + var source3 = source1; // Add the attribute back again + + var compilation0 = CreateCompilation(source0, options: TestOptions.DebugExe, targetFramework: TargetFramework.NetStandard20); + var compilation1 = compilation0.WithSource(source1); + var compilation2 = compilation1.WithSource(source2); + var compilation3 = compilation1.WithSource(source3); + + var method0 = compilation0.GetMember("C.F"); + + // Verify full metadata contains expected rows. + var bytes0 = compilation0.EmitToArray(); + using var md0 = ModuleMetadata.CreateFromImage(bytes0); + var reader0 = md0.MetadataReader; + + CheckNames(reader0, reader0.GetTypeDefNames(), "", "C"); + CheckNames(reader0, reader0.GetMethodDefNames(), "Main", "F", ".ctor"); + CheckNames(reader0, reader0.GetMemberRefNames(), /*CompilationRelaxationsAttribute.*/".ctor", /*RuntimeCompatibilityAttribute.*/".ctor", /*Object.*/".ctor", /*DebuggableAttribute*/".ctor"); + + CheckAttributes(reader0, + new CustomAttributeRow(Handle(1, TableIndex.Assembly), Handle(1, TableIndex.MemberRef)), + new CustomAttributeRow(Handle(1, TableIndex.Assembly), Handle(2, TableIndex.MemberRef)), + new CustomAttributeRow(Handle(1, TableIndex.Assembly), Handle(3, TableIndex.MemberRef))); + + var generation0 = EmitBaseline.CreateInitialBaseline( + md0, + EmptyLocalsProvider); + var method1 = compilation1.GetMember("C.F"); + + var diff1 = compilation1.EmitDifference( + generation0, + ImmutableArray.Create(SemanticEdit.Create(SemanticEditKind.Update, method0, method1))); + + // Verify delta metadata contains expected rows. + using var md1 = diff1.GetMetadata(); + var reader1 = md1.Reader; + var readers = new[] { reader0, reader1 }; + + EncValidation.VerifyModuleMvid(1, reader0, reader1); + + CheckNames(readers, reader1.GetTypeDefNames()); + CheckNames(readers, reader1.GetMethodDefNames(), "F"); + CheckNames(readers, reader1.GetMemberRefNames(), /*DescriptionAttribute*/".ctor", /*String.*/"Empty"); + + CheckAttributes(reader1, + new CustomAttributeRow(Handle(2, TableIndex.MethodDef), Handle(5, TableIndex.MemberRef))); + + CheckEncLog(reader1, + Row(2, TableIndex.AssemblyRef, EditAndContinueOperation.Default), + Row(5, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(6, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(6, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(7, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(8, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(2, TableIndex.StandAloneSig, EditAndContinueOperation.Default), + Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); // Row 4, so adding a new CustomAttribute + + CheckEncMap(reader1, + Handle(6, TableIndex.TypeRef), + Handle(7, TableIndex.TypeRef), + Handle(8, TableIndex.TypeRef), + Handle(2, TableIndex.MethodDef), + Handle(5, TableIndex.MemberRef), + Handle(6, TableIndex.MemberRef), + Handle(4, TableIndex.CustomAttribute), + Handle(2, TableIndex.StandAloneSig), + Handle(2, TableIndex.AssemblyRef)); + + var method2 = compilation2.GetMember("C.F"); + var diff2 = compilation2.EmitDifference( + diff1.NextGeneration, + ImmutableArray.Create( + SemanticEdit.Create(SemanticEditKind.Update, method1, method2))); + + // Verify delta metadata contains expected rows. + using var md2 = diff2.GetMetadata(); + var reader2 = md2.Reader; + readers = new[] { reader0, reader1, reader2 }; + + CheckNames(readers, reader2.GetTypeDefNames()); + CheckNames(readers, reader2.GetMethodDefNames(), "F"); + CheckNames(readers, reader2.GetMemberRefNames()); + + CheckAttributes(reader2, + new CustomAttributeRow(Handle(0, TableIndex.MethodDef), Handle(0, TableIndex.MemberRef))); // 0, delete + + CheckEncLog(reader2, + Row(3, TableIndex.AssemblyRef, EditAndContinueOperation.Default), + Row(9, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(3, TableIndex.StandAloneSig, EditAndContinueOperation.Default), + Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); // Row 4, so updating existing CustomAttribute + + CheckEncMap(reader2, + Handle(9, TableIndex.TypeRef), + Handle(2, TableIndex.MethodDef), + Handle(4, TableIndex.CustomAttribute), + Handle(3, TableIndex.StandAloneSig), + Handle(3, TableIndex.AssemblyRef)); + + var method3 = compilation3.GetMember("C.F"); + var diff3 = compilation3.EmitDifference( + diff2.NextGeneration, + ImmutableArray.Create( + SemanticEdit.Create(SemanticEditKind.Update, method2, method3))); + + // Verify delta metadata contains expected rows. + using var md3 = diff3.GetMetadata(); + var reader3 = md3.Reader; + readers = new[] { reader0, reader1, reader2, reader3 }; + + CheckNames(readers, reader3.GetTypeDefNames()); + CheckNames(readers, reader3.GetMethodDefNames(), "F"); + CheckNames(readers, reader3.GetMemberRefNames(), /*DescriptionAttribute*/".ctor", /*String.*/"Empty"); + + CheckAttributes(reader3, + new CustomAttributeRow(Handle(2, TableIndex.MethodDef), Handle(7, TableIndex.MemberRef))); + + CheckEncLog(reader3, + Row(4, TableIndex.AssemblyRef, EditAndContinueOperation.Default), + Row(7, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(8, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(10, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(11, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(12, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(4, TableIndex.StandAloneSig, EditAndContinueOperation.Default), + Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); // Row 4, update the previously deleted row + + CheckEncMap(reader3, + Handle(10, TableIndex.TypeRef), + Handle(11, TableIndex.TypeRef), + Handle(12, TableIndex.TypeRef), + Handle(2, TableIndex.MethodDef), + Handle(7, TableIndex.MemberRef), + Handle(8, TableIndex.MemberRef), + Handle(4, TableIndex.CustomAttribute), + Handle(4, TableIndex.StandAloneSig), + Handle(4, TableIndex.AssemblyRef)); + } + + [Fact] + public void AddMethod_WithAttributes() + { + var source0 = +@"class C +{ + static void Main() { } +}"; + var source1 = +@"class C +{ + static void Main() { } + [System.ComponentModel.Description(""The F method"")] + static string F() { return string.Empty; } +}"; + var compilation0 = CreateCompilation(source0, options: TestOptions.DebugExe, targetFramework: TargetFramework.NetStandard20); + var compilation1 = compilation0.WithSource(source1); + + // Verify full metadata contains expected rows. + var bytes0 = compilation0.EmitToArray(); + using var md0 = ModuleMetadata.CreateFromImage(bytes0); + var reader0 = md0.MetadataReader; + + CheckNames(reader0, reader0.GetTypeDefNames(), "", "C"); + CheckNames(reader0, reader0.GetMethodDefNames(), "Main", ".ctor"); + CheckNames(reader0, reader0.GetMemberRefNames(), /*CompilationRelaxationsAttribute.*/".ctor", /*RuntimeCompatibilityAttribute.*/".ctor", /*Object.*/".ctor", /*DebuggableAttribute*/".ctor"); + + Assert.Equal(3, reader0.CustomAttributes.Count); + + var generation0 = EmitBaseline.CreateInitialBaseline( + md0, + EmptyLocalsProvider); + var method1 = compilation1.GetMember("C.F"); + + var diff1 = compilation1.EmitDifference( + generation0, + ImmutableArray.Create(SemanticEdit.Create(SemanticEditKind.Insert, null, method1))); + + // Verify delta metadata contains expected rows. + using var md1 = diff1.GetMetadata(); + var reader1 = md1.Reader; + var readers = new[] { reader0, reader1 }; + + EncValidation.VerifyModuleMvid(1, reader0, reader1); + + CheckNames(readers, reader1.GetTypeDefNames()); + CheckNames(readers, reader1.GetMethodDefNames(), "F"); + CheckNames(readers, reader1.GetMemberRefNames(), /*DescriptionAttribute*/".ctor", /*String.*/"Empty"); + + Assert.Equal(1, reader1.CustomAttributes.Count); + + CheckEncLog(reader1, + Row(2, TableIndex.AssemblyRef, EditAndContinueOperation.Default), + Row(5, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(6, TableIndex.MemberRef, EditAndContinueOperation.Default), + Row(6, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(7, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(8, TableIndex.TypeRef, EditAndContinueOperation.Default), + Row(1, TableIndex.StandAloneSig, EditAndContinueOperation.Default), + Row(2, TableIndex.TypeDef, EditAndContinueOperation.AddMethod), + Row(3, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); // Row 4, a new attribute + + CheckEncMap(reader1, + Handle(6, TableIndex.TypeRef), + Handle(7, TableIndex.TypeRef), + Handle(8, TableIndex.TypeRef), + Handle(3, TableIndex.MethodDef), + Handle(5, TableIndex.MemberRef), + Handle(6, TableIndex.MemberRef), + Handle(4, TableIndex.CustomAttribute), + Handle(1, TableIndex.StandAloneSig), + Handle(2, TableIndex.AssemblyRef)); + } + [WorkItem(962219, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/962219")] [Fact] public void PartialMethod() @@ -2266,6 +2952,7 @@ [B] static void M2<[A]T>() { } Row(8, TableIndex.Param, EditAndContinueOperation.Default), Row(15, TableIndex.MethodDef, EditAndContinueOperation.AddParameter), Row(9, TableIndex.Param, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default), Row(13, TableIndex.CustomAttribute, EditAndContinueOperation.Default), Row(14, TableIndex.CustomAttribute, EditAndContinueOperation.Default), Row(15, TableIndex.CustomAttribute, EditAndContinueOperation.Default), @@ -2274,7 +2961,6 @@ [B] static void M2<[A]T>() { } Row(18, TableIndex.CustomAttribute, EditAndContinueOperation.Default), Row(19, TableIndex.CustomAttribute, EditAndContinueOperation.Default), Row(20, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(21, TableIndex.CustomAttribute, EditAndContinueOperation.Default), Row(4, TableIndex.MethodSemantics, EditAndContinueOperation.Default), Row(5, TableIndex.MethodSemantics, EditAndContinueOperation.Default), Row(6, TableIndex.MethodSemantics, EditAndContinueOperation.Default), @@ -2300,6 +2986,7 @@ [B] static void M2<[A]T>() { } Handle(13, TableIndex.MemberRef), Handle(14, TableIndex.MemberRef), Handle(15, TableIndex.MemberRef), + Handle(7, TableIndex.CustomAttribute), Handle(13, TableIndex.CustomAttribute), Handle(14, TableIndex.CustomAttribute), Handle(15, TableIndex.CustomAttribute), @@ -2308,7 +2995,6 @@ [B] static void M2<[A]T>() { } Handle(18, TableIndex.CustomAttribute), Handle(19, TableIndex.CustomAttribute), Handle(20, TableIndex.CustomAttribute), - Handle(21, TableIndex.CustomAttribute), Handle(3, TableIndex.StandAloneSig), Handle(4, TableIndex.StandAloneSig), Handle(2, TableIndex.Event), diff --git a/src/Compilers/Core/Portable/Emit/EditAndContinue/DeltaMetadataWriter.cs b/src/Compilers/Core/Portable/Emit/EditAndContinue/DeltaMetadataWriter.cs index 353c61b7f2e88..46b3955fa274d 100644 --- a/src/Compilers/Core/Portable/Emit/EditAndContinue/DeltaMetadataWriter.cs +++ b/src/Compilers/Core/Portable/Emit/EditAndContinue/DeltaMetadataWriter.cs @@ -38,6 +38,18 @@ internal sealed class DeltaMetadataWriter : MetadataWriter private readonly EventOrPropertyMapIndex _propertyMap; private readonly MethodImplIndex _methodImpls; + // For the EncLog table we need to know which things we're emitting custom attributes for so we can + // correctly map the attributes to row numbers of existing attributes for that target + private readonly Dictionary _customAttributeParentCounts; + + // For the EncMap table we need to keep a list of exactly which rows in the CustomAttributes table are updated + // since we spread these out amongst existing rows, it's not just a contiguous set + private readonly List _customAttributeEncMapRows; + + // Keep track of which CustomAttributes rows are added in this and previous deltas, over what is in the + // original metadata + private readonly Dictionary> _customAttributesAdded; + private readonly HeapOrReferenceIndex _assemblyRefIndex; private readonly HeapOrReferenceIndex _moduleRefIndex; private readonly InstanceAndStructuralReferenceIndex _memberRefIndex; @@ -90,6 +102,10 @@ public DeltaMetadataWriter( _propertyMap = new EventOrPropertyMapIndex(this.TryGetExistingPropertyMapIndex, sizes[(int)TableIndex.PropertyMap]); _methodImpls = new MethodImplIndex(this, sizes[(int)TableIndex.MethodImpl]); + _customAttributeParentCounts = new Dictionary(); + _customAttributeEncMapRows = new List(); + _customAttributesAdded = new Dictionary>(); + _assemblyRefIndex = new HeapOrReferenceIndex(this, lastRowId: sizes[(int)TableIndex.AssemblyRef]); _moduleRefIndex = new HeapOrReferenceIndex(this, lastRowId: sizes[(int)TableIndex.ModuleRef]); _memberRefIndex = new InstanceAndStructuralReferenceIndex(this, new MemberRefComparer(this), lastRowId: sizes[(int)TableIndex.MemberRef]); @@ -171,6 +187,7 @@ internal EmitBaseline GetDelta(EmitBaseline baseline, Compilation compilation, G eventMapAdded: AddRange(_previousGeneration.EventMapAdded, _eventMap.GetAdded()), propertyMapAdded: AddRange(_previousGeneration.PropertyMapAdded, _propertyMap.GetAdded()), methodImplsAdded: AddRange(_previousGeneration.MethodImplsAdded, _methodImpls.GetAdded()), + customAttributesAdded: AddRange(_previousGeneration.CustomAttributesAdded, _customAttributesAdded, replace: true), tableEntriesAdded: ImmutableArray.Create(tableSizes), // Blob stream is concatenated aligned. blobStreamLengthAdded: metadataSizes.GetAlignedHeapSize(HeapIndex.Blob) + _previousGeneration.BlobStreamLengthAdded, @@ -692,6 +709,17 @@ private EncLocalInfo CreateEncLocalInfo(ILocalDefinition localDef, byte[] signat return new EncLocalInfo(localDef.SlotInfo, translatedType, localDef.Constraints, signature); } + protected override int AddCustomAttributesToTable(EntityHandle parentHandle, IEnumerable attributes) + { + // The base class will write out the actual metadata for us + var numAttributesEmitted = base.AddCustomAttributesToTable(parentHandle, attributes); + + // We need to keep track of all of the things attributes could be associated with in this delta, in order to populate the EncLog and Map tables + _customAttributeParentCounts.Add(parentHandle, numAttributesEmitted); + + return numAttributesEmitted; + } + protected override void PopulateEncLogTableRows(ImmutableArray rowCounts) { // The EncLog table is a log of all the operations needed @@ -720,7 +748,7 @@ protected override void PopulateEncLogTableRows(ImmutableArray rowCounts) PopulateEncLogTableParameters(); PopulateEncLogTableRows(TableIndex.Constant, previousSizes, deltaSizes); - PopulateEncLogTableRows(TableIndex.CustomAttribute, previousSizes, deltaSizes); + PopulateEncLogTableCustomAttributes(); PopulateEncLogTableRows(TableIndex.DeclSecurity, previousSizes, deltaSizes); PopulateEncLogTableRows(TableIndex.ClassLayout, previousSizes, deltaSizes); PopulateEncLogTableRows(TableIndex.FieldLayout, previousSizes, deltaSizes); @@ -802,6 +830,118 @@ private void PopulateEncLogTableParameters() } } + /// + /// CustomAttributes point to their target via the Parent column so we cannot simply output new rows + /// in the delta or we would end up with duplicates, but we also don't want to do complex logic to determine + /// which attributes have changes, so we just emit them all. + /// This means our logic for emitting CustomAttributes is to update any existing rows, either from the original + /// compilation or subsequent deltas, and only add more if we need to. The EncLog table is the thing that tells + /// the runtime which row a CustomAttributes row is (ie, new or existing) + /// + private void PopulateEncLogTableCustomAttributes() + { + // List of attributes that need to be emitted to delete a previously emitted attribute + var deletedAttributeRows = new List<(int parentRowId, HandleKind kind)>(); + var customAttributesAdded = new Dictionary>(); + + // The data in _previousGeneration.CustomAttributesAdded is not nicely sorted, or even necessarily contiguous + // so we need to map each target onto the rows its attributes occupy so we know which rows to update + var lastRowId = _previousGeneration.OriginalMetadata.MetadataReader.GetTableRowCount(TableIndex.CustomAttribute); + if (_previousGeneration.CustomAttributesAdded.Count > 0) + { + lastRowId = _previousGeneration.CustomAttributesAdded.SelectMany(s => s.Value).Max(); + } + + // Iterate through the parents we emitted custom attributes for, in parent order + foreach (var (parent, count) in _customAttributeParentCounts.OrderBy(kvp => CodedIndex.HasCustomAttribute(kvp.Key))) + { + int index = 0; + + // First we try to update any existing attributes. + // GetCustomAttributes does a binary search, so is fast. We presume that the number of rows in the original metadata + // greatly outnumbers the amount of parents emitted in this delta so even with repeated searches this is still + // quicker than iterating the entire original table, even once. + var existingCustomAttributes = _previousGeneration.OriginalMetadata.MetadataReader.GetCustomAttributes(parent); + foreach (var attributeHandle in existingCustomAttributes) + { + int rowId = MetadataTokens.GetRowNumber(attributeHandle); + AddLogEntryOrDelete(rowId, parent, add: index < count); + index++; + } + + // If we emitted any attributes for this parent in previous deltas then we either need to update + // them next, or delete them if necessary + if (_previousGeneration.CustomAttributesAdded.TryGetValue(parent, out var rowIds)) + { + foreach (var rowId in rowIds) + { + TrackCustomAttributeAdded(rowId, parent); + AddLogEntryOrDelete(rowId, parent, add: index < count); + index++; + } + } + + // Finally if there are still attributes for this parent left, they are additions new to this delta + for (int i = index; i < count; i++) + { + lastRowId++; + TrackCustomAttributeAdded(lastRowId, parent); + AddEncLogEntry(lastRowId); + } + } + + // Save the attributes we've emitted, and the ones from previous deltas, for use in the next generation + foreach (var (parent, rowIds) in customAttributesAdded) + { + _customAttributesAdded.Add(parent, rowIds.ToImmutableAndFree()); + } + + // Add attributes and log entries for everything we've deleted + foreach (var row in deletedAttributeRows) + { + // now emit a "delete" row with a parent that is for the 0 row of the same table as the existing one + if (!MetadataTokens.TryGetTableIndex(row.kind, out var tableIndex)) + { + throw new InvalidOperationException("Trying to delete a custom attribute for a parent kind that doesn't have a matching table index."); + } + metadata.AddCustomAttribute(MetadataTokens.Handle(tableIndex, 0), MetadataTokens.EntityHandle(TableIndex.MemberRef, 0), value: default); + + AddEncLogEntry(row.parentRowId); + } + + void AddEncLogEntry(int rowId) + { + _customAttributeEncMapRows.Add(rowId); + metadata.AddEncLogEntry( + entity: MetadataTokens.CustomAttributeHandle(rowId), + code: EditAndContinueOperation.Default); + } + + void AddLogEntryOrDelete(int rowId, EntityHandle parent, bool add) + { + if (add) + { + // Update this row + AddEncLogEntry(rowId); + } + else + { + // Delete this row + deletedAttributeRows.Add((rowId, parent.Kind)); + } + } + + void TrackCustomAttributeAdded(int nextRowId, EntityHandle parent) + { + if (!customAttributesAdded.TryGetValue(parent, out var existing)) + { + existing = ArrayBuilder.GetInstance(); + customAttributesAdded.Add(parent, existing); + } + existing.Add(nextRowId); + } + } + private void PopulateEncLogTableRows(DefinitionIndex index, TableIndex tableIndex) where T : class, IDefinition { @@ -854,7 +994,7 @@ protected override void PopulateEncMapTableRows(ImmutableArray rowCounts) AddReferencedTokens(tokens, TableIndex.Param, previousSizes, deltaSizes); AddReferencedTokens(tokens, TableIndex.Constant, previousSizes, deltaSizes); - AddReferencedTokens(tokens, TableIndex.CustomAttribute, previousSizes, deltaSizes); + AddRowNumberTokens(tokens, _customAttributeEncMapRows, TableIndex.CustomAttribute); AddReferencedTokens(tokens, TableIndex.DeclSecurity, previousSizes, deltaSizes); AddReferencedTokens(tokens, TableIndex.ClassLayout, previousSizes, deltaSizes); AddReferencedTokens(tokens, TableIndex.FieldLayout, previousSizes, deltaSizes); @@ -981,6 +1121,14 @@ private static void AddDefinitionTokens(ArrayBuilder tokens, De } } + private static void AddRowNumberTokens(ArrayBuilder tokens, IEnumerable rowNumbers, TableIndex tableIndex) + { + foreach (var row in rowNumbers) + { + tokens.Add(MetadataTokens.Handle(tableIndex, row)); + } + } + protected override void PopulateEventMapTableRows() { foreach (var typeId in _eventMap.GetRows()) diff --git a/src/Compilers/Core/Portable/Emit/EditAndContinue/EmitBaseline.cs b/src/Compilers/Core/Portable/Emit/EditAndContinue/EmitBaseline.cs index b5e2eec851b7e..b16628e10f05b 100644 --- a/src/Compilers/Core/Portable/Emit/EditAndContinue/EmitBaseline.cs +++ b/src/Compilers/Core/Portable/Emit/EditAndContinue/EmitBaseline.cs @@ -212,6 +212,7 @@ public static EmitBaseline CreateInitialBaseline( eventMapAdded: new Dictionary(), propertyMapAdded: new Dictionary(), methodImplsAdded: new Dictionary(), + customAttributesAdded: new Dictionary>(), tableEntriesAdded: s_emptyTableSizes, blobStreamLengthAdded: 0, stringStreamLengthAdded: 0, @@ -262,6 +263,7 @@ public static EmitBaseline CreateInitialBaseline( internal readonly IReadOnlyDictionary EventMapAdded; internal readonly IReadOnlyDictionary PropertyMapAdded; internal readonly IReadOnlyDictionary MethodImplsAdded; + internal readonly IReadOnlyDictionary> CustomAttributesAdded; internal readonly ImmutableArray TableEntriesAdded; @@ -317,6 +319,7 @@ private EmitBaseline( IReadOnlyDictionary eventMapAdded, IReadOnlyDictionary propertyMapAdded, IReadOnlyDictionary methodImplsAdded, + IReadOnlyDictionary> customAttributesAdded, ImmutableArray tableEntriesAdded, int blobStreamLengthAdded, int stringStreamLengthAdded, @@ -377,6 +380,7 @@ private EmitBaseline( EventMapAdded = eventMapAdded; PropertyMapAdded = propertyMapAdded; MethodImplsAdded = methodImplsAdded; + CustomAttributesAdded = customAttributesAdded; TableEntriesAdded = tableEntriesAdded; BlobStreamLengthAdded = blobStreamLengthAdded; StringStreamLengthAdded = stringStreamLengthAdded; @@ -407,6 +411,7 @@ internal EmitBaseline With( IReadOnlyDictionary eventMapAdded, IReadOnlyDictionary propertyMapAdded, IReadOnlyDictionary methodImplsAdded, + IReadOnlyDictionary> customAttributesAdded, ImmutableArray tableEntriesAdded, int blobStreamLengthAdded, int stringStreamLengthAdded, @@ -438,6 +443,7 @@ internal EmitBaseline With( eventMapAdded, propertyMapAdded, methodImplsAdded, + customAttributesAdded, tableEntriesAdded, blobStreamLengthAdded: blobStreamLengthAdded, stringStreamLengthAdded: stringStreamLengthAdded, diff --git a/src/Compilers/Core/Portable/Emit/EditAndContinue/SymbolMatcher.cs b/src/Compilers/Core/Portable/Emit/EditAndContinue/SymbolMatcher.cs index c30390aee8bc9..890c0699ec78d 100644 --- a/src/Compilers/Core/Portable/Emit/EditAndContinue/SymbolMatcher.cs +++ b/src/Compilers/Core/Portable/Emit/EditAndContinue/SymbolMatcher.cs @@ -51,6 +51,7 @@ public EmitBaseline MapBaselineToCompilation( eventMapAdded: baseline.EventMapAdded, propertyMapAdded: baseline.PropertyMapAdded, methodImplsAdded: baseline.MethodImplsAdded, + customAttributesAdded: baseline.CustomAttributesAdded, tableEntriesAdded: baseline.TableEntriesAdded, blobStreamLengthAdded: baseline.BlobStreamLengthAdded, stringStreamLengthAdded: baseline.StringStreamLengthAdded, diff --git a/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs b/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs index 96e49d321b22f..24ba7a0146f1b 100644 --- a/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs +++ b/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs @@ -1158,7 +1158,6 @@ private BlobHandle GetMethodSignatureHandleAndBlob(IMethodReference methodRefere SerializeReturnValueAndParameters(encoder, methodReference, methodReference.ExtraParameters); - signatureBlob = builder.ToImmutableArray(); result = metadata.GetOrAddBlob(signatureBlob); _signatureIndex.Add(methodReference, KeyValuePairUtil.Create(result, signatureBlob)); @@ -2091,10 +2090,7 @@ private TypeReferenceHandle GetDummyAssemblyAttributeParent(bool isSecurity, boo private void AddModuleAttributesToTable(CommonPEModuleBuilder module) { Debug.Assert(this.IsFullMetadata); - foreach (ICustomAttribute customAttribute in module.GetSourceModuleAttributes()) - { - AddCustomAttributeToTable(EntityHandle.ModuleDefinition, customAttribute); - } + AddCustomAttributesToTable(EntityHandle.ModuleDefinition, module.GetSourceModuleAttributes()); } private void AddCustomAttributesToTable(IEnumerable parentList, TableIndex tableIndex) @@ -2104,10 +2100,7 @@ private void AddCustomAttributesToTable(IEnumerable parentList, TableIndex foreach (var parent in parentList) { var parentHandle = MetadataTokens.Handle(tableIndex, parentRowId++); - foreach (ICustomAttribute customAttribute in parent.GetAttributes(Context)) - { - AddCustomAttributeToTable(parentHandle, customAttribute); - } + AddCustomAttributesToTable(parentHandle, parent.GetAttributes(Context)); } } @@ -2117,33 +2110,19 @@ private void AddCustomAttributesToTable(IEnumerable parentList, Func attributes) + protected virtual int AddCustomAttributesToTable(EntityHandle parentHandle, IEnumerable attributes) { + int count = 0; foreach (var attr in attributes) { - AddCustomAttributeToTable(handle, attr); - } - } - - private void AddCustomAttributesToTable(IEnumerable typeRefsWithAttributes) - { - foreach (var typeRefWithAttributes in typeRefsWithAttributes) - { - var ifaceHandle = GetTypeHandle(typeRefWithAttributes.TypeRef); - foreach (var customAttribute in typeRefWithAttributes.Attributes) - { - AddCustomAttributeToTable(ifaceHandle, customAttribute); - } + count++; + AddCustomAttributeToTable(parentHandle, attr); } + return count; } private void AddCustomAttributeToTable(EntityHandle parentHandle, ICustomAttribute customAttribute) @@ -2435,7 +2414,6 @@ private void PopulateFileTableRows() } } - private void PopulateGenericParameters( ImmutableArray sortedGenericParameters) { diff --git a/src/Compilers/VisualBasic/Test/Emit/Emit/EditAndContinue/EditAndContinueClosureTests.vb b/src/Compilers/VisualBasic/Test/Emit/Emit/EditAndContinue/EditAndContinueClosureTests.vb index 1e1e3abbe0b7d..d1a70a3446e3e 100644 --- a/src/Compilers/VisualBasic/Test/Emit/Emit/EditAndContinue/EditAndContinueClosureTests.vb +++ b/src/Compilers/VisualBasic/Test/Emit/Emit/EditAndContinue/EditAndContinueClosureTests.vb @@ -222,7 +222,7 @@ End Class Row(4, TableIndex.StandAloneSig, EditAndContinueOperation.Default), Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(3, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) End Sub @@ -435,9 +435,9 @@ End Module Row(7, TableIndex.StandAloneSig, EditAndContinueOperation.Default), Row(6, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(11, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(18, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(19, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(20, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) + Row(9, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(10, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(14, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) End Sub diff --git a/src/Compilers/VisualBasic/Test/Emit/Emit/EditAndContinue/EditAndContinueStateMachineTests.vb b/src/Compilers/VisualBasic/Test/Emit/Emit/EditAndContinue/EditAndContinueStateMachineTests.vb index 49aca9d89d25c..fc4bd161e65f5 100644 --- a/src/Compilers/VisualBasic/Test/Emit/Emit/EditAndContinue/EditAndContinueStateMachineTests.vb +++ b/src/Compilers/VisualBasic/Test/Emit/Emit/EditAndContinue/EditAndContinueStateMachineTests.vb @@ -911,7 +911,8 @@ End Class Using md1 = diff1.GetMetadata() CheckEncLogDefinitions(md1.Reader, Row(3, TableIndex.StandAloneSig, EditAndContinueOperation.Default), - Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default)) + Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) End Using End Using End Sub @@ -958,7 +959,9 @@ End Class Using md1 = diff1.GetMetadata() CheckEncLogDefinitions(md1.Reader, Row(3, TableIndex.StandAloneSig, EditAndContinueOperation.Default), - Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default)) + Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) End Using End Using End Sub @@ -1038,15 +1041,15 @@ End Class Row(6, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(9, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(12, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(19, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(20, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(21, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(22, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(23, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(24, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(25, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(26, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(27, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(9, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(10, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(13, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(15, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(17, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) End Using End Using End Sub @@ -1101,9 +1104,9 @@ End Class Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(13, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(14, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(15, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) End Using diff1.VerifyIL("C.VB$StateMachine_1_F.MoveNext()", " @@ -1250,9 +1253,9 @@ End Class Row(4, TableIndex.StandAloneSig, EditAndContinueOperation.Default), Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(9, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(10, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(11, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) End Using diff1.VerifyIL("C.VB$StateMachine_1_F.MoveNext()", " @@ -1500,9 +1503,9 @@ End Class Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(13, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(14, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(15, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) End Using diff1.VerifyIL("C.VB$StateMachine_1_F.MoveNext()", " @@ -1614,9 +1617,9 @@ End Class Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(13, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(14, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(15, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) End Using diff1.VerifyIL("C.VB$StateMachine_1_F.MoveNext()", " @@ -1731,9 +1734,9 @@ End Class Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(13, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(14, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(15, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) End Using diff1.VerifyIL("C.VB$StateMachine_1_F.MoveNext()", " @@ -1844,9 +1847,9 @@ End Class Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(13, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(14, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(15, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) End Using diff1.VerifyIL("C.VB$StateMachine_1_F.MoveNext()", " @@ -1987,9 +1990,9 @@ End Class Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(13, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(14, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(15, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) End Using diff1.VerifyIL("C.VB$StateMachine_1_F.MoveNext()", " @@ -2134,9 +2137,9 @@ End Class Row(4, TableIndex.StandAloneSig, EditAndContinueOperation.Default), Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(9, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(10, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(11, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) End Using diff1.VerifyIL("C.VB$StateMachine_1_F.MoveNext()", " @@ -2296,9 +2299,9 @@ End Class Row(7, TableIndex.Field, EditAndContinueOperation.Default), Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(9, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(10, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(11, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) End Using diff1.VerifyIL("C.VB$StateMachine_1_F.MoveNext()", " @@ -2461,9 +2464,9 @@ End Class Row(7, TableIndex.Field, EditAndContinueOperation.Default), Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(9, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(10, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(11, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) End Using diff1.VerifyIL("C.VB$StateMachine_1_F.MoveNext()", " @@ -2622,9 +2625,9 @@ End Class Row(6, TableIndex.Field, EditAndContinueOperation.Default), Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(9, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(10, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(11, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) End Using diff1.VerifyIL("C.VB$StateMachine_1_F.MoveNext()", " @@ -2930,12 +2933,12 @@ End Class Row(3, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(6, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(9, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(19, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(20, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(21, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(22, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(23, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(24, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(13, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(15, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) diff1.VerifyIL("C.VB$StateMachine_1_F.MoveNext()", " { @@ -3048,9 +3051,9 @@ End Class Row(21, TableIndex.Field, EditAndContinueOperation.Default), Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(6, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(25, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(26, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(27, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) + Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(13, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) diff2.VerifyIL("C.VB$StateMachine_1_F.MoveNext()", " { @@ -3167,12 +3170,12 @@ End Class Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(9, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(12, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(28, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(29, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(30, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(31, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(32, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(33, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) + Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(9, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(10, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(15, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(17, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) End Sub @@ -3444,12 +3447,12 @@ End Class Row(6, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(9, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(12, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(19, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(20, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(21, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(22, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(23, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(24, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) + Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(9, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(10, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(13, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(15, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) diff1.VerifyIL("C.VB$StateMachine_4_F.MoveNext()", " { @@ -3603,9 +3606,9 @@ End Class Row(15, TableIndex.Field, EditAndContinueOperation.Default), Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(9, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(25, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(26, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(27, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) + Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(13, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) diff2.VerifyIL("C.VB$StateMachine_4_F.MoveNext()", " { @@ -3765,12 +3768,12 @@ End Class Row(7, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(12, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(15, TableIndex.MethodDef, EditAndContinueOperation.Default), - Row(28, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(29, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(30, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(31, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(32, TableIndex.CustomAttribute, EditAndContinueOperation.Default), - Row(33, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) + Row(9, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(10, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(11, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(12, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(15, TableIndex.CustomAttribute, EditAndContinueOperation.Default), + Row(17, TableIndex.CustomAttribute, EditAndContinueOperation.Default)) End Sub