Skip to content

Commit 772317a

Browse files
committed
Fix #2 - Message types should be auto-registered
This change completes the work to have all Transport.Stdio message types be marked with a MessageTypeNameAttribute. This attribute specifies the name used to identify the type in the JSON messages that are sent between client and editor service. The MessageTypeResolver also validates whether a message type is decorated with an attribute and throws a debug assert if it is missing. This helps message type authors remember to add the attribute so that everything works correctly. Finally, all existing message types have been updated to follow the new message type decoration pattern.
1 parent bae2e93 commit 772317a

34 files changed

+694
-383
lines changed

src/PowerShellEditorServices.Transport.Stdio/Constants.cs

+17-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//
55

66
using Newtonsoft.Json;
7+
using Newtonsoft.Json.Converters;
78
using Newtonsoft.Json.Serialization;
89
using System;
910
using System.Collections.Generic;
@@ -13,13 +14,25 @@
1314

1415
namespace Microsoft.PowerShell.EditorServices.Transport.Stdio
1516
{
16-
public class Constants
17+
public static class Constants
1718
{
1819
public const string ContentLengthString = "Content-Length: ";
20+
public static readonly JsonSerializerSettings JsonSerializerSettings;
1921

20-
public static readonly JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings
22+
static Constants()
2123
{
22-
ContractResolver = new CamelCasePropertyNamesContractResolver()
23-
};
24+
JsonSerializerSettings = new JsonSerializerSettings();
25+
26+
// Camel case all object properties
27+
JsonSerializerSettings.ContractResolver =
28+
new CamelCasePropertyNamesContractResolver();
29+
30+
// Convert enum values to their string representation with camel casing
31+
JsonSerializerSettings.Converters.Add(
32+
new StringEnumConverter
33+
{
34+
CamelCaseText = true
35+
});
36+
}
2437
}
2538
}

src/PowerShellEditorServices.Transport.Stdio/Event/DiagnosticEvent.cs

+63-8
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,43 @@
33
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
44
//
55

6+
using Microsoft.PowerShell.EditorServices.Session;
7+
using Microsoft.PowerShell.EditorServices.Transport.Stdio.Message;
8+
using System.Collections.Generic;
9+
610
namespace Microsoft.PowerShell.EditorServices.Transport.Stdio.Event
711
{
8-
public class DiagnosticEvent : EventBase<DiagnosticEventBody>
12+
[MessageTypeName("syntaxDiag")]
13+
public class SyntaxDiagnosticEvent : EventBase<DiagnosticEventBody>
914
{
10-
public DiagnosticEvent()
15+
public static SyntaxDiagnosticEvent Create(
16+
string filePath,
17+
ScriptFileMarker[] syntaxMarkers)
1118
{
12-
// Initialize to an identifiable uninitialized value.
13-
// Could either be "syntaxDiag" or "semanticDiag"
14-
// This should be replaced by the deserialization process.
15-
this.EventType = "NOT_SUPPLIED";
19+
return new SyntaxDiagnosticEvent
20+
{
21+
Body =
22+
DiagnosticEventBody.Create(
23+
filePath,
24+
syntaxMarkers)
25+
};
1626
}
27+
}
1728

18-
public DiagnosticEvent(string eventType)
29+
[MessageTypeName("semanticDiag")]
30+
public class SemanticDiagnosticEvent : EventBase<DiagnosticEventBody>
31+
{
32+
public static SemanticDiagnosticEvent Create(
33+
string filePath,
34+
ScriptFileMarker[] semanticMarkers)
1935
{
20-
this.EventType = eventType;
36+
return new SemanticDiagnosticEvent
37+
{
38+
Body =
39+
DiagnosticEventBody.Create(
40+
filePath,
41+
semanticMarkers)
42+
};
2143
}
2244
}
2345

@@ -26,6 +48,39 @@ public class DiagnosticEventBody
2648
public string File { get; set; }
2749

2850
public Diagnostic[] Diagnostics { get; set; }
51+
52+
public static DiagnosticEventBody Create(
53+
string filePath,
54+
ScriptFileMarker[] diagnosticMarkers)
55+
{
56+
List<Diagnostic> diagnosticList = new List<Diagnostic>();
57+
58+
foreach (ScriptFileMarker diagnosticMarker in diagnosticMarkers)
59+
{
60+
diagnosticList.Add(
61+
new Diagnostic
62+
{
63+
Text = diagnosticMarker.Message,
64+
Start = new Location
65+
{
66+
Line = diagnosticMarker.Extent.StartLineNumber,
67+
Offset = diagnosticMarker.Extent.StartColumnNumber
68+
},
69+
End = new Location
70+
{
71+
Line = diagnosticMarker.Extent.EndLineNumber,
72+
Offset = diagnosticMarker.Extent.EndColumnNumber
73+
}
74+
});
75+
}
76+
77+
return
78+
new DiagnosticEventBody
79+
{
80+
File = filePath,
81+
Diagnostics = diagnosticList.ToArray()
82+
};
83+
}
2984
}
3085

