@@ -15,6 +15,8 @@ namespace Microsoft.CodeAnalysis.Tools.Analyzers
15
15
internal class AnalyzerReferenceInformationProvider : IAnalyzerInformationProvider
16
16
{
17
17
private static readonly Dictionary < string , Assembly > s_pathsToAssemblies = new ( StringComparer . OrdinalIgnoreCase ) ;
18
+ private static readonly Dictionary < string , Assembly > s_namesToAssemblies = new ( StringComparer . OrdinalIgnoreCase ) ;
19
+
18
20
private static readonly object s_guard = new ( ) ;
19
21
20
22
public ImmutableDictionary < ProjectId , AnalyzersAndFixers > GetAnalyzersAndFixers (
@@ -53,18 +55,7 @@ private AnalyzersAndFixers GetAnalyzersAndFixers(Project project)
53
55
54
56
try
55
57
{
56
- var analyzerDirectory = new DirectoryInfo ( Path . GetDirectoryName ( path ) ) ;
57
-
58
- // Analyzer packages will put language specific assemblies in subfolders.
59
- if ( analyzerDirectory . Name == "cs" || analyzerDirectory . Name == "vb" )
60
- {
61
- // Get the root analyzer folder.
62
- analyzerDirectory = analyzerDirectory . Parent ;
63
- }
64
-
65
- var context = new AnalyzerLoadContext ( analyzerDirectory . FullName ) ;
66
-
67
- // First try loading the assembly from disk.
58
+ var context = new AnalyzerLoadContext ( path ) ;
68
59
var assembly = context . LoadFromAssemblyPath ( path ) ;
69
60
70
61
s_pathsToAssemblies . Add ( path , assembly ) ;
@@ -74,7 +65,6 @@ private AnalyzersAndFixers GetAnalyzersAndFixers(Project project)
74
65
catch { }
75
66
}
76
67
77
- // Give up.
78
68
return null ;
79
69
}
80
70
@@ -83,18 +73,51 @@ private AnalyzersAndFixers GetAnalyzersAndFixers(Project project)
83
73
internal sealed class AnalyzerLoadContext : AssemblyLoadContext
84
74
{
85
75
internal string AssemblyFolderPath { get ; }
76
+ internal AssemblyDependencyResolver DependencyResolver { get ; }
86
77
87
- public AnalyzerLoadContext ( string assemblyFolderPath )
78
+ public AnalyzerLoadContext ( string assemblyPath )
88
79
{
89
- AssemblyFolderPath = assemblyFolderPath ;
80
+ var analyzerDirectory = new DirectoryInfo ( Path . GetDirectoryName ( assemblyPath ) ) ;
81
+
82
+ // Analyzer packages will put language specific assemblies in subfolders.
83
+ if ( analyzerDirectory . Name == "cs" || analyzerDirectory . Name == "vb" )
84
+ {
85
+ // Get the root analyzer folder.
86
+ analyzerDirectory = analyzerDirectory . Parent ;
87
+ }
88
+
89
+ AssemblyFolderPath = analyzerDirectory . FullName ;
90
+ DependencyResolver = new AssemblyDependencyResolver ( assemblyPath ) ;
90
91
}
91
92
92
- protected override Assembly Load ( AssemblyName assemblyName )
93
+ protected override Assembly ? Load ( AssemblyName assemblyName )
93
94
{
94
- // Since we build against .NET Core 2.1 we do not have access to the
95
- // AssemblyDependencyResolver which resolves depenendency assembly paths
96
- // from AssemblyName by using the .deps.json.
95
+ if ( s_namesToAssemblies . TryGetValue ( assemblyName . FullName , out var assembly ) )
96
+ {
97
+ return assembly ;
98
+ }
97
99
100
+ assembly = TryLoad ( assemblyName ) ;
101
+ if ( assembly is not null )
102
+ {
103
+ s_namesToAssemblies [ assemblyName . FullName ] = assembly ;
104
+ }
105
+
106
+ return assembly ;
107
+ }
108
+
109
+ private Assembly ? TryLoad ( AssemblyName assemblyName )
110
+ {
111
+ // If the analyzer was packaged with a .deps.json file which described
112
+ // its dependencies, then the DependencyResolver should locate them for us.
113
+ var resolvedPath = DependencyResolver . ResolveAssemblyToPath ( assemblyName ) ;
114
+ if ( resolvedPath is not null )
115
+ {
116
+ return LoadFromAssemblyPath ( resolvedPath ) ;
117
+ }
118
+
119
+ // The dependency resolver failed to locate the dependency so fall back to inspecting
120
+ // the analyzer package folder.
98
121
foreach ( var searchPath in
99
122
new [ ]
100
123
{
@@ -116,8 +139,20 @@ protected override Assembly Load(AssemblyName assemblyName)
116
139
catch { }
117
140
}
118
141
119
- // Try to load the requested assembly from the default load context.
120
- return AssemblyLoadContext . Default . LoadFromAssemblyName ( assemblyName ) ;
142
+ return null ;
143
+ }
144
+
145
+ protected override IntPtr LoadUnmanagedDll ( string unmanagedDllName )
146
+ {
147
+ // If the analyzer was packaged with a .deps.json file which described
148
+ // its dependencies, then the DependencyResolver should locate them for us.
149
+ var resolvedPath = DependencyResolver . ResolveUnmanagedDllToPath ( unmanagedDllName ) ;
150
+ if ( resolvedPath is not null )
151
+ {
152
+ return LoadUnmanagedDllFromPath ( resolvedPath ) ;
153
+ }
154
+
155
+ return base . LoadUnmanagedDll ( unmanagedDllName ) ;
121
156
}
122
157
}
123
158
}
0 commit comments