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

Merge pull request #8607 from DustinCampbell/fix-codemodel-race

Fix race in Code Model cache
......@@ -196,30 +196,16 @@ internal void UpdateCodeElementNodeKey(AbstractKeyedCodeElement keyedElement, Sy
internal void OnCodeElementCreated(SyntaxNodeKey nodeKey, EnvDTE.CodeElement element)
{
_codeElementTable.Add(nodeKey, element);
}
internal void OnBeforeCodeElementCreated(SyntaxNode node)
{
// It's conceivable that a consumer is creating a code element with the same node key as a "dead" element
// that hasn't been removed from the cache yet. For example, the element could have been "deleted" by
// simply replacing its text in the underlying buffer. To handle this situation, we test to see if the
// element is "dead" by checking whether it's underlying node is invalid (that is, it can't be found by
// its node key). If the element is "dead", we'll go ahead and remove it from the cache here to avoid a
// collision with the new element.
// If we're creating an element with the same node key as an element that's already in the table, just remove
// the old element. The old element will continue to function but the new element will replace it in the cache.
var nodeKey = CodeModelService.TryGetNodeKey(node);
EnvDTE.CodeElement codeElement;
if (!nodeKey.IsEmpty && _codeElementTable.TryGetValue(nodeKey, out codeElement))
EnvDTE.CodeElement oldElement;
if (_codeElementTable.TryGetValue(nodeKey, out oldElement))
{
var managedElement = ComAggregate.GetManagedObject<AbstractKeyedCodeElement>(codeElement);
Debug.Assert(managedElement != null, $"Could not get the underlying {nameof(AbstractKeyedCodeElement)} from {nameof(codeElement)} with {nameof(nodeKey)}: {nodeKey}");
if (managedElement?.IsValidNode() != true)
{
_codeElementTable.Remove(nodeKey);
}
_codeElementTable.Remove(nodeKey);
}
_codeElementTable.Add(nodeKey, element);
}
internal void OnCodeElementDeleted(SyntaxNodeKey nodeKey)
......
......@@ -62,8 +62,6 @@ private SyntaxNode InsertMember(SyntaxNode containerNode, SyntaxNode memberNode,
var resultNode = CodeModelService.InsertMember(
document, IsBatchOpen, insertionIndex, containerNode, memberNode, CancellationToken.None, out newDocument);
OnBeforeCodeElementCreated(resultNode);
return Tuple.Create(resultNode, newDocument);
});
}
......
......@@ -3854,6 +3854,8 @@ class C$$
Assert.False(True,
$"Failed to add variable in loop iteration {i}!
Exception: {ex.Message}
Document text:
{initialDocument.GetTextAsync(CancellationToken.None).Result}")
......
......@@ -3163,6 +3163,8 @@ End Class
Assert.False(True,
$"Failed to add variable in loop iteration {i}!
Exception: {ex.Message}
Document text:
{initialDocument.GetTextAsync(CancellationToken.None).Result}")
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册