Skip to content

Depend on DocumentUri for handing vscode Uri's #1291

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
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 @@ -3,14 +3,14 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

using System;
using System.Collections.Generic;
using Microsoft.PowerShell.EditorServices.Services;
using Microsoft.PowerShell.EditorServices.Services.Symbols;
using Microsoft.PowerShell.EditorServices.Services.TextDocument;
using Microsoft.PowerShell.EditorServices.Utility;
using Newtonsoft.Json.Linq;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using OmniSharp.Extensions.LanguageServer.Protocol.Serialization;

namespace Microsoft.PowerShell.EditorServices.CodeLenses
{
Expand Down Expand Up @@ -60,11 +60,14 @@ private CodeLens[] GetPesterLens(PesterSymbolReference pesterSymbol, ScriptFile
{
Name = "PowerShell.RunPesterTests",
Title = $"Run {word}",
Arguments = JArray.FromObject(new object[] {
Arguments = JArray.FromObject(new object[]
{
scriptFile.DocumentUri,
false /* No debug */,
pesterSymbol.TestName,
pesterSymbol.ScriptRegion?.StartLineNumber })
pesterSymbol.ScriptRegion?.StartLineNumber
},
Serializer.Instance.JsonSerializer)
}
},

Expand All @@ -79,11 +82,14 @@ private CodeLens[] GetPesterLens(PesterSymbolReference pesterSymbol, ScriptFile
{
Name = "PowerShell.RunPesterTests",
Title = $"Debug {word}",
Arguments = JArray.FromObject(new object[] {
Arguments = JArray.FromObject(new object[]
{
scriptFile.DocumentUri,
true /* No debug */,
pesterSymbol.TestName,
pesterSymbol.ScriptRegion?.StartLineNumber })
pesterSymbol.ScriptRegion?.StartLineNumber
},
Serializer.Instance.JsonSerializer)
}
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
using Microsoft.PowerShell.EditorServices.Services.TextDocument;
using Microsoft.PowerShell.EditorServices.Utility;
using Newtonsoft.Json.Linq;
using OmniSharp.Extensions.LanguageServer.Protocol;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using OmniSharp.Extensions.LanguageServer.Protocol.Serialization;

namespace Microsoft.PowerShell.EditorServices.CodeLenses
{
Expand Down Expand Up @@ -113,7 +115,7 @@ public CodeLens ResolveCodeLens(CodeLens codeLens, ScriptFile scriptFile)

acc.Add(new Location
{
Uri = PathUtils.ToUri(foundReference.FilePath),
Uri = DocumentUri.FromFileSystemPath(foundReference.FilePath),
Range = foundReference.ScriptRegion.ToRange()
});
}
Expand All @@ -133,7 +135,8 @@ public CodeLens ResolveCodeLens(CodeLens codeLens, ScriptFile scriptFile)
scriptFile.DocumentUri,
codeLens.Range.Start,
referenceLocations
})
},
Serializer.Instance.JsonSerializer)
}
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,8 @@ public SymbolReference(
/// </summary>
/// <param name="symbolType">The higher level type of the symbol</param>
/// <param name="scriptExtent">The script extent of the symbol</param>
/// <param name="filePath">The file path of the symbol</param>
/// <param name="sourceLine">The line contents of the given symbol (defaults to empty string)</param>
public SymbolReference(SymbolType symbolType, IScriptExtent scriptExtent, string filePath = "", string sourceLine = "")
: this(symbolType, scriptExtent.Text, scriptExtent, filePath, sourceLine)
public SymbolReference(SymbolType symbolType, IScriptExtent scriptExtent)
: this(symbolType, scriptExtent.Text, scriptExtent, scriptExtent.File, "")
{
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
StartLineNumber = startLineNumber,
EndLineNumber = startLineNumber,
StartColumnNumber = startColumnNumber,
EndColumnNumber = startColumnNumber + functionDefinitionAst.Name.Length
EndColumnNumber = startColumnNumber + functionDefinitionAst.Name.Length,
File = functionDefinitionAst.Extent.File
};

if (symbolRef.SymbolType.Equals(SymbolType.Function) &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
StartLineNumber = functionDefinitionAst.Extent.StartLineNumber,
EndLineNumber = functionDefinitionAst.Extent.EndLineNumber,
StartColumnNumber = startColumnNumber,
EndColumnNumber = startColumnNumber + functionDefinitionAst.Name.Length
EndColumnNumber = startColumnNumber + functionDefinitionAst.Name.Length,
File = functionDefinitionAst.Extent.File
};

if (this.IsPositionInExtent(nameExtent))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
StartLineNumber = functionDefinitionAst.Extent.StartLineNumber,
EndLineNumber = functionDefinitionAst.Extent.EndLineNumber,
StartColumnNumber = functionDefinitionAst.Extent.StartColumnNumber,
EndColumnNumber = functionDefinitionAst.Extent.EndColumnNumber
EndColumnNumber = functionDefinitionAst.Extent.EndColumnNumber,
File = functionDefinitionAst.Extent.File
};

