Skip to content

Commit 06db46e

Browse files
committed
Add razor redirector implementation
1 parent a18e3a6 commit 06db46e

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Microsoft.CodeAnalysis.Razor.CohostingShared.projitems

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
<Compile Include="$(MSBuildThisFileDirectory)Formatting\CohostRangeFormattingEndpoint.cs" />
3333
<Compile Include="$(MSBuildThisFileDirectory)OnAutoInsert\CohostOnAutoInsertEndpoint.cs" />
3434
<Compile Include="$(MSBuildThisFileDirectory)OnAutoInsert\CohostOnAutoInsertTriggerCharacterProviders.cs" />
35+
<Compile Include="$(MSBuildThisFileDirectory)RazorAnalyzerAssemblyRedirector.cs" />
3536
<Compile Include="$(MSBuildThisFileDirectory)Rename\CohostRenameEndpoint.cs" />
3637
<Compile Include="$(MSBuildThisFileDirectory)SignatureHelp\CohostSignatureHelpEndpoint.cs" />
3738
<Compile Include="$(MSBuildThisFileDirectory)FoldingRange\CohostFoldingRangeEndpoint.cs" />
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT license. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Collections.Immutable;
6+
using System.IO;
7+
using System.Reflection;
8+
using System.Composition;
9+
using IRazorAnalyzerAssemblyRedirector = Microsoft.CodeAnalysis.ExternalAccess.Razor.RazorAnalyzerAssemblyRedirector.IRazorAnalyzerAssemblyRedirector;
10+
11+
namespace Microsoft.VisualStudio.Razor;
12+
13+
#pragma warning disable RS0030 // Do not use banned APIs
14+
[Shared]
15+
[Export(typeof(IRazorAnalyzerAssemblyRedirector))]
16+
[method: ImportingConstructor]
17+
#pragma warning restore RS0030 // Do not use banned APIs
18+
internal class RazorAnalyzerAssemblyRedirector() : IRazorAnalyzerAssemblyRedirector
19+
{
20+
private static readonly ImmutableArray<Type> s_compilerAssemblyTypes = [
21+
22+
typeof(CodeAnalysis.Razor.CompilerFeatures), // Microsoft.CodeAnalysis.Razor.Compiler.dll
23+
typeof(AspNetCore.Razor.ArgHelper), // Microsoft.AspNetCore.Razor.Utilities.Shared.dll
24+
25+
// The following dependencies will be provided by the Compiler ALC so its not strictly required to redirect them, but we do so for completeness.
26+
typeof(Microsoft.Extensions.ObjectPool.ObjectPool), // Microsoft.Extensions.ObjectPool.dll
27+
typeof(ImmutableArray) // System.Collections.Immutable.dll
28+
];
29+
30+
private static readonly ImmutableDictionary<string, string> s_compilerAssemblyMap = s_compilerAssemblyTypes.ToImmutableDictionary(t => t.Assembly.GetName().Name!, t => GetAssemblyLocation(t.Assembly));
31+
32+
public string? RedirectPath(string fullPath)
33+
{
34+
var name = Path.GetFileNameWithoutExtension(fullPath);
35+
return s_compilerAssemblyMap.TryGetValue(name, out var path) ? path : null;
36+
}
37+
38+
private static string GetAssemblyLocation(Assembly assembly)
39+
{
40+
var location = assembly.Location;
41+
var name = Path.GetFileName(location);
42+
var directory = Path.GetDirectoryName(location) ?? "";
43+
44+
// In VS on windows, depending on who wins the race to load these assemblies, the base directory will either be the tooling root (if Roslyn wins)
45+
// or the ServiceHubCore subfolder (razor). In the root directory these are netstandard2.0 targeted, in ServiceHubCore they are .NET targeted.
46+
// We need to always pick the same set of assemblies regardless of who causes us to load. Because this code only runs in a .NET based host,
47+
// we want to prefer the .NET targeted ServiceHubCore versions if they exist.
48+
var serviceHubCoreVersion = Path.Combine(directory, "ServiceHubCore", name);
49+
if (File.Exists(serviceHubCoreVersion))
50+
{
51+
return serviceHubCoreVersion;
52+
}
53+
54+
return location;
55+
}
56+
}

0 commit comments

Comments
 (0)