提交 6a463b29 编写于 作者: C CyrusNajmabadi 提交者: GitHub

Merge pull request #19328 from CyrusNajmabadi/deferCompilationCreation

Defer creating a compilation if it is not needed.
......@@ -323,7 +323,13 @@ private int BinarySearch(string name)
// for non-fuzzy searches, and soon afterwards it will be able to perform
// fuzzy searches as well.
return Task.Run(() => LoadOrCreateSpellCheckerAsync(solution, checksum, filePath,
() => new SpellChecker(checksum, sortedNodes.Select(n => new StringSlice(concatenatedNames, n.NameSpan)))));
() => CreateSpellCheckerAsync(checksum, concatenatedNames, sortedNodes)));
}
private static Task<SpellChecker> CreateSpellCheckerAsync(Checksum checksum, string concatenatedNames, Node[] sortedNodes)
{
return Task.FromResult(new SpellChecker(
checksum, sortedNodes.Select(n => new StringSlice(concatenatedNames, n.NameSpan))));
}
private static void SortNodes(
......
......@@ -161,20 +161,20 @@ private static Metadata GetMetadataNoThrow(PortableExecutableReference reference
checksum,
filePath,
loadOnly,
create: () => CreateMetadataSymbolTreeInfo(solution, checksum, reference, cancellationToken),
createAsync: () => CreateMetadataSymbolTreeInfoAsync(solution, checksum, reference, cancellationToken),
keySuffix: "_Metadata",
getPersistedChecksum: info => info.Checksum,
readObject: reader => ReadSymbolTreeInfo(reader, (names, nodes) => GetSpellCheckerTask(solution, checksum, filePath, names, nodes)),
cancellationToken: cancellationToken);
}
private static SymbolTreeInfo CreateMetadataSymbolTreeInfo(
private static Task<SymbolTreeInfo> CreateMetadataSymbolTreeInfoAsync(
Solution solution, Checksum checksum,
PortableExecutableReference reference,
CancellationToken cancellationToken)
{
var creator = new MetadataInfoCreator(solution, checksum, reference, cancellationToken);
return creator.Create();
return Task.FromResult(creator.Create());
}
private struct MetadataInfoCreator : IDisposable
......
......@@ -24,22 +24,17 @@ internal partial class SymbolTreeInfo : IObjectWritable
/// info can't be loaded, it will be created (and persisted if possible).
/// </summary>
private static Task<SymbolTreeInfo> LoadOrCreateSourceSymbolTreeInfoAsync(
Solution solution,
IAssemblySymbol assembly,
Checksum checksum,
string filePath,
bool loadOnly,
CancellationToken cancellationToken)
Project project, Checksum checksum, bool loadOnly, CancellationToken cancellationToken)
{
return LoadOrCreateAsync(
solution,
project.Solution,
checksum,
filePath,
project.FilePath,
loadOnly,
create: () => CreateSourceSymbolTreeInfo(solution, checksum, assembly, filePath, cancellationToken),
createAsync: () => CreateSourceSymbolTreeInfoAsync(project, checksum, cancellationToken),
keySuffix: "_Source",
getPersistedChecksum: info => info.Checksum,
readObject: reader => ReadSymbolTreeInfo(reader, (names, nodes) => GetSpellCheckerTask(solution, checksum, filePath, names, nodes)),
readObject: reader => ReadSymbolTreeInfo(reader, (names, nodes) => GetSpellCheckerTask(project.Solution, checksum, project.FilePath, names, nodes)),
cancellationToken: cancellationToken);
}
......@@ -51,14 +46,14 @@ internal partial class SymbolTreeInfo : IObjectWritable
Solution solution,
Checksum checksum,
string filePath,
Func<SpellChecker> create)
Func<Task<SpellChecker>> createAsync)
{
return LoadOrCreateAsync(
solution,
checksum,
filePath,
loadOnly: false,
create: create,
createAsync: createAsync,
keySuffix: "_SpellChecker",
getPersistedChecksum: s => s.Checksum,
readObject: SpellChecker.ReadFrom,
......@@ -74,7 +69,7 @@ internal partial class SymbolTreeInfo : IObjectWritable
Checksum checksum,
string filePath,
bool loadOnly,
Func<T> create,
Func<Task<T>> createAsync,
string keySuffix,
Func<T, Checksum> getPersistedChecksum,
Func<ObjectReader, T> readObject,
......@@ -82,7 +77,7 @@ internal partial class SymbolTreeInfo : IObjectWritable
{
if (checksum == null)
{
return loadOnly ? null : create();
return loadOnly ? null : await createAsync().ConfigureAwait(false);
}
// Ok, we can use persistence. First try to load from the persistence service.
......@@ -120,7 +115,7 @@ internal partial class SymbolTreeInfo : IObjectWritable
}
// Now, try to create a new instance and write it to the persistence service.
result = create();
result = await createAsync().ConfigureAwait(false);
if (result != null)
{
using (var stream = SerializableBytes.CreateWritableStream())
......
......@@ -28,14 +28,11 @@ private static void FreeSymbolMap(MultiDictionary<string, ISymbol> symbolMap)
s_symbolMapPool.Free(symbolMap);
}
public static async Task<SymbolTreeInfo> GetInfoForSourceAssemblyAsync(
public static Task<SymbolTreeInfo> GetInfoForSourceAssemblyAsync(
Project project, Checksum checksum, CancellationToken cancellationToken)
{
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
return await LoadOrCreateSourceSymbolTreeInfoAsync(
project.Solution, compilation.Assembly, checksum, project.FilePath,
loadOnly: false, cancellationToken: cancellationToken).ConfigureAwait(false);
return LoadOrCreateSourceSymbolTreeInfoAsync(
project, checksum, loadOnly: false, cancellationToken: cancellationToken);
}
public static async Task<Checksum> GetSourceSymbolsChecksumAsync(Project project, CancellationToken cancellationToken)
......@@ -49,7 +46,9 @@ public static async Task<Checksum> GetSourceSymbolsChecksumAsync(Project project
var serializer = new Serializer(project.Solution.Workspace);
var projectStateChecksums = await project.State.GetStateChecksumsAsync(cancellationToken).ConfigureAwait(false);
var textChecksumsTasks = project.Documents.Select(async d =>
// Order the documents by FilePath. Default ordering in the RemoteWorkspace is
// to be ordered by Guid (which is not consistent across VS sessions).
var textChecksumsTasks = project.Documents.OrderBy(d => d.FilePath).Select(async d =>
{
var documentStateChecksum = await d.State.GetStateChecksumsAsync(cancellationToken).ConfigureAwait(false);
return documentStateChecksum.Text;
......@@ -75,10 +74,11 @@ public static async Task<Checksum> GetSourceSymbolsChecksumAsync(Project project
}
}
internal static SymbolTreeInfo CreateSourceSymbolTreeInfo(
Solution solution, Checksum checksum, IAssemblySymbol assembly,
string filePath, CancellationToken cancellationToken)
internal static async Task<SymbolTreeInfo> CreateSourceSymbolTreeInfoAsync(
Project project, Checksum checksum, CancellationToken cancellationToken)
{
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
var assembly = compilation.Assembly;
if (assembly == null)
{
return null;
......@@ -90,7 +90,7 @@ public static async Task<Checksum> GetSourceSymbolsChecksumAsync(Project project
GenerateSourceNodes(assembly.GlobalNamespace, unsortedNodes, s_getMembersNoPrivate);
return CreateSymbolTreeInfo(
solution, checksum, filePath, unsortedNodes.ToImmutableAndFree(),
project.Solution, checksum, project.FilePath, unsortedNodes.ToImmutableAndFree(),
inheritanceMap: new OrderPreservingMultiDictionary<string, string>());
}
......
......@@ -537,13 +537,11 @@ public async Task FindSourceDeclarationsAsync_Solution_Func_Test_Cancellation()
public async Task TestSymbolTreeInfoSerialization()
{
var solution = GetSolution(WorkspaceKind.SingleClass);
var compilation = await solution.Projects.First().GetCompilationAsync();
var assembly = compilation.GetSpecialType(SpecialType.System_Byte).ContainingAssembly;
////var assembly = compilation.Assembly;
var project = solution.Projects.First();
// create symbol tree info from assembly
var info = SymbolTreeInfo.CreateSourceSymbolTreeInfo(
solution, Checksum.Null, assembly, "", cancellationToken: CancellationToken.None);
var info = await SymbolTreeInfo.CreateSourceSymbolTreeInfoAsync(
project, Checksum.Null, cancellationToken: CancellationToken.None);
using (var writerStream = new MemoryStream())
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册