Skip to content

Commit 9f64562

Browse files
Fix untitled file references (#1177)
* fix untitled file references * cleanup more code
1 parent d7c2893 commit 9f64562

File tree

2 files changed

+19
-117
lines changed

2 files changed

+19
-117
lines changed

src/PowerShellEditorServices/Services/TextDocument/ScriptFile.cs

+14-31
Original file line numberDiff line numberDiff line change
@@ -150,20 +150,24 @@ public string[] ReferencedFiles
150150
/// Creates a new ScriptFile instance by reading file contents from
151151
/// the given TextReader.
152152
/// </summary>
153-
/// <param name="filePath">The path at which the script file resides.</param>
154-
/// <param name="clientFilePath">The path which the client uses to identify the file.</param>
153+
/// <param name="fileUri">The System.Uri of the file.</param>
155154
/// <param name="textReader">The TextReader to use for reading the file's contents.</param>
156155
/// <param name="powerShellVersion">The version of PowerShell for which the script is being parsed.</param>
157156
public ScriptFile(
158-
string filePath,
159-
string clientFilePath,
157+
Uri fileUri,
160158
TextReader textReader,
161159
Version powerShellVersion)
162160
{
163-
this.FilePath = filePath;
164-
this.ClientFilePath = clientFilePath;
161+
// For non-files, use their URI representation instead
162+
// so that other operations know it's untitled/in-memory
163+
// and don't think that it's a relative path
164+
// on the file system.
165+
this.FilePath = fileUri.IsFile
166+
? fileUri.LocalPath
167+
: fileUri.OriginalString;
168+
this.ClientFilePath = fileUri.OriginalString;
165169
this.IsAnalysisEnabled = true;
166-
this.IsInMemory = WorkspaceService.IsPathInMemory(filePath);
170+
this.IsInMemory = !fileUri.IsFile;
167171
this.powerShellVersion = powerShellVersion;
168172

169173
// SetFileContents() calls ParseFileContents() which initializes the rest of the properties.
@@ -173,41 +177,20 @@ public ScriptFile(
173177
/// <summary>
174178
/// Creates a new ScriptFile instance with the specified file contents.
175179
/// </summary>
176-
/// <param name="filePath">The path at which the script file resides.</param>
177-
/// <param name="clientFilePath">The path which the client uses to identify the file.</param>
180+
/// <param name="fileUri">The System.Uri of the file.</param>
178181
/// <param name="initialBuffer">The initial contents of the script file.</param>
179182
/// <param name="powerShellVersion">The version of PowerShell for which the script is being parsed.</param>
180183
public ScriptFile(
181-
string filePath,
182-
string clientFilePath,
184+
Uri fileUri,
183185
string initialBuffer,
184186
Version powerShellVersion)
185187
: this(
186-
filePath,
187-
clientFilePath,
188+
fileUri,
188189
new StringReader(initialBuffer),
189190
powerShellVersion)
190191
{
191192
}
192193

193-
/// <summary>
194-
/// Creates a new ScriptFile instance with the specified filepath.
195-
/// </summary>
196-
/// <param name="filePath">The path at which the script file resides.</param>
197-
/// <param name="clientFilePath">The path which the client uses to identify the file.</param>
198-
/// <param name="powerShellVersion">The version of PowerShell for which the script is being parsed.</param>
199-
public ScriptFile(
200-
string filePath,
201-
string clientFilePath,
202-
Version powerShellVersion)
203-
: this(
204-
filePath,
205-
clientFilePath,
206-
File.ReadAllText(filePath),
207-
powerShellVersion)
208-
{
209-
}
210-
211194
#endregion
212195

213196
#region Public Methods

src/PowerShellEditorServices/Services/Workspace/WorkspaceService.cs

+5-86
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,7 @@ public ScriptFile GetFile(Uri fileUri)
142142
{
143143
scriptFile =
144144
new ScriptFile(
145-
resolvedFileUri.LocalPath,
146-
resolvedFileUri.OriginalString,
145+
resolvedFileUri,
147146
streamReader,
148147
this.powerShellVersion);
149148

@@ -249,8 +248,7 @@ public ScriptFile GetFileBuffer(Uri fileUri, string initialBuffer)
249248
{
250249
scriptFile =
251250
new ScriptFile(
252-
resolvedFileUri.LocalPath,
253-
resolvedFileUri.OriginalString,
251+
resolvedFileUri,
254252
initialBuffer,
255253
this.powerShellVersion);
256254

@@ -399,9 +397,9 @@ private void RecursivelyFindReferences(
399397
Dictionary<string, ScriptFile> referencedScriptFiles)
400398
{
401399
// Get the base path of the current script for use in resolving relative paths
402-
string baseFilePath =
403-
GetBaseFilePath(
404-
scriptFile.FilePath);
400+
string baseFilePath = scriptFile.IsInMemory
401+
? WorkspacePath
402+
: Path.GetDirectoryName(scriptFile.FilePath);
405403

406404
foreach (string referencedFileName in scriptFile.ReferencedFiles)
407405
{
@@ -437,31 +435,6 @@ private void RecursivelyFindReferences(
437435
}
438436
}
439437

440-
internal string ResolveFilePath(string filePath)
441-
{
442-
if (!IsPathInMemory(filePath))
443-
{
444-
if (filePath.StartsWith(@"file://"))
445-
{
446-
filePath = WorkspaceService.UnescapeDriveColon(filePath);
447-
// Client sent the path in URI format, extract the local path
448-
filePath = new Uri(filePath).LocalPath;
449-
}
450-
451-
// Clients could specify paths with escaped space, [ and ] characters which .NET APIs
452-
// will not handle. These paths will get appropriately escaped just before being passed
453-
// into the PowerShell engine.
454-
//filePath = PowerShellContext.UnescapeWildcardEscapedPath(filePath);
455-
456-
// Get the absolute file path
457-
filePath = Path.GetFullPath(filePath);
458-
}
459-
460-
this.logger.LogDebug("Resolved path: " + filePath);
461-
462-
return filePath;
463-
}
464-
465438
internal Uri ResolveFileUri(Uri fileUri)
466439
{
467440
if (fileUri.IsFile)
@@ -509,27 +482,6 @@ internal static bool IsPathInMemory(string filePath)
509482
return isInMemory;
510483
}
511484

512-
private string GetBaseFilePath(string filePath)
513-
{
514-
if (IsPathInMemory(filePath))
515-
{
516-
// If the file is in memory, use the workspace path
517-
return this.WorkspacePath;
518-
}
519-
520-
if (!Path.IsPathRooted(filePath))
521-
{
522-
// TODO: Assert instead?
523-
throw new InvalidOperationException(
524-
string.Format(
525-
"Must provide a full path for originalScriptPath: {0}",
526-
filePath));
527-
}
528-
529-
// Get the directory of the file path
530-
return Path.GetDirectoryName(filePath);
531-
}
532-
533485
internal string ResolveRelativeScriptPath(string baseFilePath, string relativePath)
534486
{
535487
string combinedPath = null;
@@ -578,39 +530,6 @@ internal string ResolveRelativeScriptPath(string baseFilePath, string relativePa
578530
return combinedPath;
579531
}
580532

581-
/// <summary>
582-
/// Takes a file-scheme URI with an escaped colon after the drive letter and unescapes only the colon.
583-
/// VSCode sends escaped colons after drive letters, but System.Uri expects unescaped.
584-
/// </summary>
585-
/// <param name="fileUri">The fully-escaped file-scheme URI string.</param>
586-
/// <returns>A file-scheme URI string with the drive colon unescaped.</returns>
587-
private static string UnescapeDriveColon(string fileUri)
588-
{
589-
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
590-
{
591-
return fileUri;
592-
}
593-
594-
// Check here that we have something like "file:///C%3A/" as a prefix (caller must check the file:// part)
595-
if (!(fileUri[7] == '/' &&
596-
char.IsLetter(fileUri[8]) &&
597-
fileUri[9] == '%' &&
598-
fileUri[10] == '3' &&
599-
fileUri[11] == 'A' &&
600-
fileUri[12] == '/'))
601-
{
602-
return fileUri;
603-
}
604-
605-
var sb = new StringBuilder(fileUri.Length - 2); // We lost "%3A" and gained ":", so length - 2
606-
sb.Append("file:///");
607-
sb.Append(fileUri[8]); // The drive letter
608-
sb.Append(':');
609-
sb.Append(fileUri.Substring(12)); // The rest of the URI after the colon
610-
611-
return sb.ToString();
612-
}
613-
614533
private static Uri UnescapeDriveColon(Uri fileUri)
615534
{
616535
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))

0 commit comments

Comments
 (0)