提交 b8f785ca 编写于 作者: D Dustin Campbell

Ensure that calls into EnvDTE.CodeModel work even if the underlying...

Ensure that calls into EnvDTE.CodeModel work even if the underlying FileCodeModel has not been realized

When calling into an EnvDTE.CodeModel API, the caller must pass the file
name of the file to be operated on. For example:

var ns = codeModel.AddNamespace("MyFile.cs", "MyNamespace");

However, the implementation EnvDTE.CodeModel would only ever succeed to
find the FileCodeModel for "MyFile.cs" if had already been created and
cached. If the FileCodeModel wasn't in the cache, the API that was
called would throw.

Ultimately, this comes down to a set of APIs with bad names that don't
reflect that they only return cached values. This change renames those
APIs to give them proper names (e.g. TryGetCachedFileCodeModelInstance)
and adds an API that will retrieve a cached FileCodeModel or create a
new one if needed.
上级 289315ba
......@@ -58,14 +58,25 @@ internal CodeModelProjectCache GetCodeModelCache()
}
}
public IEnumerable<ComHandle<EnvDTE80.FileCodeModel2, FileCodeModel>> GetFileCodeModelInstances()
public IEnumerable<ComHandle<EnvDTE80.FileCodeModel2, FileCodeModel>> GetCachedFileCodeModelInstances()
{
return GetCodeModelCache().GetFileCodeModelInstances();
}
public ComHandle<EnvDTE80.FileCodeModel2, FileCodeModel>? GetFileCodeModelInstance(string fileName)
public bool TryGetCachedFileCodeModel(string fileName, out ComHandle<EnvDTE80.FileCodeModel2, FileCodeModel> fileCodeModelHandle)
{
return GetCodeModelCache().GetComHandleForFileCodeModel(fileName);
var handle = GetCodeModelCache().GetComHandleForFileCodeModel(fileName);
fileCodeModelHandle = handle != null
? handle.Value
: default(ComHandle<EnvDTE80.FileCodeModel2, FileCodeModel>);
return handle != null;
}
public ComHandle<EnvDTE80.FileCodeModel2, FileCodeModel> GetOrCreateFileCodeModel(string fileName)
{
return GetCodeModelCache().GetOrCreateFileCodeModel(fileName);
}
internal abstract bool CanCreateFileCodeModelThroughProject(string fileName);
......
......@@ -10,6 +10,7 @@
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.SolutionCrawler;
using Microsoft.VisualStudio.LanguageServices.Implementation.Interop;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem;
using Roslyn.Utilities;
......@@ -87,13 +88,13 @@ public void FireEvents(DocumentId documentId, CancellationToken cancellationToke
return;
}
var fileCodeModel = codeModelProvider.ProjectCodeModel.GetFileCodeModelInstance(filename);
if (fileCodeModel == null)
ComHandle<EnvDTE80.FileCodeModel2, FileCodeModel> fileCodeModelHandle;
if (!codeModelProvider.ProjectCodeModel.TryGetCachedFileCodeModel(filename, out fileCodeModelHandle))
{
return;
}
var codeModel = fileCodeModel.Value.Object;
var codeModel = fileCodeModelHandle.Object;
_notificationService.RegisterNotification(() => codeModel.FireEvents(), _listener.BeginAsyncOperation("CodeModelEvent"), cancellationToken);
}
......
......@@ -63,8 +63,8 @@ public bool FireEvents()
return needMoreTime;
}
var comHandleToThis = provider.ProjectCodeModel.GetFileCodeModelInstance(this.Workspace.GetFilePath(GetDocumentId()));
if (comHandleToThis == null)
ComHandle<EnvDTE80.FileCodeModel2, FileCodeModel> fileCodeModelHandle;
if (!provider.ProjectCodeModel.TryGetCachedFileCodeModel(this.Workspace.GetFilePath(GetDocumentId()), out fileCodeModelHandle))
{
return needMoreTime;
}
......
......@@ -18,7 +18,7 @@ public NodeKeyValidation()
public void AddProject(AbstractProject project)
{
var provider = (IProjectCodeModelProvider)project;
IEnumerable<ComHandle<EnvDTE80.FileCodeModel2, FileCodeModel>> fcms = provider.ProjectCodeModel.GetFileCodeModelInstances();
var fcms = provider.ProjectCodeModel.GetCachedFileCodeModelInstances();
foreach (var fcm in fcms)
{
......
......@@ -85,13 +85,12 @@ private Compilation GetCompilation()
var hostProject = ((VisualStudioWorkspaceImpl)Workspace).ProjectTracker.GetProject(_projectId);
var projectCodeModel = ((IProjectCodeModelProvider)hostProject).ProjectCodeModel;
return projectCodeModel.GetFileCodeModelInstance(fileName).Value;
return projectCodeModel.GetOrCreateFileCodeModel(fileName);
}
else
{
throw Exceptions.ThrowEInvalidArg();
}
}
public EnvDTE.Project Parent
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册