SymbolType symbolType =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Microsoft.PowerShell.EditorServices.Services.Symbols;
using Microsoft.PowerShell.EditorServices.Services.TextDocument;
using Microsoft.PowerShell.EditorServices.Utility;
using OmniSharp.Extensions.LanguageServer.Protocol;
using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
Expand Down Expand Up @@ -66,7 +67,7 @@ public async Task<LocationOrLocationLinks> Handle(DefinitionParams request, Canc
new LocationOrLocationLink(
new Location
{
Uri = PathUtils.ToUri(foundDefinition.FilePath),
Uri = DocumentUri.FromFileSystemPath(foundDefinition.FilePath),
Range = GetRangeFromScriptRegion(foundDefinition.ScriptRegion)
}));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using Microsoft.PowerShell.EditorServices.Services.Symbols;
using Microsoft.PowerShell.EditorServices.Services.TextDocument;
using Microsoft.PowerShell.EditorServices.Utility;
using OmniSharp.Extensions.LanguageServer.Protocol;
using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
Expand Down Expand Up @@ -74,7 +75,7 @@ public Task<SymbolInformationOrDocumentSymbolContainer> Handle(DocumentSymbolPar
Kind = GetSymbolKind(r.SymbolType),
Location = new Location
{
Uri = PathUtils.ToUri(r.FilePath),
Uri = DocumentUri.FromFileSystemPath(r.FilePath),
Range = GetRangeFromScriptRegion(r.ScriptRegion)
},
Name = GetDecoratedSymbolName(r)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Microsoft.PowerShell.EditorServices.Services.Symbols;
using Microsoft.PowerShell.EditorServices.Services.TextDocument;
using Microsoft.PowerShell.EditorServices.Utility;
using OmniSharp.Extensions.LanguageServer.Protocol;
using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
Expand Down Expand Up @@ -63,7 +64,7 @@ public Task<LocationContainer> Handle(ReferenceParams request, CancellationToken
{
locations.Add(new Location
{
Uri = PathUtils.ToUri(foundReference.FilePath),
Uri = DocumentUri.FromFileSystemPath(foundReference.FilePath),
Range = GetRangeFromScriptRegion(foundReference.ScriptRegion)
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,10 @@ public string DocumentUri
{
get
{
// TODO: Have this be a DocumentUri type and stop having it be computed every time.
return this.ClientFilePath == null
? string.Empty
: WorkspaceService.ConvertPathToDocumentUri(this.ClientFilePath);
: OmniSharp.Extensions.LanguageServer.Protocol.DocumentUri.FromFileSystemPath(ClientFilePath)?.ToString();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
using Microsoft.PowerShell.EditorServices.Services;
using Microsoft.PowerShell.EditorServices.Services.Symbols;
using Microsoft.PowerShell.EditorServices.Services.TextDocument;
using Microsoft.PowerShell.EditorServices.Utility;
using OmniSharp.Extensions.LanguageServer.Protocol;
using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
Expand Down Expand Up @@ -59,7 +59,7 @@ public Task<Container<SymbolInformation>> Handle(WorkspaceSymbolParams request,

var location = new Location
{
Uri = PathUtils.ToUri(foundOccurrence.FilePath),
Uri = DocumentUri.FromFileSystemPath(foundOccurrence.FilePath),
Range = GetRangeFromScriptRegion(foundOccurrence.ScriptRegion)
};

Expand Down
147 changes: 0 additions & 147 deletions src/PowerShellEditorServices/Services/Workspace/WorkspaceService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using System.IO;
using System.Security;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Extensions.FileSystemGlobbing;
using Microsoft.Extensions.Logging;
using Microsoft.PowerShell.EditorServices.Utility;
Expand Down Expand Up @@ -462,17 +461,6 @@ private void RecursivelyFindReferences(
}
}

internal Uri ResolveFileUri(Uri fileUri)
{
if (fileUri.IsFile)
{
fileUri = WorkspaceService.UnescapeDriveColon(fileUri);
}

this.logger.LogDebug("Resolved path: " + fileUri.OriginalString);
return fileUri;
}

internal static bool IsPathInMemory(string filePath)
{
bool isInMemory = false;
Expand Down Expand Up @@ -562,141 +550,6 @@ internal string ResolveRelativeScriptPath(string baseFilePath, string relativePa
return combinedPath;
}

private static Uri UnescapeDriveColon(Uri fileUri)
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return fileUri;
}

string driveSegment = fileUri.Segments[1];
// Check here that we have something like "file:///C%3A/" as a prefix (caller must check the file:// part)
if (!(char.IsLetter(driveSegment[0]) &&
driveSegment[1] == '%' &&
driveSegment[2] == '3' &&
driveSegment[3] == 'A' &&
driveSegment[4] == '/'))
{
return fileUri;
}

// We lost "%3A" and gained ":", so length - 2
var sb = new StringBuilder(fileUri.OriginalString.Length - 2);
sb.Append("file:///");

// The drive letter.
sb.Append(driveSegment[0]);
sb.Append(":/");

// The rest of the URI after the colon.
// Skip the first two segments which are / and the drive.
for (int i = 2; i < fileUri.Segments.Length; i++)
{
sb.Append(fileUri.Segments[i]);
}

return new Uri(sb.ToString());
}

/// <summary>
/// Converts a file system path into a DocumentUri required by Language Server Protocol.
/// </summary>
/// <remarks>
/// When sending a document path to a LSP client, the path must be provided as a
/// DocumentUri in order to features like the Problems window or peek definition
/// to be able to open the specified file.
/// </remarks>
/// <param name="path">
/// A file system path. Note: if the path is already a DocumentUri, it will be returned unmodified.
/// </param>
/// <returns>The file system path encoded as a DocumentUri.</returns>
public static string ConvertPathToDocumentUri(string path)
{
const string fileUriPrefix = "file:";
const string untitledUriPrefix = "untitled:";

// If path is already in document uri form, there is nothing to convert.
if (path.StartsWith(untitledUriPrefix, StringComparison.Ordinal) ||
path.StartsWith(fileUriPrefix, StringComparison.Ordinal))
{
return path;
}

string escapedPath = Uri.EscapeDataString(path);

// Max capacity of the StringBuilder will be the current escapedPath length
// plus extra chars for file:///.
var docUriStrBld = new StringBuilder(escapedPath.Length + fileUriPrefix.Length + 3);
docUriStrBld.Append(fileUriPrefix).Append("//");

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
// VSCode file URIs on Windows need the drive letter to be lowercase. Search the
// original path for colon since a char search (no string culture involved) is
// faster than a string search. If found, then lowercase the associated drive letter.
if (path.Contains(':'))
{
// A valid, drive-letter based path converted to URI form needs to be prefixed
// with a / to indicate the path is an absolute path.
docUriStrBld.Append("/");
int prefixLen = docUriStrBld.Length;

docUriStrBld.Append(escapedPath);

// Uri.EscapeDataString goes a bit far, encoding \ chars. Also, VSCode wants / instead of \.
docUriStrBld.Replace("%5C", "/");

// Find the first colon after the "file:///" prefix, skipping the first char after
// the prefix since a Windows path cannot start with a colon. End the check at
// less than docUriStrBld.Length - 2 since we need to look-ahead two characters.
for (int i = prefixLen + 1; i < docUriStrBld.Length - 2; i++)
{
if ((docUriStrBld[i] == '%') && (docUriStrBld[i + 1] == '3') && (docUriStrBld[i + 2] == 'A'))
{
int driveLetterIndex = i - 1;
char driveLetter = char.ToLowerInvariant(docUriStrBld[driveLetterIndex]);
docUriStrBld.Replace(docUriStrBld[driveLetterIndex], driveLetter, driveLetterIndex, 1);
break;
}
}
}
else
{
// This is a Windows path without a drive specifier, must be either a relative or UNC path.
int prefixLen = docUriStrBld.Length;

docUriStrBld.Append(escapedPath);

// Uri.EscapeDataString goes a bit far, encoding \ chars. Also, VSCode wants / instead of \.
docUriStrBld.Replace("%5C", "/");

// The proper URI form for a UNC path is file://server/share. In the case of a UNC
// path, remove the path's leading // because the file:// prefix already provides it.
if ((docUriStrBld.Length > prefixLen + 1) &&
(docUriStrBld[prefixLen] == '/') &&
(docUriStrBld[prefixLen + 1] == '/'))
{
docUriStrBld.Remove(prefixLen, 2);
}
}
}
else
{
// On non-Windows systems, append the escapedPath and undo the over-aggressive
// escaping of / done by Uri.EscapeDataString.
docUriStrBld.Append(escapedPath).Replace("%2F", "/");
}

if (!VersionUtils.IsNetCore)
{
// ' is not encoded by Uri.EscapeDataString in Windows PowerShell 5.x.
// This is apparently a difference between .NET Framework and .NET Core.
docUriStrBld.Replace("'", "%27");
}

return docUriStrBld.ToString();
}

#endregion
}
}
Loading