Skip to content

Commit 4b4910b

Browse files
committed
Invoke Created action from HotReloadException constructor
1 parent 5d9db59 commit 4b4910b

File tree

4 files changed

+600
-187
lines changed

4 files changed

+600
-187
lines changed

src/Compilers/CSharp/Portable/Emitter/EditAndContinue/PEDeltaAssemblyBuilder.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,11 +329,12 @@ private SynthesizedHotReloadExceptionSymbol GetOrCreateSynthesizedHotReloadExcep
329329
}
330330

331331
var exceptionType = Compilation.GetWellKnownType(WellKnownType.System_Exception);
332+
var actionOfTType = Compilation.GetWellKnownType(WellKnownType.System_Action_T);
332333
var stringType = Compilation.GetSpecialType(SpecialType.System_String);
333334
var intType = Compilation.GetSpecialType(SpecialType.System_Int32);
334335

335336
var containingNamespace = GetOrSynthesizeNamespace(SynthesizedHotReloadExceptionSymbol.NamespaceName);
336-
symbol = new SynthesizedHotReloadExceptionSymbol(containingNamespace, exceptionType, stringType, intType);
337+
symbol = new SynthesizedHotReloadExceptionSymbol(containingNamespace, exceptionType, actionOfTType, stringType, intType);
337338

338339
Interlocked.CompareExchange(ref _lazyHotReloadExceptionType, symbol, comparand: null);
339340
return _lazyHotReloadExceptionType;

src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedHotReloadExceptionConstructorSymbol.cs

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,44 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState,
5252
return;
5353
}
5454

55+
var delegateInvoke = (containingType.CreatedActionField.Type as NamedTypeSymbol)?.DelegateInvokeMethod;
56+
if (delegateInvoke is null)
57+
{
58+
diagnostics.Add(ErrorCode.ERR_EncUpdateFailedMissingSymbol,
59+
Location.None,
60+
CodeAnalysisResources.Method,
61+
"System.Delegate.Invoke");
62+
63+
factory.CloseMethod(factory.Block());
64+
return;
65+
}
66+
67+
var actionTemp = factory.StoreToTemp(
68+
factory.Field(receiver: null, containingType.CreatedActionField),
69+
out var storeAction);
70+
5571
var block = factory.Block(
56-
ImmutableArray.Create<BoundStatement>(
57-
factory.ExpressionStatement(factory.Call(
58-
factory.This(),
59-
exceptionConstructor,
60-
factory.Parameter(MessageParameter))),
61-
factory.Assignment(factory.Field(factory.This(), containingType.CodeField), factory.Parameter(CodeParameter)),
62-
factory.Return()
63-
));
72+
[actionTemp.LocalSymbol],
73+
74+
// base(message)
75+
factory.ExpressionStatement(factory.Call(
76+
factory.This(),
77+
exceptionConstructor,
78+
factory.Parameter(MessageParameter))),
79+
80+
// this.CodeField = code;
81+
factory.Assignment(factory.Field(factory.This(), containingType.CodeField), factory.Parameter(CodeParameter)),
82+
83+
// s_created?.Invoke(this);
84+
factory.If(
85+
factory.IsNotNullReference(storeAction),
86+
factory.ExpressionStatement(
87+
factory.Call(
88+
actionTemp,
89+
delegateInvoke,
90+
factory.This()))),
91+
92+
factory.Return());
6493

6594
factory.CloseMethod(block);
6695
}

src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedHotReloadExceptionSymbol.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ internal sealed class SynthesizedHotReloadExceptionSymbol : NamedTypeSymbol
2222
public const string TypeName = "HotReloadException";
2323
public const string CodeFieldName = "Code";
2424

25+
/// <summary>
26+
/// The Hot Reload agent that's injected into the application needs to intercept creation of a runtime rude edit.
27+
/// It uses reflection to set this action field.
28+
/// </summary>
29+
public const string CreatedActionFieldName = "Created";
30+
2531
private readonly NamedTypeSymbol _baseType;
2632
private readonly NamespaceSymbol _namespace;
2733

@@ -31,6 +37,7 @@ internal sealed class SynthesizedHotReloadExceptionSymbol : NamedTypeSymbol
3137
public SynthesizedHotReloadExceptionSymbol(
3238
NamespaceSymbol containingNamespace,
3339
NamedTypeSymbol exceptionType,
40+
NamedTypeSymbol actionOfTType,
3441
TypeSymbol stringType,
3542
TypeSymbol intType)
3643
{
@@ -40,7 +47,8 @@ public SynthesizedHotReloadExceptionSymbol(
4047
_members =
4148
[
4249
new SynthesizedHotReloadExceptionConstructorSymbol(this, stringType, intType),
43-
new SynthesizedFieldSymbol(this, intType, CodeFieldName, isPublic: true, isReadOnly: true, isStatic: false)
50+
new SynthesizedFieldSymbol(this, intType, CodeFieldName, isPublic: true, isReadOnly: true, isStatic: false),
51+
new SynthesizedFieldSymbol(this, actionOfTType.Construct(exceptionType), CreatedActionFieldName, isPublic: false, isReadOnly: false, isStatic: true)
4452
];
4553
}
4654

@@ -50,6 +58,9 @@ public MethodSymbol Constructor
5058
public FieldSymbol CodeField
5159
=> (FieldSymbol)_members[1];
5260

61+
public FieldSymbol CreatedActionField
62+
=> (FieldSymbol)_members[2];
63+
5364
public override ImmutableArray<Symbol> GetMembers()
5465
=> _members;
5566

@@ -58,14 +69,15 @@ public override ImmutableArray<Symbol> GetMembers(string name)
5869
{
5970
WellKnownMemberNames.InstanceConstructorName => [Constructor],
6071
CodeFieldName => [CodeField],
72+
CreatedActionFieldName => [CreatedActionField],
6173
_ => []
6274
};
6375

6476
public override IEnumerable<string> MemberNames
6577
=> _members.Select(static m => m.Name);
6678

6779
internal override IEnumerable<FieldSymbol> GetFieldsToEmit()
68-
=> [CodeField];
80+
=> [CodeField, CreatedActionField];
6981

7082
public override ImmutableArray<NamedTypeSymbol> GetTypeMembers() => [];
7183
public override ImmutableArray<NamedTypeSymbol> GetTypeMembers(ReadOnlyMemory<char> name) => [];

0 commit comments

Comments
 (0)