|
6 | 6 | using System.Linq; |
7 | 7 | using System.Runtime.InteropServices; |
8 | 8 | using System.Threading; |
| 9 | +using System.Threading.Tasks; |
9 | 10 | using Microsoft.CodeAnalysis; |
10 | 11 | using Microsoft.CodeAnalysis.Shared.Extensions; |
11 | 12 | using Microsoft.VisualStudio.LanguageServices.CSharp.ProjectSystemShim.Interop; |
@@ -120,48 +121,50 @@ public void OnModuleRemoved(string filename) |
120 | 121 |
|
121 | 122 | public int GetValidStartupClasses(IntPtr[] classNames, ref int count) |
122 | 123 | { |
123 | | - var project = Workspace.CurrentSolution.GetRequiredProject(ProjectSystemProject.Id); |
124 | | - var compilation = project.GetRequiredCompilationAsync(CancellationToken.None).WaitAndGetResult(CancellationToken.None); |
125 | | - var entryPoints = CSharpEntryPointFinder.FindEntryPoints(compilation); |
| 124 | + var (result, newCount) = this.ThreadingContext.JoinableTaskFactory.Run(GetValidStartupClassesAsync); |
| 125 | + if (newCount.HasValue) |
| 126 | + count = newCount.Value; |
126 | 127 |
|
127 | | - // If classNames is NULL, then we need to populate the number of valid startup |
128 | | - // classes only |
129 | | - if (classNames == null) |
130 | | - { |
131 | | - count = entryPoints.Count(); |
132 | | - return VSConstants.S_OK; |
133 | | - } |
134 | | - else |
| 128 | + return result; |
| 129 | + |
| 130 | + async Task<(int result, int? newCount)> GetValidStartupClassesAsync() |
135 | 131 | { |
136 | | - // We return S_FALSE if we have more entrypoints than places in the array. |
137 | | - var entryPointNames = entryPoints.Select(e => e.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat.WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Omitted))).ToArray(); |
| 132 | + var project = Workspace.CurrentSolution.GetRequiredProject(ProjectSystemProject.Id); |
| 133 | + var compilation = await project.GetRequiredCompilationAsync(CancellationToken.None).ConfigureAwait(true); |
| 134 | + var entryPoints = CSharpEntryPointFinder.FindEntryPoints(compilation); |
138 | 135 |
|
139 | | - if (entryPointNames.Length > classNames.Length) |
| 136 | + // If classNames is NULL, then we need to populate the number of valid startup |
| 137 | + // classes only |
| 138 | + if (classNames == null) |
140 | 139 | { |
141 | | - return VSConstants.S_FALSE; |
| 140 | + return (VSConstants.S_OK, entryPoints.Count()); |
142 | 141 | } |
143 | | - |
144 | | - // The old language service stored startup class names in its string table, |
145 | | - // so the property page never freed them. To avoid leaking memory, we're |
146 | | - // going to allocate our strings on the native heap and keep the pointers to them. |
147 | | - // Subsequent calls to this function will free the old strings and allocate the |
148 | | - // new ones. The last set of marshalled strings is freed in the destructor. |
149 | | - if (_startupClasses != null) |
| 142 | + else |
150 | 143 | { |
151 | | - foreach (var @class in _startupClasses) |
| 144 | + // We return S_FALSE if we have more entrypoints than places in the array. |
| 145 | + var entryPointNames = entryPoints.Select(e => e.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat.WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Omitted))).ToArray(); |
| 146 | + |
| 147 | + if (entryPointNames.Length > classNames.Length) |
| 148 | + return (VSConstants.S_FALSE, null); |
| 149 | + |
| 150 | + // The old language service stored startup class names in its string table, |
| 151 | + // so the property page never freed them. To avoid leaking memory, we're |
| 152 | + // going to allocate our strings on the native heap and keep the pointers to them. |
| 153 | + // Subsequent calls to this function will free the old strings and allocate the |
| 154 | + // new ones. The last set of marshalled strings is freed in the destructor. |
| 155 | + if (_startupClasses != null) |
152 | 156 | { |
153 | | - Marshal.FreeHGlobal(@class); |
| 157 | + foreach (var @class in _startupClasses) |
| 158 | + Marshal.FreeHGlobal(@class); |
154 | 159 | } |
155 | | - } |
156 | 160 |
|
157 | | - _startupClasses = entryPointNames.Select(Marshal.StringToHGlobalUni).ToArray(); |
158 | | - Array.Copy(_startupClasses, classNames, _startupClasses.Length); |
| 161 | + _startupClasses = entryPointNames.Select(Marshal.StringToHGlobalUni).ToArray(); |
| 162 | + Array.Copy(_startupClasses, classNames, _startupClasses.Length); |
159 | 163 |
|
160 | | - count = entryPointNames.Length; |
161 | | - return VSConstants.S_OK; |
| 164 | + return (VSConstants.S_OK, entryPointNames.Length); |
| 165 | + } |
162 | 166 | } |
163 | 167 | } |
164 | | - |
165 | 168 | public void OnAliasesChanged(string file, string project, int previousAliasesCount, string[] previousAliases, int currentAliasesCount, string[] currentAliases) |
166 | 169 | { |
167 | 170 | using (ProjectSystemProject.CreateBatchScope()) |
|
0 commit comments