diff --git a/src/Workspaces/CSharp/Portable/LanguageServices/CSharpSemanticFactsService.cs b/src/Workspaces/CSharp/Portable/LanguageServices/CSharpSemanticFactsService.cs index 74293eb2c8ff6e1aa82d6a47de1b7e1f707b34a0..9296c06e0a27526cb9e30cdb722c28a2af1b25bf 100644 --- a/src/Workspaces/CSharp/Portable/LanguageServices/CSharpSemanticFactsService.cs +++ b/src/Workspaces/CSharp/Portable/LanguageServices/CSharpSemanticFactsService.cs @@ -26,7 +26,7 @@ private CSharpSemanticFactsService() { } - protected override IEnumerable GetUsedSymbols(SemanticModel semanticModel, SyntaxNode location, SyntaxNode container, CancellationToken cancellationToken) + protected override IEnumerable GetCollidableSymbols(SemanticModel semanticModel, SyntaxNode location, SyntaxNode container, CancellationToken cancellationToken) { // Get all the symbols visible to the current location. var visibleSymbols = semanticModel.LookupSymbols(location.SpanStart); @@ -36,7 +36,7 @@ protected override IEnumerable GetUsedSymbols(SemanticModel semanticMod // Walk through the enclosing block to find them, but avoid exploring local functions because // a) Visible local function symbols would be returned from LookupSymbols // (e.g. location is inside a local function or the local function method name). - // b) Local function symbols are not affected by outer variables and do not contribute to the outer scope. + // b) Symbols declared inside a local function do not cause collisions with symbols declared outside the local function, so avoid considering them. var symbolsInBlock = semanticModel.GetExistingSymbols(container, cancellationToken, descendInto: n => !n.IsKind(SyntaxKind.LocalFunctionStatement)); diff --git a/src/Workspaces/Core/Portable/LanguageServices/SemanticsFactsService/AbstractSemanticFactsService.cs b/src/Workspaces/Core/Portable/LanguageServices/SemanticsFactsService/AbstractSemanticFactsService.cs index 823bbeae7b8730d51554054615c5b633b04d1d7f..f5c40d7b753512f80cb16c8d781d664af7c850cd 100644 --- a/src/Workspaces/Core/Portable/LanguageServices/SemanticsFactsService/AbstractSemanticFactsService.cs +++ b/src/Workspaces/Core/Portable/LanguageServices/SemanticsFactsService/AbstractSemanticFactsService.cs @@ -60,13 +60,18 @@ internal abstract class AbstractSemanticFactsService var container = containerOpt ?? location.AncestorsAndSelf().FirstOrDefault( a => syntaxFacts.IsExecutableBlock(a) || syntaxFacts.IsMethodBody(a)); - var candidates = GetUsedSymbols(semanticModel, location, container, cancellationToken); + var candidates = GetCollidableSymbols(semanticModel, location, container, cancellationToken); var filteredCandidates = filter != null ? candidates.Where(filter) : candidates; return GenerateUniqueName(baseName, filteredCandidates.Select(s => s.Name).Concat(usedNames)); } - protected virtual IEnumerable GetUsedSymbols(SemanticModel semanticModel, SyntaxNode location, SyntaxNode container, CancellationToken cancellationToken) + /// + /// Retrieves all symbols that could collide with a symbol at the specified location. + /// A symbol can possibly collide with the location if it is available to that location and/or + /// could cause a compiler error if its name is re-used at that location. + /// + protected virtual IEnumerable GetCollidableSymbols(SemanticModel semanticModel, SyntaxNode location, SyntaxNode container, CancellationToken cancellationToken) => semanticModel.LookupSymbols(location.SpanStart).Concat(semanticModel.GetExistingSymbols(container, cancellationToken)); private SyntaxToken GenerateUniqueName(string baseName, IEnumerable usedNames)