diff --git a/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs b/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs index fb2f7750fed1fa629431656df1614b899a8154ef..cd8aa83f6e4fa93ccedae87866d2f3c31fd54851 100644 --- a/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs +++ b/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs @@ -1332,6 +1332,28 @@ void M() MainDescription("DateTime C.Prop { get; set; }")); } + [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] + public void LocalProperty_Minimal_PrivateSet() + { + TestInClass(@"public DateTime Prop { get; private set; } +void M() +{ + P$$rop.ToString(); +}", + MainDescription("DateTime C.Prop { get; private set; }")); + } + + [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] + public void LocalProperty_Minimal_PrivateSet1() + { + TestInClass(@"protected internal int Prop { get; private set; } +void M() +{ + P$$rop.ToString(); +}", + MainDescription("int C.Prop { get; private set; }")); + } + [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] public void LocalProperty_Qualified() { diff --git a/src/Features/CSharp/Portable/LanguageServices/CSharpSymbolDisplayService.SymbolDescriptionBuilder.cs b/src/Features/CSharp/Portable/LanguageServices/CSharpSymbolDisplayService.SymbolDescriptionBuilder.cs index 162be343cdf5a6f190f3613dd38798882705946a..bea4ec6754c52d503459ca7ed7dece971d8738fb 100644 --- a/src/Features/CSharp/Portable/LanguageServices/CSharpSymbolDisplayService.SymbolDescriptionBuilder.cs +++ b/src/Features/CSharp/Portable/LanguageServices/CSharpSymbolDisplayService.SymbolDescriptionBuilder.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Classification; @@ -27,6 +28,32 @@ protected class SymbolDescriptionBuilder : AbstractSymbolDescriptionBuilder .AddMemberOptions(SymbolDisplayMemberOptions.IncludeConstantValue) .AddParameterOptions(SymbolDisplayParameterOptions.IncludeDefaultValue); + private static readonly SymbolDisplayFormat s_propertySignatureDisplayFormat = + new SymbolDisplayFormat( + globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted, + genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters | SymbolDisplayGenericsOptions.IncludeTypeConstraints, + memberOptions: + SymbolDisplayMemberOptions.IncludeAccessibility | + SymbolDisplayMemberOptions.IncludeParameters | + SymbolDisplayMemberOptions.IncludeType | + SymbolDisplayMemberOptions.IncludeContainingType, + kindOptions: + SymbolDisplayKindOptions.IncludeMemberKeyword, + propertyStyle: + SymbolDisplayPropertyStyle.ShowReadWriteDescriptor, + parameterOptions: + SymbolDisplayParameterOptions.IncludeName | + SymbolDisplayParameterOptions.IncludeType | + SymbolDisplayParameterOptions.IncludeParamsRefOut | + SymbolDisplayParameterOptions.IncludeExtensionThis | + SymbolDisplayParameterOptions.IncludeDefaultValue | + SymbolDisplayParameterOptions.IncludeOptionalBrackets, + localOptions: SymbolDisplayLocalOptions.IncludeType, + miscellaneousOptions: + SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers | + SymbolDisplayMiscellaneousOptions.UseSpecialTypes | + SymbolDisplayMiscellaneousOptions.UseErrorTypeSymbolName); + public SymbolDescriptionBuilder( ISymbolDisplayService displayService, SemanticModel semanticModel, @@ -74,6 +101,20 @@ protected override void AddAwaitableExtensionPrefix() Space()); } + protected override void AddDescriptionForProperty(IPropertySymbol symbol) + { + if (symbol.ContainingType?.TypeKind == TypeKind.Interface) + { + base.AddDescriptionForProperty(symbol); + } + else + { + var fullParts = ToMinimalDisplayParts(symbol, s_propertySignatureDisplayFormat); + var neededParts = fullParts.SkipWhile(p => p.Symbol == null); + AddToGroup(SymbolDescriptionGroups.MainDescription, neededParts); + } + } + protected override Task> GetInitializerSourcePartsAsync( ISymbol symbol) { diff --git a/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.AbstractSymbolDescriptionBuilder.cs b/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.AbstractSymbolDescriptionBuilder.cs index b1a696bacc46a0fb9a7cb7100b5ab857041b3d72..c4b062b265b72635629a361ef95cdbc2c51c8f35 100644 --- a/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.AbstractSymbolDescriptionBuilder.cs +++ b/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.AbstractSymbolDescriptionBuilder.cs @@ -533,7 +533,7 @@ private async Task AddDescriptionForParameterAsync(IParameterSymbol symbol) ToMinimalDisplayParts(symbol, MinimallyQualifiedFormatWithConstants)); } - private void AddDescriptionForProperty(IPropertySymbol symbol) + protected virtual void AddDescriptionForProperty(IPropertySymbol symbol) { if (symbol.IsIndexer) {