Skip to content

Commit 1f3df7a

Browse files
authored
Merge pull request #311 from PowerShell/kapilmb/UpdatablePSSARules
Make PSSA includerule list updatable
2 parents d342685 + f298def commit 1f3df7a

File tree

6 files changed

+171
-18
lines changed

6 files changed

+171
-18
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// Copyright (c) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4+
//
5+
6+
using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol;
7+
8+
namespace Microsoft.PowerShell.EditorServices.Protocol.LanguageServer
9+
{
10+
class GetPSSARulesRequest
11+
{
12+
public static readonly
13+
RequestType<string, object> Type =
14+
RequestType<string, object>.Create("powerShell/getPSSARules");
15+
}
16+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// Copyright (c) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4+
//
5+
6+
using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol;
7+
8+
namespace Microsoft.PowerShell.EditorServices.Protocol.LanguageServer
9+
{
10+
class SetPSSARulesRequest
11+
{
12+
public static readonly
13+
RequestType<object, object> Type =
14+
RequestType<object, object>.Create("powerShell/setPSSARules");
15+
}
16+
}

src/PowerShellEditorServices.Protocol/PowerShellEditorServices.Protocol.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,13 @@
5555
<Compile Include="DebugAdapter\ContinueRequest.cs" />
5656
<Compile Include="DebugAdapter\SetFunctionBreakpointsRequest.cs" />
5757
<Compile Include="DebugAdapter\SetVariableRequest.cs" />
58+
<Compile Include="LanguageServer\GetPSSARulesRequest.cs" />
5859
<Compile Include="LanguageServer\EditorCommands.cs" />
5960
<Compile Include="LanguageServer\CodeAction.cs" />
6061
<Compile Include="LanguageServer\FindModuleRequest.cs" />
6162
<Compile Include="LanguageServer\InstallModuleRequest.cs" />
6263
<Compile Include="LanguageServer\PowerShellVersionRequest.cs" />
64+
<Compile Include="LanguageServer\SetPSSARulesRequest.cs" />
6365
<Compile Include="MessageProtocol\Channel\NamedPipeClientChannel.cs" />
6466
<Compile Include="MessageProtocol\Channel\NamedPipeServerChannel.cs" />
6567
<Compile Include="MessageProtocol\Channel\TcpSocketClientChannel.cs" />

src/PowerShellEditorServices.Protocol/Server/LanguageServer.cs

Lines changed: 95 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ protected override void Initialize()
109109

110110
this.SetRequestHandler(DebugAdapterMessages.EvaluateRequest.Type, this.HandleEvaluateRequest);
111111

112+
this.SetRequestHandler(GetPSSARulesRequest.Type, this.HandleGetPSSARulesRequest);
113+
this.SetRequestHandler(SetPSSARulesRequest.Type, this.HandleSetPSSARulesRequest);
114+
112115
// Initialize the extension service
113116
// TODO: This should be made awaited once Initialize is async!
114117
this.editorSession.ExtensionService.Initialize(
@@ -180,6 +183,55 @@ protected async Task HandleShowOnlineHelpRequest(
180183
await requestContext.SendResult(null);
181184
}
182185

186+
private async Task HandleSetPSSARulesRequest(
187+
object param,
188+
RequestContext<object> requestContext)
189+
{
190+
var dynParams = param as dynamic;
191+
if (editorSession.AnalysisService != null &&
192+
editorSession.AnalysisService.SettingsPath == null)
193+
{
194+
var activeRules = new List<string>();
195+
var ruleInfos = dynParams.ruleInfos;
196+
foreach (dynamic ruleInfo in ruleInfos)
197+
{
198+
if ((Boolean) ruleInfo.isEnabled)
199+
{
200+
activeRules.Add((string) ruleInfo.name);
201+
}
202+
}
203+
editorSession.AnalysisService.ActiveRules = activeRules.ToArray();
204+
}
205+
206+
var sendresult = requestContext.SendResult(null);
207+
var scripFile = editorSession.Workspace.GetFile((string)dynParams.filepath);
208+
await RunScriptDiagnostics(
209+
new ScriptFile[] { scripFile },
210+
editorSession,
211+
requestContext.SendEvent);
212+
await sendresult;
213+
}
214+
215+
private async Task HandleGetPSSARulesRequest(
216+
object param,
217+
RequestContext<object> requestContext)
218+
{
219+
List<object> rules = null;
220+
if (editorSession.AnalysisService != null
221+
&& editorSession.AnalysisService.SettingsPath == null)
222+
{
223+
rules = new List<object>();
224+
var ruleNames = editorSession.AnalysisService.GetPSScriptAnalyzerRules();
225+
var activeRules = editorSession.AnalysisService.ActiveRules;
226+
foreach (var ruleName in ruleNames)
227+
{
228+
rules.Add(new { name = ruleName, isEnabled = activeRules.Contains(ruleName, StringComparer.OrdinalIgnoreCase) });
229+
}
230+
}
231+
232+
await requestContext.SendResult(rules);
233+
}
234+
183235
private async Task HandleInstallModuleRequest(
184236
string moduleName,
185237
RequestContext<object> requestContext
@@ -964,6 +1016,14 @@ private Task RunScriptDiagnostics(
9641016
ScriptFile[] filesToAnalyze,
9651017
EditorSession editorSession,
9661018
EventContext eventContext)
1019+
{
1020+
return RunScriptDiagnostics(filesToAnalyze, editorSession, eventContext.SendEvent);
1021+
}
1022+
1023+
private Task RunScriptDiagnostics(
1024+
ScriptFile[] filesToAnalyze,
1025+
EditorSession editorSession,
1026+
Func<EventType<PublishDiagnosticsNotification>, PublishDiagnosticsNotification, Task> eventSender)
9671027
{
9681028
if (!this.currentSettings.ScriptAnalysis.Enable.Value)
9691029
{
@@ -1011,7 +1071,7 @@ private Task RunScriptDiagnostics(
10111071
filesToAnalyze,
10121072
this.codeActionsPerFile,
10131073
editorSession,
1014-
eventContext,
1074+
eventSender,
10151075
existingRequestCancellation.Token),
10161076
CancellationToken.None,
10171077
TaskCreationOptions.None,
@@ -1020,13 +1080,32 @@ private Task RunScriptDiagnostics(
10201080
return Task.FromResult(true);
10211081
}
10221082

1083+
10231084
private static async Task DelayThenInvokeDiagnostics(
10241085
int delayMilliseconds,
10251086
ScriptFile[] filesToAnalyze,
10261087
Dictionary<string, Dictionary<string, MarkerCorrection>> correctionIndex,
10271088
EditorSession editorSession,
10281089
EventContext eventContext,
10291090
CancellationToken cancellationToken)
1091+
{
1092+
await DelayThenInvokeDiagnostics(
1093+
delayMilliseconds,
1094+
filesToAnalyze,
1095+
correctionIndex,
1096+
editorSession,
1097+
eventContext.SendEvent,
1098+
cancellationToken);
1099+
}
1100+
1101+
1102+
private static async Task DelayThenInvokeDiagnostics(
1103+
int delayMilliseconds,
1104+
ScriptFile[] filesToAnalyze,
1105+
Dictionary<string, Dictionary<string, MarkerCorrection>> correctionIndex,
1106+
EditorSession editorSession,
1107+
Func<EventType<PublishDiagnosticsNotification>, PublishDiagnosticsNotification, Task> eventSender,
1108+
CancellationToken cancellationToken)
10301109
{
10311110
// First of all, wait for the desired delay period before
10321111
// analyzing the provided list of files
@@ -1072,7 +1151,7 @@ await PublishScriptDiagnostics(
10721151
scriptFile,
10731152
semanticMarkers,
10741153
correctionIndex,
1075-
eventContext);
1154+
eventSender);
10761155
}
10771156
}
10781157

@@ -1081,6 +1160,19 @@ private static async Task PublishScriptDiagnostics(
10811160
ScriptFileMarker[] semanticMarkers,
10821161
Dictionary<string, Dictionary<string, MarkerCorrection>> correctionIndex,
10831162
EventContext eventContext)
1163+
{
1164+
await PublishScriptDiagnostics(
1165+
scriptFile,
1166+
semanticMarkers,
1167+
correctionIndex,
1168+
eventContext.SendEvent);
1169+
}
1170+
1171+
private static async Task PublishScriptDiagnostics(
1172+
ScriptFile scriptFile,
1173+
ScriptFileMarker[] semanticMarkers,
1174+
Dictionary<string, Dictionary<string, MarkerCorrection>> correctionIndex,
1175+
Func<EventType<PublishDiagnosticsNotification>, PublishDiagnosticsNotification, Task> eventSender)
10841176
{
10851177
List<Diagnostic> diagnostics = new List<Diagnostic>();
10861178

@@ -1104,7 +1196,7 @@ private static async Task PublishScriptDiagnostics(
11041196

11051197
// Always send syntax and semantic errors. We want to
11061198
// make sure no out-of-date markers are being displayed.
1107-
await eventContext.SendEvent(
1199+
await eventSender(
11081200
PublishDiagnosticsNotification.Type,
11091201
new PublishDiagnosticsNotification
11101202
{

src/PowerShellEditorServices/Analysis/AnalysisService.cs

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ public class AnalysisService : IDisposable
5151

5252
#region Properties
5353

54+
/// <summary>
55+
/// Set of PSScriptAnalyzer rules used for analysis
56+
/// </summary>
57+
public string[] ActiveRules { get; set; }
58+
5459
/// <summary>
5560
/// Gets or sets the path to a settings file (.psd1)
5661
/// containing PSScriptAnalyzer settings.
@@ -79,6 +84,7 @@ public AnalysisService(IConsoleHost consoleHost, string settingsPath = null)
7984
this.analysisRunspace = RunspaceFactory.CreateRunspace(InitialSessionState.CreateDefault2());
8085
this.analysisRunspace.ThreadOptions = PSThreadOptions.ReuseThread;
8186
this.analysisRunspace.Open();
87+
ActiveRules = IncludedRules.ToArray();
8288
InitializePSScriptAnalyzer();
8389
}
8490
catch (Exception e)
@@ -129,6 +135,28 @@ public ScriptFileMarker[] GetSemanticMarkers(ScriptFile file)
129135
}
130136
}
131137

138+
/// <summary>
139+
/// Returns a list of builtin-in PSScriptAnalyzer rules
140+
/// </summary>
141+
public IEnumerable<string> GetPSScriptAnalyzerRules()
142+
{
143+
List<string> ruleNames = new List<string>();
144+
if (scriptAnalyzerModuleInfo != null)
145+
{
146+
using (var ps = System.Management.Automation.PowerShell.Create())
147+
{
148+
ps.Runspace = this.analysisRunspace;
149+
var ruleObjects = ps.AddCommand("Get-ScriptAnalyzerRule").Invoke();
150+
foreach (var rule in ruleObjects)
151+
{
152+
ruleNames.Add((string)rule.Members["RuleName"].Value);
153+
}
154+
}
155+
}
156+
157+
return ruleNames;
158+
}
159+
132160
/// <summary>
133161
/// Disposes the runspace being used by the analysis service.
134162
/// </summary>
@@ -207,23 +235,16 @@ private void EnumeratePSScriptAnalyzerRules()
207235
{
208236
if (scriptAnalyzerModuleInfo != null)
209237
{
210-
using (var ps = System.Management.Automation.PowerShell.Create())
238+
var rules = GetPSScriptAnalyzerRules();
239+
var sb = new StringBuilder();
240+
sb.AppendLine("Available PSScriptAnalyzer Rules:");
241+
foreach (var rule in rules)
211242
{
212-
ps.Runspace = this.analysisRunspace;
213-
214-
var rules = ps.AddCommand("Get-ScriptAnalyzerRule").Invoke();
215-
var sb = new StringBuilder();
216-
sb.AppendLine("Available PSScriptAnalyzer Rules:");
217-
218-
foreach (var rule in rules)
219-
{
220-
sb.AppendLine((string)rule.Members["RuleName"].Value);
221-
}
222-
223-
Logger.Write(LogLevel.Verbose, sb.ToString());
243+
sb.AppendLine(rule);
224244
}
225-
}
226245

246+
Logger.Write(LogLevel.Verbose, sb.ToString());
247+
}
227248
}
228249

229250
private void InitializePSScriptAnalyzer()
@@ -257,7 +278,7 @@ private IEnumerable<PSObject> GetDiagnosticRecords(ScriptFile file)
257278
}
258279
else
259280
{
260-
powerShell.AddParameter("IncludeRule", IncludedRules);
281+
powerShell.AddParameter("IncludeRule", ActiveRules);
261282
}
262283

263284
diagnosticRecords = powerShell.Invoke();

src/PowerShellEditorServices/Nano.PowerShellEditorServices.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@
3636
<DocumentationFile>bin\Release\Microsoft.PowerShell.EditorServices.XML</DocumentationFile>
3737
</PropertyGroup>
3838
<ItemGroup>
39+
<Compile Include="..\PowerShellEditorServices.Protocol\LanguageServer\GetPSSARulesRequest.cs">
40+
<Link>GetPSSARulesRequest.cs</Link>
41+
</Compile>
42+
<Compile Include="..\PowerShellEditorServices.Protocol\LanguageServer\SetPSSARulesRequest.cs">
43+
<Link>SetPSSARulesRequest.cs</Link>
44+
</Compile>
3945
<Compile Include="Analysis\AnalysisOutputWriter.cs" />
4046
<Compile Include="Analysis\AnalysisService.cs" />
4147
<Compile Include="Console\ChoicePromptHandler.cs" />

0 commit comments

Comments
 (0)