diff --git a/PowerShellEditorServices.Common.props b/PowerShellEditorServices.Common.props
index 4f85f1157..a93f1e8b2 100644
--- a/PowerShellEditorServices.Common.props
+++ b/PowerShellEditorServices.Common.props
@@ -4,7 +4,7 @@
Microsoft
© Microsoft Corporation.
- 9.0
+ latest
PowerShell;editor;development;language;debugging
https://raw.githubusercontent.com/PowerShell/PowerShellEditorServices/master/LICENSE
true
diff --git a/src/PowerShellEditorServices/Services/DebugAdapter/DebugService.cs b/src/PowerShellEditorServices/Services/DebugAdapter/DebugService.cs
index 56b6ecb11..6c8d94ae8 100644
--- a/src/PowerShellEditorServices/Services/DebugAdapter/DebugService.cs
+++ b/src/PowerShellEditorServices/Services/DebugAdapter/DebugService.cs
@@ -2,21 +2,22 @@
// Licensed under the MIT License.
using System;
+using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Language;
using System.Reflection;
-using System.Threading.Tasks;
-using Microsoft.PowerShell.EditorServices.Utility;
using System.Threading;
+using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
-using Microsoft.PowerShell.EditorServices.Services.TextDocument;
using Microsoft.PowerShell.EditorServices.Services.DebugAdapter;
using Microsoft.PowerShell.EditorServices.Services.PowerShell;
+using Microsoft.PowerShell.EditorServices.Services.PowerShell.Debugging;
using Microsoft.PowerShell.EditorServices.Services.PowerShell.Execution;
using Microsoft.PowerShell.EditorServices.Services.PowerShell.Host;
-using Microsoft.PowerShell.EditorServices.Services.PowerShell.Debugging;
+using Microsoft.PowerShell.EditorServices.Services.TextDocument;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Services
{
@@ -40,11 +41,13 @@ internal class DebugService
private readonly IPowerShellDebugContext _debugContext;
+ // The LSP protocol refers to variables by individual IDs, this is an iterator for that purpose.
private int nextVariableId;
private string temporaryScriptListingPath;
private List variables;
private VariableContainerDetails globalScopeVariables;
private VariableContainerDetails scriptScopeVariables;
+ private VariableContainerDetails localScopeVariables;
private StackFrameDetails[] stackFrameDetails;
private readonly PropertyInfo invocationTypeScriptPositionProperty;
@@ -109,7 +112,7 @@ public DebugService(
{
Validate.IsNotNull(nameof(executionService), executionService);
- this._logger = factory.CreateLogger();
+ _logger = factory.CreateLogger();
_executionService = executionService;
_breakpointService = breakpointService;
_psesHost = psesHost;
@@ -120,7 +123,7 @@ public DebugService(
this.remoteFileManager = remoteFileManager;
- this.invocationTypeScriptPositionProperty =
+ invocationTypeScriptPositionProperty =
typeof(InvocationInfo)
.GetProperty(
"ScriptPosition",
@@ -147,30 +150,23 @@ public async Task SetLineBreakpointsAsync(
string scriptPath = scriptFile.FilePath;
// Make sure we're using the remote script path
- if (_psesHost.CurrentRunspace.IsOnRemoteMachine
- && this.remoteFileManager != null)
+ if (_psesHost.CurrentRunspace.IsOnRemoteMachine && remoteFileManager is not null)
{
- if (!this.remoteFileManager.IsUnderRemoteTempPath(scriptPath))
+ if (!remoteFileManager.IsUnderRemoteTempPath(scriptPath))
{
- this._logger.LogTrace(
- $"Could not set breakpoints for local path '{scriptPath}' in a remote session.");
+ _logger.LogTrace($"Could not set breakpoints for local path '{scriptPath}' in a remote session.");
return Array.Empty();
}
- string mappedPath =
- this.remoteFileManager.GetMappedPath(
- scriptPath,
- _psesHost.CurrentRunspace);
+ string mappedPath = remoteFileManager.GetMappedPath(scriptPath, _psesHost.CurrentRunspace);
scriptPath = mappedPath;
}
- else if (
- this.temporaryScriptListingPath != null &&
- this.temporaryScriptListingPath.Equals(scriptPath, StringComparison.CurrentCultureIgnoreCase))
+ else if (temporaryScriptListingPath is not null
+ && temporaryScriptListingPath.Equals(scriptPath, StringComparison.CurrentCultureIgnoreCase))
{
- this._logger.LogTrace(
- $"Could not set breakpoint on temporary script listing path '{scriptPath}'.");
+ _logger.LogTrace($"Could not set breakpoint on temporary script listing path '{scriptPath}'.");
return Array.Empty();
}
@@ -179,7 +175,7 @@ public async Task SetLineBreakpointsAsync(
// quoted and have those wildcard chars escaped.
string escapedScriptPath = PathUtils.WildcardEscapePath(scriptPath);
- if (dscBreakpoints == null || !dscBreakpoints.IsDscResourcePath(escapedScriptPath))
+ if (dscBreakpoints is null || !dscBreakpoints.IsDscResourcePath(escapedScriptPath))
{
if (clearExisting)
{
@@ -257,7 +253,7 @@ public void StepOut()
///
/// Causes the debugger to break execution wherever it currently
- /// is at the time. This is equivalent to clicking "Pause" in a
+ /// is at the time. This is equivalent to clicking "Pause" in a
/// debugger UI.
///
public void Break()
@@ -283,26 +279,26 @@ public void Abort()
public VariableDetailsBase[] GetVariables(int variableReferenceId)
{
VariableDetailsBase[] childVariables;
- this.debugInfoHandle.Wait();
+ debugInfoHandle.Wait();
try
{
- if ((variableReferenceId < 0) || (variableReferenceId >= this.variables.Count))
+ if ((variableReferenceId < 0) || (variableReferenceId >= variables.Count))
{
_logger.LogWarning($"Received request for variableReferenceId {variableReferenceId} that is out of range of valid indices.");
return Array.Empty();
}
- VariableDetailsBase parentVariable = this.variables[variableReferenceId];
+ VariableDetailsBase parentVariable = variables[variableReferenceId];
if (parentVariable.IsExpandable)
{
- childVariables = parentVariable.GetChildren(this._logger);
+ childVariables = parentVariable.GetChildren(_logger);
foreach (var child in childVariables)
{
// Only add child if it hasn't already been added.
if (child.Id < 0)
{
- child.Id = this.nextVariableId++;
- this.variables.Add(child);
+ child.Id = nextVariableId++;
+ variables.Add(child);
}
}
}
@@ -315,23 +311,22 @@ public VariableDetailsBase[] GetVariables(int variableReferenceId)
}
finally
{
- this.debugInfoHandle.Release();
+ debugInfoHandle.Release();
}
}
///
/// Evaluates a variable expression in the context of the stopped
- /// debugger. This method decomposes the variable expression to
+ /// debugger. This method decomposes the variable expression to
/// walk the cached variable data for the specified stack frame.
///
/// The variable expression string to evaluate.
- /// The ID of the stack frame in which the expression should be evaluated.
/// A VariableDetailsBase object containing the result.
- public VariableDetailsBase GetVariableFromExpression(string variableExpression, int stackFrameId)
+ public VariableDetailsBase GetVariableFromExpression(string variableExpression)
{
// NOTE: From a watch we will get passed expressions that are not naked variables references.
- // Probably the right way to do this woudld be to examine the AST of the expr before calling
- // this method to make sure it is a VariableReference. But for the most part, non-naked variable
+ // Probably the right way to do this would be to examine the AST of the expr before calling
+ // this method to make sure it is a VariableReference. But for the most part, non-naked variable
// references are very unlikely to find a matching variable e.g. "$i+5.2" will find no var matching "$i+5".
// Break up the variable path
@@ -341,21 +336,21 @@ public VariableDetailsBase GetVariableFromExpression(string variableExpression,
IEnumerable variableList;
// Ensure debug info isn't currently being built.
- this.debugInfoHandle.Wait();
+ debugInfoHandle.Wait();
try
{
- variableList = this.variables;
+ variableList = variables;
}
finally
{
- this.debugInfoHandle.Release();
+ debugInfoHandle.Release();
}
foreach (var variableName in variablePathParts)
{
- if (variableList == null)
+ if (variableList is null)
{
- // If there are no children left to search, break out early
+ // If there are no children left to search, break out early.
return null;
}
@@ -367,11 +362,10 @@ public VariableDetailsBase GetVariableFromExpression(string variableExpression,
variableName,
StringComparison.CurrentCultureIgnoreCase));
- if (resolvedVariable != null &&
- resolvedVariable.IsExpandable)
+ if (resolvedVariable is not null && resolvedVariable.IsExpandable)
{
- // Continue by searching in this variable's children
- variableList = this.GetVariables(resolvedVariable.Id);
+ // Continue by searching in this variable's children.
+ variableList = GetVariables(resolvedVariable.Id);
}
}
@@ -380,7 +374,7 @@ public VariableDetailsBase GetVariableFromExpression(string variableExpression,
///
/// Sets the specified variable by container variableReferenceId and variable name to the
- /// specified new value. If the variable cannot be set or converted to that value this
+ /// specified new value. If the variable cannot be set or converted to that value this
/// method will throw InvalidPowerShellExpressionException, ArgumentTransformationMetadataException, or
/// SessionStateUnauthorizedAccessException.
///
@@ -394,7 +388,7 @@ public async Task SetVariableAsync(int variableContainerReferenceId, str
Validate.IsNotNull(nameof(name), name);
Validate.IsNotNull(nameof(value), value);
- this._logger.LogTrace($"SetVariableRequest for '{name}' to value string (pre-quote processing): '{value}'");
+ _logger.LogTrace($"SetVariableRequest for '{name}' to value string (pre-quote processing): '{value}'");
// An empty or whitespace only value is not a valid expression for SetVariable.
if (value.Trim().Length == 0)
@@ -405,7 +399,9 @@ public async Task SetVariableAsync(int variableContainerReferenceId, str
// Evaluate the expression to get back a PowerShell object from the expression string.
// This may throw, in which case the exception is propagated to the caller
PSCommand evaluateExpressionCommand = new PSCommand().AddScript(value);
- object expressionResult = (await _executionService.ExecutePSCommandAsync