Esempio n. 1
0
        public async Task DebuggerAcceptsScriptArgs(string[] args)
        {
            // The path is intentionally odd (some escaped chars but not all) because we are testing
            // the internal path escaping mechanism - it should escape certains chars ([, ] and space) but
            // it should not escape already escaped chars.
            ScriptFile debugWithParamsFile =
                this.workspace.GetFile(
                    @"..\..\..\..\PowerShellEditorServices.Test.Shared\Debugging\Debug` With Params `[Test].ps1");

            await this.debugService.SetLineBreakpoints(
                debugWithParamsFile,
                new[] { BreakpointDetails.Create("", 3) });

            string arguments = string.Join(" ", args);

            // Execute the script and wait for the breakpoint to be hit
            Task executeTask =
                this.powerShellContext.ExecuteScriptWithArgs(
                    debugWithParamsFile.FilePath, arguments);

            await this.AssertDebuggerStopped(debugWithParamsFile.FilePath);

            StackFrameDetails[] stackFrames = debugService.GetStackFrames();

            VariableDetailsBase[] variables =
                debugService.GetVariables(stackFrames[0].LocalVariables.Id);

            var var = variables.FirstOrDefault(v => v.Name == "$Param1");

            Assert.NotNull(var);
            Assert.Equal("\"Foo\"", var.ValueString);
            Assert.False(var.IsExpandable);

            var = variables.FirstOrDefault(v => v.Name == "$Param2");
            Assert.NotNull(var);
            Assert.True(var.IsExpandable);

            var childVars = debugService.GetVariables(var.Id);

            Assert.Equal(9, childVars.Length);
            Assert.Equal("\"Bar\"", childVars[0].ValueString);
            Assert.Equal("\"Baz\"", childVars[1].ValueString);

            var = variables.FirstOrDefault(v => v.Name == "$Force");
            Assert.NotNull(var);
            Assert.Equal("True", var.ValueString);
            Assert.True(var.IsExpandable);

            var = variables.FirstOrDefault(v => v.Name == "$args");
            Assert.NotNull(var);
            Assert.True(var.IsExpandable);

            childVars = debugService.GetVariables(var.Id);
            Assert.Equal(8, childVars.Length);
            Assert.Equal("\"Extra1\"", childVars[0].ValueString);

            // Abort execution of the script
            this.powerShellContext.AbortExecution();
        }
Esempio n. 2
0
        protected async Task HandleSetBreakpointsRequest(
            SetBreakpointsRequestArguments setBreakpointsParams,
            RequestContext <SetBreakpointsResponseBody> requestContext)
        {
            ScriptFile scriptFile;

            // Fix for issue #195 - user can change name of file outside of VSCode in which case
            // VSCode sends breakpoint requests with the original filename that doesn't exist anymore.
            try
            {
                scriptFile = editorSession.Workspace.GetFile(setBreakpointsParams.Source.Path);
            }
            catch (FileNotFoundException)
            {
                Logger.Write(
                    LogLevel.Warning,
                    $"Attempted to set breakpoints on a non-existing file: {setBreakpointsParams.Source.Path}");

                var srcBreakpoints = setBreakpointsParams.Breakpoints
                                     .Select(srcBkpt => Protocol.DebugAdapter.Breakpoint.Create(
                                                 srcBkpt, setBreakpointsParams.Source.Path, "Source does not exist, breakpoint not set."));

                // Return non-verified breakpoint message.
                await requestContext.SendResult(
                    new SetBreakpointsResponseBody {
                    Breakpoints = srcBreakpoints.ToArray()
                });

                return;
            }

            var breakpointDetails = new BreakpointDetails[setBreakpointsParams.Breakpoints.Length];

            for (int i = 0; i < breakpointDetails.Length; i++)
            {
                SourceBreakpoint srcBreakpoint = setBreakpointsParams.Breakpoints[i];
                breakpointDetails[i] = BreakpointDetails.Create(
                    scriptFile.FilePath,
                    srcBreakpoint.Line,
                    srcBreakpoint.Column,
                    srcBreakpoint.Condition);
            }

            BreakpointDetails[] breakpoints =
                await editorSession.DebugService.SetLineBreakpoints(
                    scriptFile,
                    breakpointDetails);

            await requestContext.SendResult(
                new SetBreakpointsResponseBody
            {
                Breakpoints =
                    breakpoints
                    .Select(Protocol.DebugAdapter.Breakpoint.Create)
                    .ToArray()
            });
        }
        public async Task DebuggerGetsVariables()
        {
            await this.debugService.SetLineBreakpointsAsync(
                this.variableScriptFile,
                new[] { BreakpointDetails.Create(this.variableScriptFile.FilePath, 14) }).ConfigureAwait(false);

            // Execute the script and wait for the breakpoint to be hit
            Task executeTask =
                this.powerShellContext.ExecuteScriptStringAsync(
                    this.variableScriptFile.FilePath);

            await this.AssertDebuggerStopped(this.variableScriptFile.FilePath).ConfigureAwait(false);

            StackFrameDetails[] stackFrames = debugService.GetStackFrames();

            VariableDetailsBase[] variables =
                debugService.GetVariables(stackFrames[0].LocalVariables.Id);

            // TODO: Add checks for correct value strings as well

            var strVar = variables.FirstOrDefault(v => v.Name == "$strVar");

            Assert.NotNull(strVar);
            Assert.False(strVar.IsExpandable);

            var objVar = variables.FirstOrDefault(v => v.Name == "$assocArrVar");

            Assert.NotNull(objVar);
            Assert.True(objVar.IsExpandable);

            var objChildren = debugService.GetVariables(objVar.Id);

            Assert.Equal(9, objChildren.Length);

            var arrVar = variables.FirstOrDefault(v => v.Name == "$arrVar");

            Assert.NotNull(arrVar);
            Assert.True(arrVar.IsExpandable);

            var arrChildren = debugService.GetVariables(arrVar.Id);

            Assert.Equal(11, arrChildren.Length);

            var classVar = variables.FirstOrDefault(v => v.Name == "$classVar");

            Assert.NotNull(classVar);
            Assert.True(classVar.IsExpandable);

            var classChildren = debugService.GetVariables(classVar.Id);

            Assert.Equal(2, classChildren.Length);

            // Abort script execution early and wait for completion
            this.debugService.Abort();
            await executeTask.ConfigureAwait(false);
        }
