Skip to content

PowerShell v3/v4 Support #103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jan 4, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ public void Stop()
{
// By disposing the thread we cancel all existing work
// and cause the thread to be destroyed.
this.messageLoopThread.Dispose();
if (this.messageLoopThread != null)
this.messageLoopThread.Dispose();
}

public void SetRequestHandler<TParams, TResult>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ public void Stop()
this.OnStop();

this.serverChannel.Stop();
this.serverExitedTask.SetResult(true);
if (this.serverExitedTask != null)
this.serverExitedTask.SetResult(true);
}
}

Expand Down
19 changes: 14 additions & 5 deletions src/PowerShellEditorServices/Language/AstOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,13 +176,22 @@ static public SymbolReference FindDefinitionOfSymbol(
/// Finds all symbols in a script
/// </summary>
/// <param name="scriptAst">The abstract syntax tree of the given script</param>
/// <param name="powerShellVersion">The PowerShell version the Ast was generated from</param>
/// <returns>A collection of SymbolReference objects</returns>
static public IEnumerable<SymbolReference> FindSymbolsInDocument(Ast scriptAst)
static public IEnumerable<SymbolReference> FindSymbolsInDocument(Ast scriptAst, Version powerShellVersion)
{
FindSymbolsVisitor findSymbolsVisitor = new FindSymbolsVisitor();
scriptAst.Visit(findSymbolsVisitor);

return findSymbolsVisitor.SymbolReferences;
if (powerShellVersion >= new Version(5,0))
{
FindSymbolsVisitor2 findSymbolsVisitor = new FindSymbolsVisitor2();
scriptAst.Visit(findSymbolsVisitor);
return findSymbolsVisitor.SymbolReferences;
}
else
{
FindSymbolsVisitor findSymbolsVisitor = new FindSymbolsVisitor();
scriptAst.Visit(findSymbolsVisitor);
return findSymbolsVisitor.SymbolReferences;
}
}

/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions src/PowerShellEditorServices/Language/CompletionResults.cs
Original file line number Diff line number Diff line change
Expand Up @@ -275,8 +275,10 @@ private static CompletionType ConvertCompletionResultType(
case CompletionResultType.Type:
return CompletionType.Type;

#if !PowerShellv3
case CompletionResultType.Keyword:
return CompletionType.Keyword;
#endif

case CompletionResultType.ProviderContainer:
case CompletionResultType.ProviderItem:
Expand Down
2 changes: 1 addition & 1 deletion src/PowerShellEditorServices/Language/FindSymbolVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Microsoft.PowerShell.EditorServices
/// <summary>
/// The visitor used to find the the symbol at a specfic location in the AST
/// </summary>
internal class FindSymbolVisitor : AstVisitor2
internal class FindSymbolVisitor : AstVisitor
{
private int lineNumber;
private int columnNumber;
Expand Down
25 changes: 5 additions & 20 deletions src/PowerShellEditorServices/Language/FindSymbolsVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ namespace Microsoft.PowerShell.EditorServices
/// <summary>
/// The visitor used to find all the symbols (function and class defs) in the AST.
/// </summary>
internal class FindSymbolsVisitor : AstVisitor2
/// <remarks>
/// Requires PowerShell v3 or higher
/// </remarks>
internal class FindSymbolsVisitor : AstVisitor
{
public List<SymbolReference> SymbolReferences { get; private set; }

Expand Down Expand Up @@ -68,25 +71,7 @@ public override AstVisitAction VisitVariableExpression(VariableExpressionAst var

return AstVisitAction.Continue;
}

public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst)
{
IScriptExtent nameExtent = new ScriptExtent() {
Text = configurationDefinitionAst.InstanceName.Extent.Text,
StartLineNumber = configurationDefinitionAst.Extent.StartLineNumber,
EndLineNumber = configurationDefinitionAst.Extent.EndLineNumber,
StartColumnNumber = configurationDefinitionAst.Extent.StartColumnNumber,
EndColumnNumber = configurationDefinitionAst.Extent.EndColumnNumber
};

this.SymbolReferences.Add(
new SymbolReference(
SymbolType.Configuration,
nameExtent));

return AstVisitAction.Continue;
}


private bool IsAssignedAtScriptScope(VariableExpressionAst variableExpressionAst)
{
Ast parent = variableExpressionAst.Parent;
Expand Down
70 changes: 70 additions & 0 deletions src/PowerShellEditorServices/Language/FindSymbolsVisitor2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using System.Collections.Generic;
using System.Management.Automation.Language;

namespace Microsoft.PowerShell.EditorServices
{
/// <summary>
/// The visitor used to find all the symbols (function and class defs) in the AST.
/// </summary>
/// <remarks>
/// Requires PowerShell v5 or higher
/// </remarks>
internal class FindSymbolsVisitor2 : AstVisitor2
{
private FindSymbolsVisitor findSymbolsVisitor;

public List<SymbolReference> SymbolReferences
{
get
{
return this.findSymbolsVisitor.SymbolReferences;
}
}

public FindSymbolsVisitor2()
{
this.findSymbolsVisitor = new FindSymbolsVisitor();
}

/// <summary>
/// Adds each function defintion as a
/// </summary>
/// <param name="functionDefinitionAst">A functionDefinitionAst object in the script's AST</param>
/// <returns>A decision to stop searching if the right symbol was found,
/// or a decision to continue if it wasn't found</returns>
public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
{
return this.findSymbolsVisitor.VisitFunctionDefinition(functionDefinitionAst);
}

/// <summary>
/// Checks to see if this variable expression is the symbol we are looking for.
/// </summary>
/// <param name="variableExpressionAst">A VariableExpressionAst object in the script's AST</param>
/// <returns>A descion to stop searching if the right symbol was found,
/// or a decision to continue if it wasn't found</returns>
public override AstVisitAction VisitVariableExpression(VariableExpressionAst variableExpressionAst)
{
return this.findSymbolsVisitor.VisitVariableExpression(variableExpressionAst);
}

public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst)
{
IScriptExtent nameExtent = new ScriptExtent()
{
Text = configurationDefinitionAst.InstanceName.Extent.Text,
StartLineNumber = configurationDefinitionAst.Extent.StartLineNumber,
EndLineNumber = configurationDefinitionAst.Extent.EndLineNumber,
StartColumnNumber = configurationDefinitionAst.Extent.StartColumnNumber,
EndColumnNumber = configurationDefinitionAst.Extent.EndColumnNumber
};

this.findSymbolsVisitor.SymbolReferences.Add(
new SymbolReference(
SymbolType.Configuration,
nameExtent));

return AstVisitAction.Continue;
}
}
}
2 changes: 1 addition & 1 deletion src/PowerShellEditorServices/Language/LanguageService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ public FindOccurrencesResult FindSymbolsInFile(ScriptFile scriptFile)

IEnumerable<SymbolReference> symbolReferencesinFile =
AstOperations
.FindSymbolsInDocument(scriptFile.ScriptAst)
.FindSymbolsInDocument(scriptFile.ScriptAst, this.powerShellContext.PowerShellVersion)
.Select(
reference => {
reference.SourceLine =
Expand Down
10 changes: 7 additions & 3 deletions src/PowerShellEditorServices/PowerShellEditorServices.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<DefineConstants Condition=" '$(PowerShellVersion)' == 'v3'">PowerShellv3</DefineConstants>
<DefineConstants Condition=" '$(PowerShellVersion)' == 'v4'">PowerShellv4</DefineConstants>
<DefineConstants Condition=" '$(PowerShellVersion)' == '' Or '$(PowerShellVersion)' == 'v5'">PowerShellv5</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DefineConstants>TRACE;DEBUG;$(DefineConstants)</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\Microsoft.PowerShell.EditorServices.XML</DocumentationFile>
Expand All @@ -28,7 +31,7 @@
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<DefineConstants>TRACE;$(DefineConstants)</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<WarningsAsErrors>1591,1573,1572</WarningsAsErrors>
Expand All @@ -49,12 +52,12 @@
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Management.Automation" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="System.Management.Automation" />
</ItemGroup>
<ItemGroup>
<Compile Include="Analysis\AnalysisOutputWriter.cs" />
Expand All @@ -76,6 +79,7 @@
<Compile Include="Language\FindReferencesResult.cs" />
<Compile Include="Language\FindReferencesVisitor.cs" />
<Compile Include="Language\FindSymbolsVisitor.cs" />
<Compile Include="Language\FindSymbolsVisitor2.cs" />
<Compile Include="Language\FindSymbolVisitor.cs" />
<Compile Include="Language\GetDefinitionResult.cs" />
<Compile Include="Language\LanguageService.cs" />
Expand Down
49 changes: 46 additions & 3 deletions src/PowerShellEditorServices/Session/PowerShellContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

namespace Microsoft.PowerShell.EditorServices
{
using System.Collections;
using System.Management.Automation;
using System.Management.Automation.Host;
using System.Management.Automation.Runspaces;
Expand Down Expand Up @@ -68,6 +69,14 @@ public PowerShellContextState SessionState
private set;
}

/// <summary>
/// PowerShell Version of the current runspace.
/// </summary>
public Version PowerShellVersion
{
get; private set;
}

#endregion

#region Constructors
Expand Down Expand Up @@ -109,7 +118,7 @@ private void Initialize(Runspace initialRunspace)

this.initialRunspace = initialRunspace;
this.currentRunspace = initialRunspace;
this.currentRunspace.Debugger.SetDebugMode(DebugModes.LocalScript | DebugModes.RemoteScript);

this.currentRunspace.Debugger.BreakpointUpdated += OnBreakpointUpdated;
this.currentRunspace.Debugger.DebuggerStop += OnDebuggerStop;

Expand All @@ -120,9 +129,38 @@ private void Initialize(Runspace initialRunspace)
// TODO: Should this be configurable?
this.SetExecutionPolicy(ExecutionPolicy.RemoteSigned);

PowerShellVersion = GetPowerShellVersion();

#if !PowerShellv3
if (PowerShellVersion > new Version(3,0))
{
this.currentRunspace.Debugger.SetDebugMode(DebugModes.LocalScript | DebugModes.RemoteScript);
}
#endif

this.SessionState = PowerShellContextState.Ready;
}

private Version GetPowerShellVersion()
{
try
{
var psVersionTable = this.currentRunspace.SessionStateProxy.GetVariable("PSVersionTable") as Hashtable;
if (psVersionTable != null)
{
var version = psVersionTable["PSVersion"] as Version;
if (version == null) return new Version(5, 0);
return version;
}
}
catch (Exception ex)
{
Logger.Write(LogLevel.Warning, "Failed to look up PowerShell version. Defaulting to version 5. " + ex.Message);
}

return new Version(5, 0);
}

#endregion

#region Public Methods
Expand Down Expand Up @@ -370,7 +408,12 @@ internal void BreakExecution()
{
Logger.Write(LogLevel.Verbose, "Debugger break requested...");

this.currentRunspace.Debugger.SetDebuggerStepMode(true);
#if PowerShellv5
if (PowerShellVersion >= new Version(5, 0))
{
this.currentRunspace.Debugger.SetDebuggerStepMode(true);
}
#endif
}

internal void ResumeDebugger(DebuggerResumeAction resumeAction)
Expand Down Expand Up @@ -568,7 +611,7 @@ private static string GetStringForPSCommand(PSCommand psCommand)

return stringBuilder.ToString();
}

private void SetExecutionPolicy(ExecutionPolicy desiredExecutionPolicy)
{
var currentPolicy = ExecutionPolicy.Undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@
using Microsoft.PowerShell.EditorServices.Test.Shared.References;
using Microsoft.PowerShell.EditorServices.Test.Shared.SymbolDetails;
using Microsoft.PowerShell.EditorServices.Test.Shared.Symbols;
using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management.Automation.Runspaces;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;
using Xunit;

namespace Microsoft.PowerShell.EditorServices.Test.Language
Expand All @@ -25,6 +28,7 @@ public class LanguageServiceTests : IDisposable
private Workspace workspace;
private LanguageService languageService;
private PowerShellContext powerShellContext;


public LanguageServiceTests()
{
Expand Down Expand Up @@ -262,6 +266,7 @@ public void LanguageServiceFindsSymbolsInFile()
Assert.Equal(4, symbolsResult.FoundOccurrences.Where(r => r.SymbolType == SymbolType.Function).Count());
Assert.Equal(3, symbolsResult.FoundOccurrences.Where(r => r.SymbolType == SymbolType.Variable).Count());
Assert.Equal(1, symbolsResult.FoundOccurrences.Where(r => r.SymbolType == SymbolType.Workflow).Count());
Assert.Equal(1, symbolsResult.FoundOccurrences.Where(r => r.SymbolType == SymbolType.Configuration).Count());

SymbolReference firstFunctionSymbol = symbolsResult.FoundOccurrences.Where(r => r.SymbolType == SymbolType.Function).First();
Assert.Equal("AFunction", firstFunctionSymbol.SymbolName);
Expand All @@ -277,6 +282,11 @@ public void LanguageServiceFindsSymbolsInFile()
Assert.Equal("AWorkflow", firstWorkflowSymbol.SymbolName);
Assert.Equal(23, firstWorkflowSymbol.ScriptRegion.StartLineNumber);
Assert.Equal(1, firstWorkflowSymbol.ScriptRegion.StartColumnNumber);

SymbolReference firstConfigurationSymbol = symbolsResult.FoundOccurrences.Where(r => r.SymbolType == SymbolType.Configuration).First();
Assert.Equal("AConfiguration", firstConfigurationSymbol.SymbolName);
Assert.Equal(25, firstConfigurationSymbol.ScriptRegion.StartLineNumber);
Assert.Equal(1, firstConfigurationSymbol.ScriptRegion.StartColumnNumber);
}

[Fact]
Expand All @@ -289,6 +299,7 @@ public void LanguageServiceFindsSymbolsInNoSymbolsFile()
Assert.Equal(0, symbolsResult.FoundOccurrences.Count());
}


private ScriptFile GetScriptFile(ScriptRegion scriptRegion)
{
const string baseSharedScriptPath =
Expand Down
Loading