Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Realize less of the syntax tree during AbstractSemanticModelReuseLanguageService.GetPreviousBodyNode #77032

Merged
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.LanguageService;
using Microsoft.CodeAnalysis.PooledObjects;

namespace Microsoft.CodeAnalysis.SemanticModelReuse;

Expand Down Expand Up @@ -106,26 +107,44 @@ protected SyntaxNode GetPreviousBodyNode(SyntaxNode previousRoot, SyntaxNode cur
}
else
{
using var pooledCurrentMembers = this.SyntaxFacts.GetMethodLevelMembers(currentRoot);
var currentMembers = pooledCurrentMembers.Object;
// Walk up the ancestor nodes of currentBodyNode, finding child indexes up to the root.
using var _ = ArrayBuilder<int>.GetInstance(out var indexPath);
GetNodeChildIndexPathToRootReversed(currentBodyNode, indexPath);

var index = currentMembers.IndexOf(currentBodyNode);
if (index < 0)
// Then use those indexes to walk back down the previous tree to find the equivalent node.
var previousNode = previousRoot;
for (var i = indexPath.Count - 1; i >= 0; i--)
{
Debug.Fail($"Unhandled member type in {nameof(GetPreviousBodyNode)}");
return null;
var childIndex = indexPath[i];
var children = previousNode.ChildNodesAndTokens();
previousNode = children[childIndex].AsNode()!;
}

using var pooledPreviousMembers = this.SyntaxFacts.GetMethodLevelMembers(previousRoot);
var previousMembers = pooledPreviousMembers.Object;
return previousNode;
}
}

private static void GetNodeChildIndexPathToRootReversed(SyntaxNode node, ArrayBuilder<int> path)
{
var current = node;
var parent = current.Parent;

if (currentMembers.Count != previousMembers.Count)
while (parent != null)
{
var childIndex = 0;
foreach (var child in parent.ChildNodesAndTokens())
{
Debug.Fail("Member count shouldn't have changed as there were no top level edits.");
return null;
if (child.AsNode() == current)
{
path.Add(childIndex);
break;
}

childIndex++;
}

return previousMembers[index];
current = parent;
parent = current.Parent;
}
}

Expand Down
Loading