Esempio n. 4
0
        public async Task DebuggerStopsOnConditionalBreakpoints()
        {
            const int breakpointValue1 = 10;
            const int breakpointValue2 = 20;

            BreakpointDetails[] breakpoints =
                await this.debugService.SetLineBreakpoints(
                    this.debugScriptFile,
                    new[] {
                BreakpointDetails.Create("", 7, null, $"$i -eq {breakpointValue1} -or $i -eq {breakpointValue2}"),
            });

            await this.AssertStateChange(PowerShellContextState.Ready);

            Task executeTask =
                this.powerShellContext.ExecuteScriptWithArgs(
                    this.debugScriptFile.FilePath);

            // Wait for conditional breakpoint to hit
            await this.AssertDebuggerStopped(this.debugScriptFile.FilePath, 7);

            StackFrameDetails[]   stackFrames = debugService.GetStackFrames();
            VariableDetailsBase[] variables   =
                debugService.GetVariables(stackFrames[0].LocalVariables.Id);

            // Verify the breakpoint only broke at the condition ie. $i -eq breakpointValue1
            var i = variables.FirstOrDefault(v => v.Name == "$i");

            Assert.NotNull(i);
            Assert.False(i.IsExpandable);
            Assert.Equal($"{breakpointValue1}", i.ValueString);

            // The conditional breakpoint should not fire again, until the value of
            // i reaches breakpointValue2.
            this.debugService.Continue();
            await this.AssertDebuggerStopped(this.debugScriptFile.FilePath, 7);

            stackFrames = debugService.GetStackFrames();
            variables   = debugService.GetVariables(stackFrames[0].LocalVariables.Id);

            // Verify the breakpoint only broke at the condition ie. $i -eq breakpointValue1
            i = variables.FirstOrDefault(v => v.Name == "$i");
            Assert.NotNull(i);
            Assert.False(i.IsExpandable);
            Assert.Equal($"{breakpointValue2}", i.ValueString);

            // Abort script execution early and wait for completion
            this.debugService.Abort();
            await executeTask;
        }
        private async void DebugService_BreakpointUpdatedAsync(object sender, BreakpointUpdatedEventArgs e)
        {
            string reason = "changed";

            if (_setBreakpointInProgress)
            {
                // Don't send breakpoint update notifications when setting
                // breakpoints on behalf of the client.
                return;
            }

            switch (e.UpdateType)
            {
            case BreakpointUpdateType.Set:
                reason = "new";
                break;

            case BreakpointUpdateType.Removed:
                reason = "removed";
                break;
            }

            Protocol.DebugAdapter.Breakpoint breakpoint;
            if (e.Breakpoint is LineBreakpoint)
            {
                breakpoint = Protocol.DebugAdapter.Breakpoint.Create(BreakpointDetails.Create(e.Breakpoint));
            }
            else if (e.Breakpoint is CommandBreakpoint)
            {
                //breakpoint = Protocol.DebugAdapter.Breakpoint.Create(CommandBreakpointDetails.Create(e.Breakpoint));
                Logger.Write(LogLevel.Verbose, "Function breakpoint updated event is not supported yet");
                return;
            }
            else
            {
                Logger.Write(LogLevel.Error, $"Unrecognized breakpoint type {e.Breakpoint.GetType().FullName}");
                return;
            }

            breakpoint.Verified = e.UpdateType != BreakpointUpdateType.Disabled;

            await _messageSender.SendEventAsync(
                BreakpointEvent.Type,
                new BreakpointEvent
            {
                Reason     = reason,
                Breakpoint = breakpoint
            });
        }
        private void DebugService_BreakpointUpdated(object sender, BreakpointUpdatedEventArgs e)
        {
            string reason = "changed";

            if (_debugStateService.IsSetBreakpointInProgress)
            {
                // Don't send breakpoint update notifications when setting
                // breakpoints on behalf of the client.
                return;
            }

            switch (e.UpdateType)
            {
            case BreakpointUpdateType.Set:
                reason = "new";
                break;

            case BreakpointUpdateType.Removed:
                reason = "removed";
                break;
            }

            var breakpoint = new OmniSharp.Extensions.DebugAdapter.Protocol.Models.Breakpoint
            {
                Verified = e.UpdateType != BreakpointUpdateType.Disabled
            };

            if (e.Breakpoint is LineBreakpoint)
            {
                breakpoint = LspDebugUtils.CreateBreakpoint(BreakpointDetails.Create(e.Breakpoint));
            }
            else if (e.Breakpoint is CommandBreakpoint)
            {
                _logger.LogTrace("Function breakpoint updated event is not supported yet");
                return;
            }
            else
            {
                _logger.LogError($"Unrecognized breakpoint type {e.Breakpoint.GetType().FullName}");
                return;
            }

            _debugAdapterServer.SendNotification(EventNames.Breakpoint,
                                                 new BreakpointEvent
            {
                Reason     = reason,
                Breakpoint = breakpoint
            });
        }
        public async Task DebuggerVariableHashtableDisplaysCorrectly()
        {
            await this.debugService.SetLineBreakpointsAsync(
                this.variableScriptFile,
                new[] { BreakpointDetails.Create(this.variableScriptFile.FilePath, 11) }).ConfigureAwait(false);

            // Execute the script and wait for the breakpoint to be hit
            Task executeTask =
                this.powerShellContext.ExecuteScriptStringAsync(
                    this.variableScriptFile.FilePath);

            await this.AssertDebuggerStopped(this.variableScriptFile.FilePath).ConfigureAwait(false);

            StackFrameDetails[] stackFrames = debugService.GetStackFrames();

            VariableDetailsBase[] variables =
                debugService.GetVariables(stackFrames[0].LocalVariables.Id);

            VariableDetailsBase var = variables.FirstOrDefault(v => v.Name == "$assocArrVar");

            Assert.NotNull(var);
            Assert.Equal("[Hashtable: 2]", var.ValueString);
            Assert.True(var.IsExpandable);

            VariableDetailsBase[] childVars = debugService.GetVariables(var.Id);
            Assert.Equal(9, childVars.Length);
            Assert.Equal("[0]", childVars[0].Name);
            Assert.Equal("[1]", childVars[1].Name);

            var childVarStrs = new HashSet <string>(childVars.Select(v => v.ValueString));
            var expectedVars = new[] {
                "[firstChild, \"Child\"]",
                "[secondChild, 42]"
            };

            foreach (string expectedVar in expectedVars)
            {
                Assert.Contains(expectedVar, childVarStrs);
            }

            // Abort script execution early and wait for completion
            this.debugService.Abort();
            await executeTask.ConfigureAwait(false);
        }
