diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs index e2f3e8e23ee20..a9a66c2c4212b 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs @@ -4714,6 +4714,20 @@ static void M() } """, "x"); + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/82750")] + public Task TypeWithSameNameAsInstancePropertyInStaticMethod() + => VerifyItemExistsAsync(""" + public sealed record SourceContainer(Source Source) + { + public static SourceContainer From(string source) + { + Sour$$ + } + } + + public sealed record Source(string Content); + """, "Source", expectedDescriptionOrNull: "record Source"); + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543601")] public Task NoInstanceFieldsInStaticFieldInitializer() => VerifyItemIsAbsentAsync(""" diff --git a/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner.cs b/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner.cs index f42cf60494b2c..b6e77d71499e0 100644 --- a/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner.cs +++ b/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner.cs @@ -399,9 +399,35 @@ private ImmutableArray GetSymbolsForExpressionOrStatementContext() } else { - symbols = contextNode.IsInStaticContext() - ? semanticModel.LookupStaticMembers(_context.LeftToken.SpanStart) - : semanticModel.LookupSymbols(_context.LeftToken.SpanStart); + if (contextNode.IsInStaticContext()) + { + var position = _context.LeftToken.SpanStart; + symbols = semanticModel.LookupStaticMembers(position); + + // Primary constructor parameters are returned by LookupStaticMembers, but are unusable in a static + // context. They can hide a namespace or type with the same name, so recover those candidates. + if (!_context.IsInstanceContext) + { + using var _ = ArrayBuilder.GetInstance(symbols.Length, out var staticSymbols); + foreach (var symbol in symbols) + { + if (symbol is IParameterSymbol parameter && parameter.IsPrimaryConstructor(_cancellationToken)) + { + staticSymbols.AddRange(semanticModel.LookupNamespacesAndTypes(position, name: parameter.Name)); + } + else + { + staticSymbols.Add(symbol); + } + } + + symbols = staticSymbols.ToImmutableAndClear(); + } + } + else + { + symbols = semanticModel.LookupSymbols(_context.LeftToken.SpanStart); + } symbols = FilterOutUncapturableParameters(symbols, contextNode); }