From b792896096a4c87d6ce18953ad94c6243ea72b09 Mon Sep 17 00:00:00 2001 From: David Wilson Date: Mon, 15 Feb 2016 20:30:03 -0800 Subject: [PATCH] Fix #153: Script Analyzer is not returning markers This change fixes an issue in 0.4.1 where Script Analyzer analysis markers are not being returned by the AnalysisService. This issue was caused by a new optional parameter to the ScriptAnalyzer.Initialize method called 'includeDefaultRules' which was introduced in 1.3.0. Since this parameter has a default value of 'false', the default Script Analyzer rules were not being loaded or applied in analysis runs. --- .../Analysis/AnalysisService.cs | 37 +++++++++++++------ .../LanguageServerTests.cs | 16 ++++++++ .../PowerShellEditorServices.Test.Host.csproj | 3 ++ .../TestFiles/SimpleSemanticError.ps1 | 3 ++ 4 files changed, 48 insertions(+), 11 deletions(-) create mode 100644 test/PowerShellEditorServices.Test.Host/TestFiles/SimpleSemanticError.ps1 diff --git a/src/PowerShellEditorServices/Analysis/AnalysisService.cs b/src/PowerShellEditorServices/Analysis/AnalysisService.cs index a1ec5a0d4..dd46cbe4f 100644 --- a/src/PowerShellEditorServices/Analysis/AnalysisService.cs +++ b/src/PowerShellEditorServices/Analysis/AnalysisService.cs @@ -3,8 +3,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // +using Microsoft.PowerShell.EditorServices.Utility; using Microsoft.Windows.PowerShell.ScriptAnalyzer; using System; +using System.IO; using System.Linq; using System.Management.Automation.Runspaces; using System.Threading; @@ -47,17 +49,30 @@ public class AnalysisService : IDisposable /// public AnalysisService() { - this.analysisRunspace = RunspaceFactory.CreateRunspace(InitialSessionState.CreateDefault2()); - this.analysisRunspace.ApartmentState = ApartmentState.STA; - this.analysisRunspace.ThreadOptions = PSThreadOptions.ReuseThread; - this.analysisRunspace.Open(); + try + { + // Attempt to create a ScriptAnalyzer instance first + // just in case the assembly can't be found and we + // can skip creating an extra runspace. + this.scriptAnalyzer = new ScriptAnalyzer(); + + this.analysisRunspace = RunspaceFactory.CreateRunspace(InitialSessionState.CreateDefault2()); + this.analysisRunspace.ApartmentState = ApartmentState.STA; + this.analysisRunspace.ThreadOptions = PSThreadOptions.ReuseThread; + this.analysisRunspace.Open(); - this.scriptAnalyzer = new ScriptAnalyzer(); - this.scriptAnalyzer.Initialize( - this.analysisRunspace, - new AnalysisOutputWriter(), - null, - IncludedRules); + this.scriptAnalyzer.Initialize( + this.analysisRunspace, + new AnalysisOutputWriter(), + includeRuleNames: IncludedRules, + includeDefaultRules: true); + } + catch (FileNotFoundException) + { + Logger.Write( + LogLevel.Warning, + "Script Analyzer binaries not found, AnalysisService will be disabled."); + } } #endregion @@ -72,7 +87,7 @@ public AnalysisService() /// An array of ScriptFileMarkers containing semantic analysis results. public ScriptFileMarker[] GetSemanticMarkers(ScriptFile file) { - if (file.IsAnalysisEnabled) + if (this.scriptAnalyzer != null && file.IsAnalysisEnabled) { // TODO: This is a temporary fix until we can change how // ScriptAnalyzer invokes their async tasks. diff --git a/test/PowerShellEditorServices.Test.Host/LanguageServerTests.cs b/test/PowerShellEditorServices.Test.Host/LanguageServerTests.cs index a315df418..325f03677 100644 --- a/test/PowerShellEditorServices.Test.Host/LanguageServerTests.cs +++ b/test/PowerShellEditorServices.Test.Host/LanguageServerTests.cs @@ -65,6 +65,22 @@ await this.WaitForEvent( string.IsNullOrEmpty(diagnostics.Diagnostics[0].Message)); } + [Fact] + public async Task ServiceReturnsSemanticMarkers() + { + // Send the 'didOpen' event + await this.SendOpenFileEvent("TestFiles\\SimpleSemanticError.ps1", false); + + // Wait for the diagnostic event + PublishDiagnosticsNotification diagnostics = + await this.WaitForEvent( + PublishDiagnosticsNotification.Type); + + // Was there a semantic error? + Assert.NotEqual(0, diagnostics.Diagnostics.Length); + Assert.Contains("unapproved", diagnostics.Diagnostics[0].Message); + } + [Fact] public async Task ServiceCompletesFunctionName() { diff --git a/test/PowerShellEditorServices.Test.Host/PowerShellEditorServices.Test.Host.csproj b/test/PowerShellEditorServices.Test.Host/PowerShellEditorServices.Test.Host.csproj index e847cc94a..6829c0aa3 100644 --- a/test/PowerShellEditorServices.Test.Host/PowerShellEditorServices.Test.Host.csproj +++ b/test/PowerShellEditorServices.Test.Host/PowerShellEditorServices.Test.Host.csproj @@ -83,6 +83,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/test/PowerShellEditorServices.Test.Host/TestFiles/SimpleSemanticError.ps1 b/test/PowerShellEditorServices.Test.Host/TestFiles/SimpleSemanticError.ps1 new file mode 100644 index 000000000..a4956a97a --- /dev/null +++ b/test/PowerShellEditorServices.Test.Host/TestFiles/SimpleSemanticError.ps1 @@ -0,0 +1,3 @@ +function Do-Work { + # This should trigger the PSUseApprovedVerbs rule +} \ No newline at end of file