Esempio n. 8
0
        public async Task DebuggerFindsParseableButInvalidSimpleBreakpointConditions()
        {
            BreakpointDetails[] breakpoints =
                await this.debugService.SetLineBreakpoints(
                    this.debugScriptFile,
                    new[] {
                BreakpointDetails.Create("", 5, column: null, condition: "$i == 100"),
                BreakpointDetails.Create("", 7, column: null, condition: "$i > 100")
            });

            Assert.Equal(2, breakpoints.Length);
            Assert.Equal(5, breakpoints[0].LineNumber);
            Assert.False(breakpoints[0].Verified);
            Assert.Contains("Use '-eq' instead of '=='", breakpoints[0].Message);

            Assert.Equal(7, breakpoints[1].LineNumber);
            Assert.False(breakpoints[1].Verified);
            Assert.NotNull(breakpoints[1].Message);
            Assert.Contains("Use '-gt' instead of '>'", breakpoints[1].Message);
        }
Esempio n. 9
0
        public async Task DebuggerProvidesMessageForInvalidConditionalBreakpoint()
        {
            BreakpointDetails[] breakpoints =
                await this.debugService.SetLineBreakpoints(
                    this.debugScriptFile,
                    new[] {
                BreakpointDetails.Create("", 5),
                BreakpointDetails.Create("", 10, column: null, condition: "$i -ez 100")
            });

            Assert.Equal(2, breakpoints.Length);
            Assert.Equal(5, breakpoints[0].LineNumber);
            Assert.True(breakpoints[0].Verified);
            Assert.Null(breakpoints[0].Message);

            Assert.Equal(10, breakpoints[1].LineNumber);
            Assert.False(breakpoints[1].Verified);
            Assert.NotNull(breakpoints[1].Message);
            Assert.Contains("Unexpected token '-ez'", breakpoints[1].Message);
        }
        private void OnBreakpointUpdated(object sender, BreakpointUpdatedEventArgs e)
        {
            // Don't send breakpoint update notifications when setting
            // breakpoints on behalf of the client.
            if (_debugStateService.IsSetBreakpointInProgress)
            {
                return;
            }

            if (e.Breakpoint is LineBreakpoint)
            {
                OmniSharp.Extensions.DebugAdapter.Protocol.Models.Breakpoint breakpoint = LspDebugUtils.CreateBreakpoint(
                    BreakpointDetails.Create(e.Breakpoint, e.UpdateType)
                    );

                string reason = e.UpdateType switch
                {
                    BreakpointUpdateType.Set => BreakpointEventReason.New,
                    BreakpointUpdateType.Removed => BreakpointEventReason.Removed,
                    BreakpointUpdateType.Enabled => BreakpointEventReason.Changed,
                    BreakpointUpdateType.Disabled => BreakpointEventReason.Changed,
                    _ => "InvalidBreakpointUpdateTypeEnum"
                };

                _debugAdapterServer.SendNotification(
                    EventNames.Breakpoint,
                    new BreakpointEvent {
                    Breakpoint = breakpoint, Reason = reason
                }
                    );
            }
            else if (e.Breakpoint is CommandBreakpoint)
            {
                _logger.LogTrace("Function breakpoint updated event is not supported yet");
            }
            else
            {
                _logger.LogError($"Unrecognized breakpoint type {e.Breakpoint.GetType().FullName}");
            }
        }
        public async Task DebuggerSetsAndClearsLineBreakpoints()
        {
            BreakpointDetails[] breakpoints =
                await this.debugService.SetLineBreakpointsAsync(
                    this.debugScriptFile,
                    new[] {
                BreakpointDetails.Create(this.debugScriptFile.FilePath, 5),
                BreakpointDetails.Create(this.debugScriptFile.FilePath, 10)
            }).ConfigureAwait(false);

            var confirmedBreakpoints = await this.GetConfirmedBreakpoints(this.debugScriptFile).ConfigureAwait(false);

            Assert.Equal(2, confirmedBreakpoints.Count());
            Assert.Equal(5, breakpoints[0].LineNumber);
            Assert.Equal(10, breakpoints[1].LineNumber);

            breakpoints =
                await this.debugService.SetLineBreakpointsAsync(
                    this.debugScriptFile,
                    new[] { BreakpointDetails.Create(this.debugScriptFile.FilePath, 2) }).ConfigureAwait(false);

            confirmedBreakpoints = await this.GetConfirmedBreakpoints(this.debugScriptFile).ConfigureAwait(false);

            Assert.Single(confirmedBreakpoints);
            Assert.Equal(2, breakpoints[0].LineNumber);

            await this.debugService.SetLineBreakpointsAsync(
                this.debugScriptFile,
                Array.Empty <BreakpointDetails>()).ConfigureAwait(false);

            var remainingBreakpoints = await this.GetConfirmedBreakpoints(this.debugScriptFile).ConfigureAwait(false);

            Assert.Empty(remainingBreakpoints);

            // Abort debugger
            this.debugService.Abort();
        }
        public async Task DebuggerVariablePSCustomObjectDisplaysCorrectly()
        {
            await this.debugService.SetLineBreakpointsAsync(
                this.variableScriptFile,
                new[] { BreakpointDetails.Create(this.variableScriptFile.FilePath, 18) }).ConfigureAwait(false);

            // Execute the script and wait for the breakpoint to be hit
            Task executeTask =
                this.powerShellContext.ExecuteScriptStringAsync(
                    this.variableScriptFile.FilePath);

            await this.AssertDebuggerStopped(this.variableScriptFile.FilePath).ConfigureAwait(false);

            StackFrameDetails[] stackFrames = debugService.GetStackFrames();

            VariableDetailsBase[] variables =
                debugService.GetVariables(stackFrames[0].LocalVariables.Id);

            var var = variables.FirstOrDefault(v => v.Name == "$psCustomObjVar");

            Assert.NotNull(var);
            Assert.Equal("@{Name=Paul; Age=73}", var.ValueString);
            Assert.True(var.IsExpandable);

            var childVars = debugService.GetVariables(var.Id);

            Assert.Equal(2, childVars.Length);
            Assert.Equal("Name", childVars[0].Name);
            Assert.Equal("\"Paul\"", childVars[0].ValueString);
            Assert.Equal("Age", childVars[1].Name);
            Assert.Equal("73", childVars[1].ValueString);

            // Abort script execution early and wait for completion
            this.debugService.Abort();
            await executeTask.ConfigureAwait(false);
        }
        public async Task DebuggerVariablePSObjectDisplaysCorrectly()
        {
            await this.debugService.SetLineBreakpointsAsync(
                this.variableScriptFile,
                new[] { BreakpointDetails.Create(this.variableScriptFile.FilePath, 17) }).ConfigureAwait(false);

            // Execute the script and wait for the breakpoint to be hit
            Task executeTask =
                this.powerShellContext.ExecuteScriptStringAsync(
                    this.variableScriptFile.FilePath);

            await this.AssertDebuggerStopped(this.variableScriptFile.FilePath).ConfigureAwait(false);

            StackFrameDetails[] stackFrames = debugService.GetStackFrames();

            VariableDetailsBase[] variables =
                debugService.GetVariables(stackFrames[0].LocalVariables.Id);

            var psObjVar = variables.FirstOrDefault(v => v.Name == "$psObjVar");

            Assert.NotNull(psObjVar);
            Assert.True("@{Age=75; Name=John}".Equals(psObjVar.ValueString) || "@{Name=John; Age=75}".Equals(psObjVar.ValueString));
            Assert.True(psObjVar.IsExpandable);

            IDictionary <string, string> childVars = debugService.GetVariables(psObjVar.Id).ToDictionary(v => v.Name, v => v.ValueString);

            Assert.Equal(2, childVars.Count);
            Assert.Contains("Age", childVars.Keys);
            Assert.Contains("Name", childVars.Keys);
            Assert.Equal("75", childVars["Age"]);
            Assert.Equal("\"John\"", childVars["Name"]);

            // Abort script execution early and wait for completion
            this.debugService.Abort();
            await executeTask.ConfigureAwait(false);
        }
        public async Task DebuggerStopsOnLineBreakpoints()
        {
            await this.debugService.SetLineBreakpointsAsync(
                this.debugScriptFile,
                new[] {
                BreakpointDetails.Create(this.debugScriptFile.FilePath, 5),
                BreakpointDetails.Create(this.debugScriptFile.FilePath, 7)
            }).ConfigureAwait(false);

            Task executeTask =
                this.powerShellContext.ExecuteScriptWithArgsAsync(
                    this.debugScriptFile.FilePath);

            // Wait for a couple breakpoints
            await this.AssertDebuggerStopped(this.debugScriptFile.FilePath, 5).ConfigureAwait(false);

            this.debugService.Continue();

            await this.AssertDebuggerStopped(this.debugScriptFile.FilePath, 7).ConfigureAwait(false);

            // Abort script execution early and wait for completion
            this.debugService.Abort();
            await executeTask.ConfigureAwait(false);
        }
