diff --git a/src/PowerShellEditorServices.Protocol/Server/LanguageServer.cs b/src/PowerShellEditorServices.Protocol/Server/LanguageServer.cs index 81fc92341..a13f8ee11 100644 --- a/src/PowerShellEditorServices.Protocol/Server/LanguageServer.cs +++ b/src/PowerShellEditorServices.Protocol/Server/LanguageServer.cs @@ -1376,15 +1376,24 @@ protected Task HandleEvaluateRequest( #region Event Handlers - private FoldingRange[] Fold( - string documentUri) + private FoldingRange[] Fold(string documentUri) { // TODO Should be using dynamic registrations if (!this.currentSettings.CodeFolding.Enable) { return null; } + + // Avoid crash when using untitled: scheme or any other scheme where the document doesn't + // have a backing file. https://github.com/PowerShell/vscode-powershell/issues/1676 + // Perhaps a better option would be to parse the contents of the document as a string + // as opposed to reading a file but the senario of "no backing file" probably doesn't + // warrant the extra effort. + ScriptFile scriptFile; + if (!editorSession.Workspace.TryGetFile(documentUri, out scriptFile)) { return null; } + var result = new List(); - foreach (FoldingReference fold in TokenOperations.FoldableRegions( - editorSession.Workspace.GetFile(documentUri).ScriptTokens, - this.currentSettings.CodeFolding.ShowLastLine)) + FoldingReference[] foldableRegions = + TokenOperations.FoldableRegions(scriptFile.ScriptTokens, this.currentSettings.CodeFolding.ShowLastLine); + + foreach (FoldingReference fold in foldableRegions) { result.Add(new FoldingRange { EndCharacter = fold.EndCharacter, @@ -1394,6 +1403,7 @@ private FoldingRange[] Fold( StartLine = fold.StartLine }); } + return result.ToArray(); } diff --git a/src/PowerShellEditorServices/Workspace/Workspace.cs b/src/PowerShellEditorServices/Workspace/Workspace.cs index 69847ee4d..d74bf4955 100644 --- a/src/PowerShellEditorServices/Workspace/Workspace.cs +++ b/src/PowerShellEditorServices/Workspace/Workspace.cs @@ -91,8 +91,9 @@ public ScriptFile CreateScriptFileFromFileBuffer(string filePath, string initial } /// - /// Gets an open file in the workspace. If the file isn't open but - /// exists on the filesystem, load and return it. + /// Gets an open file in the workspace. If the file isn't open but exists on the filesystem, load and return it. + /// IMPORTANT: Not all documents have a backing file e.g. untitled: scheme documents. Consider using + /// instead. /// /// The file path at which the script resides. /// @@ -154,9 +155,7 @@ e is DirectoryNotFoundException || e is PathTooLongException || e is UnauthorizedAccessException) { - this.logger.WriteException( - $"Failed to set breakpoint on file: {filePath}", - e); + this.logger.WriteHandledException($"Failed to get file for {nameof(filePath)}: '{filePath}'", e); scriptFile = null; return false; }