3186
public class Location

src/PowerShellEditorServices.Transport.Stdio/Event/Eventbase.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
namespace Microsoft.PowerShell.EditorServices.Transport.Stdio.Event
1010
{
11-
public abstract class EventBase<TBody> : MessageBase, IEvent
11+
public abstract class EventBase<TBody> : MessageBase
1212
{
1313
[JsonProperty("event")]
1414
public string EventType { get; set; }
@@ -18,11 +18,12 @@ public abstract class EventBase<TBody> : MessageBase, IEvent
1818
internal override string PayloadType
1919
{
2020
get { return this.EventType; }
21+
set { this.EventType = value; }
2122
}
2223

2324
public EventBase()
2425
{
25-
this.Type = "event";
26+
this.Type = MessageType.Event;
2627
}
2728
}
2829
}

src/PowerShellEditorServices.Transport.Stdio/Event/IEvent.cs

-12
This file was deleted.

src/PowerShellEditorServices.Transport.Stdio/Event/ReplPromptChoiceEvent.cs

+2-4
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,14 @@
33
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
44
//
55

6+
using Microsoft.PowerShell.EditorServices.Transport.Stdio.Message;
67
using System.Management.Automation.Host;
78

89
namespace Microsoft.PowerShell.EditorServices.Transport.Stdio.Event
910
{
11+
[MessageTypeName("replPromptChoice")]
1012
public class ReplPromptChoiceEvent : EventBase<ReplPromptChoiceEventBody>
1113
{
12-
public ReplPromptChoiceEvent()
13-
{
14-
this.EventType = "replPromptChoice";
15-
}
1614
}
1715

1816
public class ReplPromptChoiceEventBody

src/PowerShellEditorServices.Transport.Stdio/Event/ReplWriteOutputEvent.cs

+2-4
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,14 @@
44
//
55

66
using Microsoft.PowerShell.EditorServices.Console;
7+
using Microsoft.PowerShell.EditorServices.Transport.Stdio.Message;
78
using System;
89

910
namespace Microsoft.PowerShell.EditorServices.Transport.Stdio.Event
1011
{
12+
[MessageTypeName("replWriteOutput")]
1113
public class ReplWriteOutputEvent : EventBase<ReplWriteOutputEventBody>
1214
{
13-
public ReplWriteOutputEvent()
14-
{
15-
this.EventType = "replWriteOutput";
16-
}
1715
}
1816

1917
public class ReplWriteOutputEventBody

src/PowerShellEditorServices.Transport.Stdio/Event/StartedEvent.cs

+3-4
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@
33
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
44
//
55

6+
using Microsoft.PowerShell.EditorServices.Transport.Stdio.Message;
7+
68
namespace Microsoft.PowerShell.EditorServices.Transport.Stdio.Event
79
{
10+
[MessageTypeName("started")]
811
public class StartedEvent : EventBase<object>
912
{
10-
public StartedEvent()
11-
{
12-
this.EventType = "started";
13-
}
1413
}
1514
}

src/PowerShellEditorServices.Transport.Stdio/Message/IMessage.cs

-25
This file was deleted.

src/PowerShellEditorServices.Transport.Stdio/Message/MessageBase.cs

+7-4
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
44
//
55

6+
using Newtonsoft.Json;
7+
using Newtonsoft.Json.Converters;
8+
69
namespace Microsoft.PowerShell.EditorServices.Transport.Stdio.Message
710
{
811
/// <summary>
912
/// Provides the base class for all message types in the
1013
/// standard I/O protocol.
1114
/// </summary>
12-
public abstract class MessageBase : IMessage
15+
public abstract class MessageBase
1316
{
1417
/// <summary>
1518
/// Gets or sets the sequence identifier for this message.
@@ -19,13 +22,13 @@ public abstract class MessageBase : IMessage
1922
/// <summary>
2023
/// Gets or sets the string identifying the type of this message.
2124
/// </summary>
22-
public string Type { get; set; }
25+
public MessageType Type { get; set; }
2326

2427
/// <summary>
25-
/// Gets the payload type name of this message. Subclasses
28+
/// Gets or sets the payload type name of this message. Subclasses
2629
/// will use this to generalize access to the property that
2730
/// identifies its protocol payload type.
2831
/// </summary>
29-
internal abstract string PayloadType { get; }
32+
internal abstract string PayloadType { get; set; }
3033
}
3134
}

0 commit comments

Comments
 (0)