Esempio n. 15
0
        public async Task DebuggerStopsOnConditionalAndHitConditionBreakpoint()
        {
            const int hitCount = 5;

            BreakpointDetails[] breakpoints =
                await this.debugService.SetLineBreakpoints(
                    this.debugScriptFile,
                    new[] {
                BreakpointDetails.Create("", 6, null, $"$i % 2 -eq 0", $"{hitCount}"),
            });

            await this.AssertStateChange(PowerShellContextState.Ready);

            Task executeTask =
                this.powerShellContext.ExecuteScriptWithArgs(
                    this.debugScriptFile.FilePath);

            // Wait for conditional breakpoint to hit
            await this.AssertDebuggerStopped(this.debugScriptFile.FilePath, 6);

            StackFrameDetails[]   stackFrames = debugService.GetStackFrames();
            VariableDetailsBase[] variables   =
                debugService.GetVariables(stackFrames[0].LocalVariables.Id);

            // Verify the breakpoint only broke at the condition ie. $i -eq breakpointValue1
            var i = variables.FirstOrDefault(v => v.Name == "$i");

            Assert.NotNull(i);
            Assert.False(i.IsExpandable);
            // Condition is even numbers ($i starting at 1) should end up on 10 with a hit count of 5.
            Assert.Equal("10", i.ValueString);

            // Abort script execution early and wait for completion
            this.debugService.Abort();
            await executeTask;
        }
