| File: Rename\ConflictEngine\ConflictingIdentifierTracker.cs | Web Access |
| Project: src\roslyn\src\Workspaces\Core\Portable\Microsoft.CodeAnalysis.Workspaces.csproj (Microsoft.CodeAnalysis.Workspaces) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Collections.Generic; using Microsoft.CodeAnalysis.PooledObjects; namespace Microsoft.CodeAnalysis.Rename.ConflictEngine; internal sealed class ConflictingIdentifierTracker(SyntaxToken tokenBeingRenamed, IEqualityComparer<string> identifierComparer) { /// <summary> /// The core data structure of the tracker. This is a dictionary of variable name to the /// current identifier tokens that are declaring variables. This should only ever be updated /// via the AddIdentifier and RemoveIdentifier helpers. /// </summary> private readonly Dictionary<string, List<SyntaxToken>> _currentIdentifiersInScope = new(identifierComparer); private readonly HashSet<SyntaxToken> _conflictingTokensToReport = []; public IEnumerable<SyntaxToken> ConflictingTokens => _conflictingTokensToReport; public void AddIdentifier(SyntaxToken token) { if (token.IsMissing || token.ValueText == null) { return; } var name = token.ValueText; if (_currentIdentifiersInScope.TryGetValue(name, out var conflictingTokens)) { conflictingTokens.Add(token); // If at least one of the identifiers is the one we're renaming, // track it. This means that conflicts unrelated to our rename (that // were there when we started) we won't flag. if (conflictingTokens.Contains(tokenBeingRenamed)) { foreach (var conflictingToken in conflictingTokens) { if (conflictingToken != tokenBeingRenamed) { // conflictingTokensToReport is a set, so we won't get duplicates _conflictingTokensToReport.Add(conflictingToken); } } } } else { // No identifiers yet, so record the first one _currentIdentifiersInScope.Add(name, [token]); } } public void AddIdentifiers(ArrayBuilder<SyntaxToken> tokens) { foreach (var token in tokens) AddIdentifier(token); } public void AddIdentifiers(IEnumerable<SyntaxToken> tokens) { foreach (var token in tokens) AddIdentifier(token); } public void RemoveIdentifier(SyntaxToken token) { if (token.IsMissing || token.ValueText == null) { return; } var name = token.ValueText; var currentIdentifiers = _currentIdentifiersInScope[name]; currentIdentifiers.Remove(token); if (currentIdentifiers.Count == 0) { _currentIdentifiersInScope.Remove(name); } } public void RemoveIdentifiers(ArrayBuilder<SyntaxToken> tokens) { foreach (var token in tokens) RemoveIdentifier(token); } public void RemoveIdentifiers(IEnumerable<SyntaxToken> tokens) { foreach (var token in tokens) RemoveIdentifier(token); } }