Skip to content

Commit 81e791f

Browse files
Call RazorProjectFileSystem.GetItem(...) with correct path
Recently, a couple of calls to RazorProjectFileSystem.GetItem(...) were changed to pass a file path rather than a target path. This results in an exception being thrown in the DefaultRazorProjectFileSystem if the file path is rooted outside of the project root. Instead, it's important to pass the "target path", i.e. the "logical" path of a file within the project. This avoids breaking completely valid scenarios where a file is included in the Razor project from an outside path (such as a content file in a NuGet package).
1 parent d8e73ed commit 81e791f

File tree

4 files changed

+20
-12
lines changed

4 files changed

+20
-12
lines changed

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/CompilationHelpers.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ internal static async Task<RazorCodeDocument> GenerateCodeDocumentAsync(
2020
{
2121
var importSources = await GetImportSourcesAsync(document, projectEngine, cancellationToken).ConfigureAwait(false);
2222
var tagHelpers = await document.Project.GetTagHelpersAsync(cancellationToken).ConfigureAwait(false);
23-
var source = await document.GetSourceAsync(projectEngine, cancellationToken).ConfigureAwait(false);
23+
var source = await document.GetSourceAsync(cancellationToken).ConfigureAwait(false);
2424

2525
var generator = new CodeDocumentGenerator(projectEngine, compilerOptions);
2626
return generator.Generate(source, document.FileKind, importSources, tagHelpers, cancellationToken);
@@ -33,15 +33,18 @@ internal static async Task<RazorCodeDocument> GenerateDesignTimeCodeDocumentAsyn
3333
{
3434
var importSources = await GetImportSourcesAsync(document, projectEngine, cancellationToken).ConfigureAwait(false);
3535
var tagHelpers = await document.Project.GetTagHelpersAsync(cancellationToken).ConfigureAwait(false);
36-
var source = await document.GetSourceAsync(projectEngine, cancellationToken).ConfigureAwait(false);
36+
var source = await document.GetSourceAsync(cancellationToken).ConfigureAwait(false);
3737

3838
var generator = new CodeDocumentGenerator(projectEngine, RazorCompilerOptions.None);
3939
return generator.GenerateDesignTime(source, document.FileKind, importSources, tagHelpers, cancellationToken);
4040
}
4141

4242
private static async Task<ImmutableArray<RazorSourceDocument>> GetImportSourcesAsync(IDocumentSnapshot document, RazorProjectEngine projectEngine, CancellationToken cancellationToken)
4343
{
44-
var projectItem = projectEngine.FileSystem.GetItem(document.FilePath, document.FileKind);
44+
// We don't use document.FilePath when calling into GetItem(...) because
45+
// it could be rooted outside of the project root. document.TargetPath should
46+
// represent the logical relative path within the project root.
47+
var projectItem = projectEngine.FileSystem.GetItem(document.TargetPath, document.FileKind);
4548

4649
using var importProjectItems = new PooledArrayBuilder<RazorProjectItem>();
4750
projectEngine.CollectImports(projectItem, ref importProjectItems.AsRef());

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/IDocumentSnapshotExtensions.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,12 @@ namespace Microsoft.CodeAnalysis.Razor.ProjectSystem;
1111

1212
internal static class IDocumentSnapshotExtensions
1313
{
14-
public static async Task<RazorSourceDocument> GetSourceAsync(this IDocumentSnapshot document, RazorProjectEngine projectEngine, CancellationToken cancellationToken)
14+
public static async Task<RazorSourceDocument> GetSourceAsync(
15+
this IDocumentSnapshot document,
16+
CancellationToken cancellationToken)
1517
{
16-
var projectItem = document is { FilePath: string filePath, FileKind: var fileKind }
17-
? projectEngine.FileSystem.GetItem(filePath, fileKind)
18-
: null;
19-
2018
var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
21-
var properties = RazorSourceDocumentProperties.Create(document.FilePath, projectItem?.RelativePhysicalPath);
19+
var properties = RazorSourceDocumentProperties.Create(document.FilePath, document.TargetPath);
2220
return RazorSourceDocument.Create(text, properties);
2321
}
2422

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/Legacy/ILegacyDocumentSnapshot.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@ namespace Microsoft.CodeAnalysis.Razor.ProjectSystem.Legacy;
1111
/// </remarks>
1212
internal interface ILegacyDocumentSnapshot
1313
{
14+
string TargetPath { get; }
1415
string FileKind { get; }
1516
}

src/Razor/src/Microsoft.VisualStudio.LegacyEditor.Razor/ImportDocumentManager.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,16 @@ public void OnUnsubscribed(IVisualStudioDocumentTracker documentTracker)
9797
private static ImmutableArray<RazorProjectItem> GetPhysicalImportItems(string filePath, ILegacyProjectSnapshot projectSnapshot)
9898
{
9999
var projectEngine = projectSnapshot.GetProjectEngine();
100-
var documentSnapshot = projectSnapshot.GetDocument(filePath);
101-
var projectItem = projectEngine.FileSystem.GetItem(filePath, documentSnapshot?.FileKind);
102100

103-
return projectEngine.GetImports(projectItem, static i => i.PhysicalPath is not null);
101+
// If we can get the document, use it's target path to find the project item
102+
// to avoid GetItem(...) throwing an exception if the file path is rooted outside
103+
// of the project. If we can't get the document, we'll just go ahead and use
104+
// the file path, since it's probably OK.
105+
var projectItem = projectSnapshot.GetDocument(filePath) is { } document
106+
? projectEngine.FileSystem.GetItem(document.TargetPath, document.FileKind)
107+
: projectEngine.FileSystem.GetItem(filePath, fileKind: null);
108+
109+
return projectEngine.GetImports(projectItem, static i => i is not DefaultImportProjectItem);
104110
}
105111

106112
private void FileChangeTracker_Changed(object sender, FileChangeEventArgs args)

0 commit comments

Comments
 (0)