Esempio n. 16
0
        public async Task DebuggerSetsAndClearsLineBreakpoints()
        {
            BreakpointDetails[] breakpoints =
                await this.debugService.SetLineBreakpoints(
                    this.debugScriptFile,
                    new[] {
                BreakpointDetails.Create("", 5),
                BreakpointDetails.Create("", 10)
            });

            var confirmedBreakpoints = await this.GetConfirmedBreakpoints(this.debugScriptFile);

            Assert.Equal(2, confirmedBreakpoints.Count());
            Assert.Equal(5, breakpoints[0].LineNumber);
            Assert.Equal(10, breakpoints[1].LineNumber);

            breakpoints =
                await this.debugService.SetLineBreakpoints(
                    this.debugScriptFile,
                    new[] { BreakpointDetails.Create("", 2) });

            confirmedBreakpoints = await this.GetConfirmedBreakpoints(this.debugScriptFile);

            Assert.Equal(1, confirmedBreakpoints.Count());
            Assert.Equal(2, breakpoints[0].LineNumber);

            await this.debugService.SetLineBreakpoints(
                this.debugScriptFile,
                new[] { BreakpointDetails.Create("", 0) });

            var remainingBreakpoints = await this.GetConfirmedBreakpoints(this.debugScriptFile);

            Assert.False(
                remainingBreakpoints.Any(),
                "Breakpoints in the script file were not cleared");
        }
        protected async Task HandleSetBreakpointsRequest(
            SetBreakpointsRequestArguments setBreakpointsParams,
            RequestContext <SetBreakpointsResponseBody> requestContext)
        {
            ScriptFile scriptFile = null;

            // Fix for issue #195 - user can change name of file outside of VSCode in which case
            // VSCode sends breakpoint requests with the original filename that doesn't exist anymore.
            try
            {
                // When you set a breakpoint in the right pane of a Git diff window on a PS1 file,
                // the Source.Path comes through as Untitled-X.
                if (!ScriptFile.IsUntitledPath(setBreakpointsParams.Source.Path))
                {
                    scriptFile = editorSession.Workspace.GetFile(setBreakpointsParams.Source.Path);
                }
            }
            catch (Exception e) when(
                e is FileNotFoundException ||
                e is DirectoryNotFoundException ||
                e is IOException ||
                e is NotSupportedException ||
                e is PathTooLongException ||
                e is SecurityException ||
                e is UnauthorizedAccessException)
            {
                Logger.WriteException(
                    $"Failed to set breakpoint on file: {setBreakpointsParams.Source.Path}",
                    e);

                string message        = this.noDebug ? string.Empty : "Source file could not be accessed, breakpoint not set - " + e.Message;
                var    srcBreakpoints = setBreakpointsParams.Breakpoints
                                        .Select(srcBkpt => Protocol.DebugAdapter.Breakpoint.Create(
                                                    srcBkpt, setBreakpointsParams.Source.Path, message, verified: this.noDebug));

                // Return non-verified breakpoint message.
                await requestContext.SendResult(
                    new SetBreakpointsResponseBody {
                    Breakpoints = srcBreakpoints.ToArray()
                });

                return;
            }

            // Verify source file is a PowerShell script file.
            string fileExtension = Path.GetExtension(scriptFile?.FilePath ?? "")?.ToLower();

            if (string.IsNullOrEmpty(fileExtension) || ((fileExtension != ".ps1") && (fileExtension != ".psm1")))
            {
                Logger.Write(
                    LogLevel.Warning,
                    $"Attempted to set breakpoints on a non-PowerShell file: {setBreakpointsParams.Source.Path}");

                string message = this.noDebug ? string.Empty : "Source is not a PowerShell script, breakpoint not set.";

                var srcBreakpoints = setBreakpointsParams.Breakpoints
                                     .Select(srcBkpt => Protocol.DebugAdapter.Breakpoint.Create(
                                                 srcBkpt, setBreakpointsParams.Source.Path, message, verified: this.noDebug));

                // Return non-verified breakpoint message.
                await requestContext.SendResult(
                    new SetBreakpointsResponseBody
                {
                    Breakpoints = srcBreakpoints.ToArray()
                });

                return;
            }

            // At this point, the source file has been verified as a PowerShell script.
            var breakpointDetails = new BreakpointDetails[setBreakpointsParams.Breakpoints.Length];

            for (int i = 0; i < breakpointDetails.Length; i++)
            {
                SourceBreakpoint srcBreakpoint = setBreakpointsParams.Breakpoints[i];
                breakpointDetails[i] = BreakpointDetails.Create(
                    scriptFile.FilePath,
                    srcBreakpoint.Line,
                    srcBreakpoint.Column,
                    srcBreakpoint.Condition,
                    srcBreakpoint.HitCondition);
            }

            // If this is a "run without debugging (Ctrl+F5)" session ignore requests to set breakpoints.
            BreakpointDetails[] updatedBreakpointDetails = breakpointDetails;
            if (!this.noDebug)
            {
                this.setBreakpointInProgress = true;

                try
                {
                    updatedBreakpointDetails =
                        await editorSession.DebugService.SetLineBreakpoints(
                            scriptFile,
                            breakpointDetails);
                }
                catch (Exception e)
                {
                    // Log whatever the error is
                    Logger.WriteException($"Caught error while setting breakpoints in SetBreakpoints handler for file {scriptFile?.FilePath}", e);
                }
                finally
                {
                    this.setBreakpointInProgress = false;
                }
            }

            await requestContext.SendResult(
                new SetBreakpointsResponseBody {
                Breakpoints =
                    updatedBreakpointDetails
                    .Select(Protocol.DebugAdapter.Breakpoint.Create)
                    .ToArray()
            });
        }
        public async Task DebuggerSetsVariablesWithConversion()
        {
            await this.debugService.SetLineBreakpointsAsync(
                this.variableScriptFile,
                new[] { BreakpointDetails.Create(this.variableScriptFile.FilePath, 14) }).ConfigureAwait(false);

            // Execute the script and wait for the breakpoint to be hit
            Task executeTask =
                this.powerShellContext.ExecuteScriptStringAsync(
                    this.variableScriptFile.FilePath);

            await this.AssertDebuggerStopped(this.variableScriptFile.FilePath).ConfigureAwait(false);

            StackFrameDetails[] stackFrames = debugService.GetStackFrames();

            VariableDetailsBase[] variables =
                debugService.GetVariables(stackFrames[0].LocalVariables.Id);

            // Test set of a local string variable (not strongly typed but force conversion)
            string newStrValue = "\"False\"";
            string newStrExpr  = "$false";
            string setStrValue = await debugService.SetVariableAsync(stackFrames[0].LocalVariables.Id, "$strVar2", newStrExpr).ConfigureAwait(false);

            Assert.Equal(newStrValue, setStrValue);

            VariableScope[] scopes = this.debugService.GetVariableScopes(0);

            // Test set of script scope bool variable (strongly typed)
            VariableScope scriptScope  = scopes.FirstOrDefault(s => s.Name == VariableContainerDetails.ScriptScopeName);
            string        newBoolValue = "$true";
            string        newBoolExpr  = "1";
            string        setBoolValue = await debugService.SetVariableAsync(scriptScope.Id, "$scriptBool", newBoolExpr).ConfigureAwait(false);

            Assert.Equal(newBoolValue, setBoolValue);

            // Test set of global scope ActionPreference variable (strongly typed)
            VariableScope globalScope    = scopes.FirstOrDefault(s => s.Name == VariableContainerDetails.GlobalScopeName);
            string        newGlobalValue = "Continue";
            string        newGlobalExpr  = "'Continue'";
            string        setGlobalValue = await debugService.SetVariableAsync(globalScope.Id, "$VerbosePreference", newGlobalExpr).ConfigureAwait(false);

            Assert.Equal(newGlobalValue, setGlobalValue);

            // The above just tests that the debug service returns the correct new value string.
            // Let's step the debugger and make sure the values got set to the new values.
            this.debugService.StepOver();
            await this.AssertDebuggerStopped(this.variableScriptFile.FilePath).ConfigureAwait(false);

            stackFrames = debugService.GetStackFrames();

            // Test set of a local string variable (not strongly typed but force conversion)
            variables = debugService.GetVariables(stackFrames[0].LocalVariables.Id);
            var strVar = variables.FirstOrDefault(v => v.Name == "$strVar2");

            Assert.Equal(newStrValue, strVar.ValueString);

            scopes = this.debugService.GetVariableScopes(0);

            // Test set of script scope bool variable (strongly typed)
            scriptScope = scopes.FirstOrDefault(s => s.Name == VariableContainerDetails.ScriptScopeName);
            variables   = debugService.GetVariables(scriptScope.Id);
            var boolVar = variables.FirstOrDefault(v => v.Name == "$scriptBool");

            Assert.Equal(newBoolValue, boolVar.ValueString);

            // Test set of global scope ActionPreference variable (strongly typed)
            globalScope = scopes.FirstOrDefault(s => s.Name == VariableContainerDetails.GlobalScopeName);
            variables   = debugService.GetVariables(globalScope.Id);
            var globalVar = variables.FirstOrDefault(v => v.Name == "$VerbosePreference");

            Assert.Equal(newGlobalValue, globalVar.ValueString);

            // Abort script execution early and wait for completion
            this.debugService.Abort();
            await executeTask.ConfigureAwait(false);
        }
        public async Task DebuggerSetsVariablesNoConversion()
        {
            await this.debugService.SetLineBreakpointsAsync(
                this.variableScriptFile,
                new[] { BreakpointDetails.Create(this.variableScriptFile.FilePath, 14) }).ConfigureAwait(false);

            // Execute the script and wait for the breakpoint to be hit
            Task executeTask =
                this.powerShellContext.ExecuteScriptStringAsync(
                    this.variableScriptFile.FilePath);

            await this.AssertDebuggerStopped(this.variableScriptFile.FilePath).ConfigureAwait(false);

            StackFrameDetails[] stackFrames = debugService.GetStackFrames();

            VariableDetailsBase[] variables =
                debugService.GetVariables(stackFrames[0].LocalVariables.Id);

            // Test set of a local string variable (not strongly typed)
            string newStrValue = "\"Goodbye\"";
            string setStrValue = await debugService.SetVariableAsync(stackFrames[0].LocalVariables.Id, "$strVar", newStrValue).ConfigureAwait(false);

            Assert.Equal(newStrValue, setStrValue);

            VariableScope[] scopes = this.debugService.GetVariableScopes(0);

            // Test set of script scope int variable (not strongly typed)
            VariableScope scriptScope = scopes.FirstOrDefault(s => s.Name == VariableContainerDetails.ScriptScopeName);
            string        newIntValue = "49";
            string        newIntExpr  = "7 * 7";
            string        setIntValue = await debugService.SetVariableAsync(scriptScope.Id, "$scriptInt", newIntExpr).ConfigureAwait(false);

            Assert.Equal(newIntValue, setIntValue);

            // Test set of global scope int variable (not strongly typed)
            VariableScope globalScope       = scopes.FirstOrDefault(s => s.Name == VariableContainerDetails.GlobalScopeName);
            string        newGlobalIntValue = "4242";
            string        setGlobalIntValue = await debugService.SetVariableAsync(globalScope.Id, "$MaximumHistoryCount", newGlobalIntValue).ConfigureAwait(false);

            Assert.Equal(newGlobalIntValue, setGlobalIntValue);

            // The above just tests that the debug service returns the correct new value string.
            // Let's step the debugger and make sure the values got set to the new values.
            this.debugService.StepOver();
            await this.AssertDebuggerStopped(this.variableScriptFile.FilePath).ConfigureAwait(false);

            stackFrames = debugService.GetStackFrames();

            // Test set of a local string variable (not strongly typed)
            variables = debugService.GetVariables(stackFrames[0].LocalVariables.Id);
            var strVar = variables.FirstOrDefault(v => v.Name == "$strVar");

            Assert.Equal(newStrValue, strVar.ValueString);

            scopes = this.debugService.GetVariableScopes(0);

            // Test set of script scope int variable (not strongly typed)
            scriptScope = scopes.FirstOrDefault(s => s.Name == VariableContainerDetails.ScriptScopeName);
            variables   = debugService.GetVariables(scriptScope.Id);
            var intVar = variables.FirstOrDefault(v => v.Name == "$scriptInt");

            Assert.Equal(newIntValue, intVar.ValueString);

            // Test set of global scope int variable (not strongly typed)
            globalScope = scopes.FirstOrDefault(s => s.Name == VariableContainerDetails.GlobalScopeName);
            variables   = debugService.GetVariables(globalScope.Id);
            var intGlobalVar = variables.FirstOrDefault(v => v.Name == "$MaximumHistoryCount");

            Assert.Equal(newGlobalIntValue, intGlobalVar.ValueString);

            // Abort script execution early and wait for completion
            this.debugService.Abort();
            await executeTask.ConfigureAwait(false);
        }
Esempio n. 20
0
        public async Task <SetBreakpointsResponse> Handle(SetBreakpointsArguments request, CancellationToken cancellationToken)
        {
            if (!_workspaceService.TryGetFile(request.Source.Path, out ScriptFile scriptFile))
            {
                string message        = _debugStateService.NoDebug ? string.Empty : "Source file could not be accessed, breakpoint not set.";
                var    srcBreakpoints = request.Breakpoints
                                        .Select(srcBkpt => LspDebugUtils.CreateBreakpoint(
                                                    srcBkpt, request.Source.Path, message, verified: _debugStateService.NoDebug));

                // Return non-verified breakpoint message.
                return(new SetBreakpointsResponse
                {
                    Breakpoints = new Container <Breakpoint>(srcBreakpoints)
                });
            }

            // Verify source file is a PowerShell script file.
            string fileExtension  = Path.GetExtension(scriptFile?.FilePath ?? "")?.ToLower();
            bool   isUntitledPath = ScriptFile.IsUntitledPath(request.Source.Path);

            if ((!isUntitledPath && fileExtension != ".ps1" && fileExtension != ".psm1") ||
                (!BreakpointApiUtils.SupportsBreakpointApis && isUntitledPath))
            {
                _logger.LogWarning(
                    $"Attempted to set breakpoints on a non-PowerShell file: {request.Source.Path}");

                string message = _debugStateService.NoDebug ? string.Empty : "Source is not a PowerShell script, breakpoint not set.";

                var srcBreakpoints = request.Breakpoints
                                     .Select(srcBkpt => LspDebugUtils.CreateBreakpoint(
                                                 srcBkpt, request.Source.Path, message, verified: _debugStateService.NoDebug));

                // Return non-verified breakpoint message.
                return(new SetBreakpointsResponse
                {
                    Breakpoints = new Container <Breakpoint>(srcBreakpoints)
                });
            }

            // At this point, the source file has been verified as a PowerShell script.
            BreakpointDetails[] breakpointDetails = request.Breakpoints
                                                    .Select((srcBreakpoint) => BreakpointDetails.Create(
                                                                scriptFile.FilePath,
                                                                srcBreakpoint.Line,
                                                                srcBreakpoint.Column,
                                                                srcBreakpoint.Condition,
                                                                srcBreakpoint.HitCondition,
                                                                srcBreakpoint.LogMessage))
                                                    .ToArray();

            // If this is a "run without debugging (Ctrl+F5)" session ignore requests to set breakpoints.
            BreakpointDetails[] updatedBreakpointDetails = breakpointDetails;
            if (!_debugStateService.NoDebug)
            {
                await _debugStateService.WaitForSetBreakpointHandleAsync().ConfigureAwait(false);

                try
                {
                    updatedBreakpointDetails =
                        await _debugService.SetLineBreakpointsAsync(
                            scriptFile,
                            breakpointDetails).ConfigureAwait(false);
                }
                catch (Exception e)
                {
                    // Log whatever the error is
                    _logger.LogException($"Caught error while setting breakpoints in SetBreakpoints handler for file {scriptFile?.FilePath}", e);
                }
                finally
                {
                    _debugStateService.ReleaseSetBreakpointHandle();
                }
            }

            return(new SetBreakpointsResponse
            {
                Breakpoints = new Container <Breakpoint>(updatedBreakpointDetails
                                                         .Select(LspDebugUtils.CreateBreakpoint))
            });
        }
        public async Task <SetBreakpointsResponse> Handle(SetBreakpointsArguments request, CancellationToken cancellationToken)
        {
            ScriptFile scriptFile = null;

            // When you set a breakpoint in the right pane of a Git diff window on a PS1 file,
            // the Source.Path comes through as Untitled-X. That's why we check for IsUntitledPath.
            if (!ScriptFile.IsUntitledPath(request.Source.Path) &&
                !_workspaceService.TryGetFile(
                    request.Source.Path,
                    out scriptFile))
            {
                string message        = _debugStateService.NoDebug ? string.Empty : "Source file could not be accessed, breakpoint not set.";
                var    srcBreakpoints = request.Breakpoints
                                        .Select(srcBkpt => LspDebugUtils.CreateBreakpoint(
                                                    srcBkpt, request.Source.Path, message, verified: _debugStateService.NoDebug));

                // Return non-verified breakpoint message.
                return(new SetBreakpointsResponse
                {
                    Breakpoints = new Container <Breakpoint>(srcBreakpoints)
                });
            }

            // Verify source file is a PowerShell script file.
            string fileExtension = Path.GetExtension(scriptFile?.FilePath ?? "")?.ToLower();

            if (string.IsNullOrEmpty(fileExtension) || ((fileExtension != ".ps1") && (fileExtension != ".psm1")))
            {
                _logger.LogWarning(
                    $"Attempted to set breakpoints on a non-PowerShell file: {request.Source.Path}");

                string message = _debugStateService.NoDebug ? string.Empty : "Source is not a PowerShell script, breakpoint not set.";

                var srcBreakpoints = request.Breakpoints
                                     .Select(srcBkpt => LspDebugUtils.CreateBreakpoint(
                                                 srcBkpt, request.Source.Path, message, verified: _debugStateService.NoDebug));

                // Return non-verified breakpoint message.
                return(new SetBreakpointsResponse
                {
                    Breakpoints = new Container <Breakpoint>(srcBreakpoints)
                });
            }

            // At this point, the source file has been verified as a PowerShell script.
            BreakpointDetails[] breakpointDetails = request.Breakpoints
                                                    .Select((srcBreakpoint) => BreakpointDetails.Create(
                                                                scriptFile.FilePath,
                                                                (int)srcBreakpoint.Line,
                                                                (int?)srcBreakpoint.Column,
                                                                srcBreakpoint.Condition,
                                                                srcBreakpoint.HitCondition))
                                                    .ToArray();

            // If this is a "run without debugging (Ctrl+F5)" session ignore requests to set breakpoints.
            BreakpointDetails[] updatedBreakpointDetails = breakpointDetails;
            if (!_debugStateService.NoDebug)
            {
                _debugStateService.SetBreakpointInProgress = true;

                try
                {
                    updatedBreakpointDetails =
                        await _debugService.SetLineBreakpointsAsync(
                            scriptFile,
                            breakpointDetails);
                }
                catch (Exception e)
                {
                    // Log whatever the error is
                    _logger.LogException($"Caught error while setting breakpoints in SetBreakpoints handler for file {scriptFile?.FilePath}", e);
                }
                finally
                {
                    _debugStateService.SetBreakpointInProgress = false;
                }
            }

            return(new SetBreakpointsResponse
            {
                Breakpoints = new Container <Breakpoint>(updatedBreakpointDetails
                                                         .Select(LspDebugUtils.CreateBreakpoint))
            });
        }
Esempio n. 22
0
        protected async Task HandleSetBreakpointsRequest(
            SetBreakpointsRequestArguments setBreakpointsParams,
            RequestContext <SetBreakpointsResponseBody> requestContext)
        {
            ScriptFile scriptFile = null;

            // Fix for issue #195 - user can change name of file outside of VSCode in which case
            // VSCode sends breakpoint requests with the original filename that doesn't exist anymore.
            try
            {
                scriptFile = editorSession.Workspace.GetFile(setBreakpointsParams.Source.Path);
            }
            catch (Exception e) when(e is FileNotFoundException || e is DirectoryNotFoundException)
            {
                Logger.Write(
                    LogLevel.Warning,
                    $"Attempted to set breakpoints on a non-existing file: {setBreakpointsParams.Source.Path}");

                string message = this.noDebug ? string.Empty : "Source does not exist, breakpoint not set.";

                var srcBreakpoints = setBreakpointsParams.Breakpoints
                                     .Select(srcBkpt => Protocol.DebugAdapter.Breakpoint.Create(
                                                 srcBkpt, setBreakpointsParams.Source.Path, message, verified: this.noDebug));

                // Return non-verified breakpoint message.
                await requestContext.SendResult(
                    new SetBreakpointsResponseBody {
                    Breakpoints = srcBreakpoints.ToArray()
                });

                return;
            }

            var breakpointDetails = new BreakpointDetails[setBreakpointsParams.Breakpoints.Length];

            for (int i = 0; i < breakpointDetails.Length; i++)
            {
                SourceBreakpoint srcBreakpoint = setBreakpointsParams.Breakpoints[i];
                breakpointDetails[i] = BreakpointDetails.Create(
                    scriptFile.FilePath,
                    srcBreakpoint.Line,
                    srcBreakpoint.Column,
                    srcBreakpoint.Condition,
                    srcBreakpoint.HitCondition);
            }

            // If this is a "run without debugging (Ctrl+F5)" session ignore requests to set breakpoints.
            BreakpointDetails[] updatedBreakpointDetails = breakpointDetails;
            if (!this.noDebug)
            {
                this.setBreakpointInProgress = true;

                try
                {
                    updatedBreakpointDetails =
                        await editorSession.DebugService.SetLineBreakpoints(
                            scriptFile,
                            breakpointDetails);
                }
                catch (Exception e)
                {
                    // Log whatever the error is
                    Logger.WriteException("Caught error while setting breakpoints in SetBreakpoints handler", e);
                }
                finally
                {
                    this.setBreakpointInProgress = false;
                }
            }

            await requestContext.SendResult(
                new SetBreakpointsResponseBody {
                Breakpoints =
                    updatedBreakpointDetails
                    .Select(Protocol.DebugAdapter.Breakpoint.Create)
                    .ToArray()
            });
        }
        protected async Task HandleSetBreakpointsRequestAsync(
            SetBreakpointsRequestArguments setBreakpointsParams,
            RequestContext <SetBreakpointsResponseBody> requestContext)
        {
            ScriptFile scriptFile = null;

            // When you set a breakpoint in the right pane of a Git diff window on a PS1 file,
            // the Source.Path comes through as Untitled-X. That's why we check for IsUntitledPath.
            if (!ScriptFile.IsUntitledPath(setBreakpointsParams.Source.Path) &&
                !_editorSession.Workspace.TryGetFile(
                    setBreakpointsParams.Source.Path,
                    out scriptFile))
            {
                string message        = _noDebug ? string.Empty : "Source file could not be accessed, breakpoint not set.";
                var    srcBreakpoints = setBreakpointsParams.Breakpoints
                                        .Select(srcBkpt => Protocol.DebugAdapter.Breakpoint.Create(
                                                    srcBkpt, setBreakpointsParams.Source.Path, message, verified: _noDebug));

                // Return non-verified breakpoint message.
                await requestContext.SendResultAsync(
                    new SetBreakpointsResponseBody {
                    Breakpoints = srcBreakpoints.ToArray()
                });

                return;
            }

            // Verify source file is a PowerShell script file.
            string fileExtension = Path.GetExtension(scriptFile?.FilePath ?? "")?.ToLower();

            if (string.IsNullOrEmpty(fileExtension) || ((fileExtension != ".ps1") && (fileExtension != ".psm1")))
            {
                Logger.Write(
                    LogLevel.Warning,
                    $"Attempted to set breakpoints on a non-PowerShell file: {setBreakpointsParams.Source.Path}");

                string message = _noDebug ? string.Empty : "Source is not a PowerShell script, breakpoint not set.";

                var srcBreakpoints = setBreakpointsParams.Breakpoints
                                     .Select(srcBkpt => Protocol.DebugAdapter.Breakpoint.Create(
                                                 srcBkpt, setBreakpointsParams.Source.Path, message, verified: _noDebug));

                // Return non-verified breakpoint message.
                await requestContext.SendResultAsync(
                    new SetBreakpointsResponseBody
                {
                    Breakpoints = srcBreakpoints.ToArray()
                });

                return;
            }

            // At this point, the source file has been verified as a PowerShell script.
            var breakpointDetails = new BreakpointDetails[setBreakpointsParams.Breakpoints.Length];

            for (int i = 0; i < breakpointDetails.Length; i++)
            {
                SourceBreakpoint srcBreakpoint = setBreakpointsParams.Breakpoints[i];
                breakpointDetails[i] = BreakpointDetails.Create(
                    scriptFile.FilePath,
                    srcBreakpoint.Line,
                    srcBreakpoint.Column,
                    srcBreakpoint.Condition,
                    srcBreakpoint.HitCondition);
            }

            // If this is a "run without debugging (Ctrl+F5)" session ignore requests to set breakpoints.
            BreakpointDetails[] updatedBreakpointDetails = breakpointDetails;
            if (!_noDebug)
            {
                _setBreakpointInProgress = true;

                try
                {
                    updatedBreakpointDetails =
                        await _editorSession.DebugService.SetLineBreakpointsAsync(
                            scriptFile,
                            breakpointDetails);
                }
                catch (Exception e)
                {
                    // Log whatever the error is
                    Logger.WriteException($"Caught error while setting breakpoints in SetBreakpoints handler for file {scriptFile?.FilePath}", e);
                }
                finally
                {
                    _setBreakpointInProgress = false;
                }
            }

            await requestContext.SendResultAsync(
                new SetBreakpointsResponseBody {
                Breakpoints =
                    updatedBreakpointDetails
                    .Select(Protocol.DebugAdapter.Breakpoint.Create)
                    .ToArray()
            });
        }
        public async Task <IEnumerable <BreakpointDetails> > SetBreakpointsAsync(string escapedScriptPath, IEnumerable <BreakpointDetails> breakpoints)
        {
            if (BreakpointApiUtils.SupportsBreakpointApis)
            {
                foreach (BreakpointDetails breakpointDetails in breakpoints)
                {
                    try
                    {
                        BreakpointApiUtils.SetBreakpoint(_powerShellContextService.CurrentRunspace.Runspace.Debugger, breakpointDetails, _debugStateService.RunspaceId);
                    }
                    catch (InvalidOperationException e)
                    {
                        breakpointDetails.Message  = e.Message;
                        breakpointDetails.Verified = false;
                    }
                }

                return(breakpoints);
            }

            // Legacy behavior
            PSCommand psCommand = null;
            List <BreakpointDetails> configuredBreakpoints = new List <BreakpointDetails>();

            foreach (BreakpointDetails breakpoint in breakpoints)
            {
                ScriptBlock actionScriptBlock = null;

                // Check if this is a "conditional" line breakpoint.
                if (!string.IsNullOrWhiteSpace(breakpoint.Condition) ||
                    !string.IsNullOrWhiteSpace(breakpoint.HitCondition) ||
                    !string.IsNullOrWhiteSpace(breakpoint.LogMessage))
                {
                    actionScriptBlock = BreakpointApiUtils.GetBreakpointActionScriptBlock(
                        breakpoint.Condition,
                        breakpoint.HitCondition,
                        breakpoint.LogMessage,
                        out string errorMessage);

                    if (!string.IsNullOrEmpty(errorMessage))
                    {
                        breakpoint.Verified = false;
                        breakpoint.Message  = errorMessage;
                        configuredBreakpoints.Add(breakpoint);
                        continue;
                    }
                }

                // On first iteration psCommand will be null, every subsequent
                // iteration will need to start a new statement.
                if (psCommand == null)
                {
                    psCommand = new PSCommand();
                }
                else
                {
                    psCommand.AddStatement();
                }

                psCommand
                .AddCommand(@"Microsoft.PowerShell.Utility\Set-PSBreakpoint")
                .AddParameter("Script", escapedScriptPath)
                .AddParameter("Line", breakpoint.LineNumber);

                // Check if the user has specified the column number for the breakpoint.
                if (breakpoint.ColumnNumber.HasValue && breakpoint.ColumnNumber.Value > 0)
                {
                    // It bums me out that PowerShell will silently ignore a breakpoint
                    // where either the line or the column is invalid.  I'd rather have an
                    // error or warning message I could relay back to the client.
                    psCommand.AddParameter("Column", breakpoint.ColumnNumber.Value);
                }

                if (actionScriptBlock != null)
                {
                    psCommand.AddParameter("Action", actionScriptBlock);
                }
            }

            // If no PSCommand was created then there are no breakpoints to set.
            if (psCommand != null)
            {
                IEnumerable <Breakpoint> setBreakpoints =
                    await _powerShellContextService.ExecuteCommandAsync <Breakpoint>(psCommand).ConfigureAwait(false);

                configuredBreakpoints.AddRange(
                    setBreakpoints.Select((breakpoint) => BreakpointDetails.Create(breakpoint))
                    );
            }

            return(configuredBreakpoints);
        }