diff --git a/src/VisualStudio/CSharp/Impl/ObjectBrowser/DescriptionBuilder.cs b/src/VisualStudio/CSharp/Impl/ObjectBrowser/DescriptionBuilder.cs index edd849ed6bc61..8b1ab58d4b13b 100644 --- a/src/VisualStudio/CSharp/Impl/ObjectBrowser/DescriptionBuilder.cs +++ b/src/VisualStudio/CSharp/Impl/ObjectBrowser/DescriptionBuilder.cs @@ -6,538 +6,531 @@ using System.Collections.Immutable; using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.VisualStudio.LanguageServices.Implementation.Library.ObjectBrowser; using Microsoft.VisualStudio.Shell.Interop; -namespace Microsoft.VisualStudio.LanguageServices.CSharp.ObjectBrowser +namespace Microsoft.VisualStudio.LanguageServices.CSharp.ObjectBrowser; + +internal sealed class DescriptionBuilder( + IVsObjectBrowserDescription3 description, + ObjectBrowserLibraryManager libraryManager, + ObjectListItem listItem, + Project project) : AbstractDescriptionBuilder(description, libraryManager, listItem, project) { - internal class DescriptionBuilder : AbstractDescriptionBuilder + protected override void BuildNamespaceDeclaration(INamespaceSymbol namespaceSymbol, _VSOBJDESCOPTIONS options) { - public DescriptionBuilder( - IVsObjectBrowserDescription3 description, - ObjectBrowserLibraryManager libraryManager, - ObjectListItem listItem, - Project project) - : base(description, libraryManager, listItem, project) - { - } + AddText("namespace "); + AddName(namespaceSymbol.ToDisplayString()); + } - protected override void BuildNamespaceDeclaration(INamespaceSymbol namespaceSymbol, _VSOBJDESCOPTIONS options) - { - AddText("namespace "); - AddName(namespaceSymbol.ToDisplayString()); - } + protected override async Task BuildDelegateDeclarationAsync( + INamedTypeSymbol typeSymbol, _VSOBJDESCOPTIONS options, CancellationToken cancellationToken) + { + Debug.Assert(typeSymbol.TypeKind == TypeKind.Delegate); - protected override void BuildDelegateDeclaration(INamedTypeSymbol typeSymbol, _VSOBJDESCOPTIONS options) - { - Debug.Assert(typeSymbol.TypeKind == TypeKind.Delegate); + BuildTypeModifiers(typeSymbol); + AddText("delegate "); - BuildTypeModifiers(typeSymbol); - AddText("delegate "); + var delegateInvokeMethod = typeSymbol.DelegateInvokeMethod; - var delegateInvokeMethod = typeSymbol.DelegateInvokeMethod; + await AddTypeLinkAsync(delegateInvokeMethod.ReturnType, LinkFlags.None, cancellationToken).ConfigureAwait(true); + AddText(" "); - AddTypeLink(delegateInvokeMethod.ReturnType, LinkFlags.None); - AddText(" "); + var typeQualificationStyle = (options & _VSOBJDESCOPTIONS.ODO_USEFULLNAME) != 0 + ? SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces + : SymbolDisplayTypeQualificationStyle.NameOnly; - var typeQualificationStyle = (options & _VSOBJDESCOPTIONS.ODO_USEFULLNAME) != 0 - ? SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces - : SymbolDisplayTypeQualificationStyle.NameOnly; + var typeNameFormat = new SymbolDisplayFormat( + typeQualificationStyle: typeQualificationStyle, + genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters | SymbolDisplayGenericsOptions.IncludeVariance); - var typeNameFormat = new SymbolDisplayFormat( - typeQualificationStyle: typeQualificationStyle, - genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters | SymbolDisplayGenericsOptions.IncludeVariance); + AddName(typeSymbol.ToDisplayString(typeNameFormat)); - AddName(typeSymbol.ToDisplayString(typeNameFormat)); + AddText("("); + await BuildParameterListAsync(delegateInvokeMethod.Parameters, cancellationToken).ConfigureAwait(true); + AddText(")"); - AddText("("); - BuildParameterList(delegateInvokeMethod.Parameters); - AddText(")"); + if (typeSymbol.IsGenericType) + await BuildGenericConstraintsAsync(typeSymbol, cancellationToken).ConfigureAwait(true); + } - if (typeSymbol.IsGenericType) - { - BuildGenericConstraints(typeSymbol); - } - } + protected override async Task BuildTypeDeclarationAsync( + INamedTypeSymbol typeSymbol, _VSOBJDESCOPTIONS options, CancellationToken cancellationToken) + { + BuildTypeModifiers(typeSymbol); - protected override void BuildTypeDeclaration(INamedTypeSymbol typeSymbol, _VSOBJDESCOPTIONS options) + switch (typeSymbol.TypeKind) { - BuildTypeModifiers(typeSymbol); + case TypeKind.Enum: + AddText("enum "); + break; - switch (typeSymbol.TypeKind) - { - case TypeKind.Enum: - AddText("enum "); - break; - - case TypeKind.Struct: - AddText("struct "); - break; + case TypeKind.Struct: + AddText("struct "); + break; - case TypeKind.Interface: - AddText("interface "); - break; + case TypeKind.Interface: + AddText("interface "); + break; - case TypeKind.Class: - AddText("class "); - break; + case TypeKind.Class: + AddText("class "); + break; - default: - Debug.Fail("Invalid type kind encountered: " + typeSymbol.TypeKind.ToString()); - break; - } + default: + Debug.Fail("Invalid type kind encountered: " + typeSymbol.TypeKind.ToString()); + break; + } - var typeNameFormat = new SymbolDisplayFormat( - genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters | SymbolDisplayGenericsOptions.IncludeVariance); + var typeNameFormat = new SymbolDisplayFormat( + genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters | SymbolDisplayGenericsOptions.IncludeVariance); - AddName(typeSymbol.ToDisplayString(typeNameFormat)); + AddName(typeSymbol.ToDisplayString(typeNameFormat)); - if (typeSymbol.TypeKind == TypeKind.Enum) + if (typeSymbol.TypeKind == TypeKind.Enum) + { + var underlyingType = typeSymbol.EnumUnderlyingType; + if (underlyingType != null) { - var underlyingType = typeSymbol.EnumUnderlyingType; - if (underlyingType != null) + if (underlyingType.SpecialType != SpecialType.System_Int32) { - if (underlyingType.SpecialType != SpecialType.System_Int32) - { - AddText(" : "); - AddTypeLink(underlyingType, LinkFlags.None); - } + AddText(" : "); + await AddTypeLinkAsync(underlyingType, LinkFlags.None, cancellationToken).ConfigureAwait(true); } } - else - { - var baseType = typeSymbol.BaseType; - if (baseType != null) + } + else + { + var baseType = typeSymbol.BaseType; + if (baseType != null) + { + if (baseType.SpecialType is not SpecialType.System_Object and + not SpecialType.System_Delegate and + not SpecialType.System_MulticastDelegate and + not SpecialType.System_Enum and + not SpecialType.System_ValueType) { - if (baseType.SpecialType is not SpecialType.System_Object and - not SpecialType.System_Delegate and - not SpecialType.System_MulticastDelegate and - not SpecialType.System_Enum and - not SpecialType.System_ValueType) - { - AddText(" : "); - AddTypeLink(baseType, LinkFlags.None); - } + AddText(" : "); + await AddTypeLinkAsync(baseType, LinkFlags.None, cancellationToken).ConfigureAwait(true); } } + } - if (typeSymbol.IsGenericType) - { - BuildGenericConstraints(typeSymbol); - } + if (typeSymbol.IsGenericType) + await BuildGenericConstraintsAsync(typeSymbol, cancellationToken).ConfigureAwait(true); + } + + private void BuildAccessibility(ISymbol symbol) + { + switch (symbol.DeclaredAccessibility) + { + case Accessibility.Public: + AddText("public "); + break; + + case Accessibility.Private: + AddText("private "); + break; + + case Accessibility.Protected: + AddText("protected "); + break; + + case Accessibility.Internal: + AddText("internal "); + break; + + case Accessibility.ProtectedOrInternal: + AddText("protected internal "); + break; + + case Accessibility.ProtectedAndInternal: + AddText("private protected "); + break; + + default: + AddText("internal "); + break; } + } + + private void BuildTypeModifiers(INamedTypeSymbol typeSymbol) + { + BuildAccessibility(typeSymbol); - private void BuildAccessibility(ISymbol symbol) + if (typeSymbol.IsStatic) { - switch (symbol.DeclaredAccessibility) - { - case Accessibility.Public: - AddText("public "); - break; + AddText("static "); + } - case Accessibility.Private: - AddText("private "); - break; + if (typeSymbol.IsAbstract && + typeSymbol.TypeKind != TypeKind.Interface) + { + AddText("abstract "); + } - case Accessibility.Protected: - AddText("protected "); - break; + if (typeSymbol.IsSealed && + typeSymbol.TypeKind != TypeKind.Struct && + typeSymbol.TypeKind != TypeKind.Enum && + typeSymbol.TypeKind != TypeKind.Delegate) + { + AddText("sealed "); + } + } - case Accessibility.Internal: - AddText("internal "); - break; + protected override async Task BuildMethodDeclarationAsync( + IMethodSymbol methodSymbol, _VSOBJDESCOPTIONS options, CancellationToken cancellationToken) + { + BuildMemberModifiers(methodSymbol); - case Accessibility.ProtectedOrInternal: - AddText("protected internal "); - break; + if (methodSymbol.MethodKind is not MethodKind.Constructor and + not MethodKind.Destructor and + not MethodKind.StaticConstructor and + not MethodKind.Conversion) + { + await AddTypeLinkAsync(methodSymbol.ReturnType, LinkFlags.None, cancellationToken).ConfigureAwait(true); + AddText(" "); + } - case Accessibility.ProtectedAndInternal: - AddText("private protected "); + if (methodSymbol.MethodKind == MethodKind.Conversion) + { + switch (methodSymbol.Name) + { + case WellKnownMemberNames.ImplicitConversionName: + AddName("implicit operator "); break; - default: - AddText("internal "); + case WellKnownMemberNames.ExplicitConversionName: + AddName("explicit operator "); break; } + + await AddTypeLinkAsync(methodSymbol.ReturnType, LinkFlags.None, cancellationToken).ConfigureAwait(true); } + else + { + var methodNameFormat = new SymbolDisplayFormat( + genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters | SymbolDisplayGenericsOptions.IncludeVariance); - private void BuildTypeModifiers(INamedTypeSymbol typeSymbol) + AddName(methodSymbol.ToDisplayString(methodNameFormat)); + } + + AddText("("); + + if (methodSymbol.IsExtensionMethod) { - BuildAccessibility(typeSymbol); + AddText("this "); + } - if (typeSymbol.IsStatic) - { - AddText("static "); - } + await BuildParameterListAsync(methodSymbol.Parameters, cancellationToken).ConfigureAwait(true); + AddText(")"); - if (typeSymbol.IsAbstract && - typeSymbol.TypeKind != TypeKind.Interface) - { - AddText("abstract "); - } + if (methodSymbol.IsGenericMethod) + await BuildGenericConstraintsAsync(methodSymbol, cancellationToken).ConfigureAwait(true); + } - if (typeSymbol.IsSealed && - typeSymbol.TypeKind != TypeKind.Struct && - typeSymbol.TypeKind != TypeKind.Enum && - typeSymbol.TypeKind != TypeKind.Delegate) - { - AddText("sealed "); - } + private void BuildMemberModifiers(ISymbol memberSymbol) + { + if (memberSymbol.ContainingType != null && memberSymbol.ContainingType.TypeKind == TypeKind.Interface) + { + return; } - protected override void BuildMethodDeclaration(IMethodSymbol methodSymbol, _VSOBJDESCOPTIONS options) + var methodSymbol = memberSymbol as IMethodSymbol; + var fieldSymbol = memberSymbol as IFieldSymbol; + + if (methodSymbol != null && + methodSymbol.MethodKind == MethodKind.Destructor) { - BuildMemberModifiers(methodSymbol); + return; + } - if (methodSymbol.MethodKind is not MethodKind.Constructor and - not MethodKind.Destructor and - not MethodKind.StaticConstructor and - not MethodKind.Conversion) - { - AddTypeLink(methodSymbol.ReturnType, LinkFlags.None); - AddText(" "); - } + if (fieldSymbol != null && + fieldSymbol.ContainingType.TypeKind == TypeKind.Enum) + { + return; + } - if (methodSymbol.MethodKind == MethodKind.Conversion) - { - switch (methodSymbol.Name) - { - case WellKnownMemberNames.ImplicitConversionName: - AddName("implicit operator "); - break; + // TODO: 'new' modifier isn't exposed on symbols. Do we need it? - case WellKnownMemberNames.ExplicitConversionName: - AddName("explicit operator "); - break; - } + // Note: we don't display the access modifier for static constructors + if (methodSymbol == null || + methodSymbol.MethodKind != MethodKind.StaticConstructor) + { + BuildAccessibility(memberSymbol); + } - AddTypeLink(methodSymbol.ReturnType, LinkFlags.None); - } - else - { - var methodNameFormat = new SymbolDisplayFormat( - genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters | SymbolDisplayGenericsOptions.IncludeVariance); + if (memberSymbol.RequiresUnsafeModifier()) + { + AddText("unsafe "); + } - AddName(methodSymbol.ToDisplayString(methodNameFormat)); - } + // Note: we don't display 'static' for constant fields + if (memberSymbol.IsStatic && + (fieldSymbol == null || !fieldSymbol.IsConst)) + { + AddText("static "); + } - AddText("("); + if (memberSymbol.IsExtern) + { + AddText("extern "); + } - if (methodSymbol.IsExtensionMethod) - { - AddText("this "); - } + if (fieldSymbol != null && fieldSymbol.IsReadOnly) + { + AddText("readonly "); + } - BuildParameterList(methodSymbol.Parameters); - AddText(")"); + if (fieldSymbol != null && fieldSymbol.IsConst) + { + AddText("const "); + } - if (methodSymbol.IsGenericMethod) - { - BuildGenericConstraints(methodSymbol); - } + if (fieldSymbol != null && fieldSymbol.IsVolatile) + { + AddText("volatile "); } - private void BuildMemberModifiers(ISymbol memberSymbol) + if (memberSymbol.IsAbstract) + { + AddText("abstract "); + } + else if (memberSymbol.IsOverride) { - if (memberSymbol.ContainingType != null && memberSymbol.ContainingType.TypeKind == TypeKind.Interface) + if (memberSymbol.IsSealed) { - return; + AddText("sealed "); } - var methodSymbol = memberSymbol as IMethodSymbol; - var fieldSymbol = memberSymbol as IFieldSymbol; + AddText("override "); + } + else if (memberSymbol.IsVirtual) + { + AddText("virtual "); + } + } - if (methodSymbol != null && - methodSymbol.MethodKind == MethodKind.Destructor) - { - return; - } + private async Task BuildGenericConstraintsAsync(INamedTypeSymbol typeSymbol, CancellationToken cancellationToken) + { + foreach (var typeParameterSymbol in typeSymbol.TypeParameters) + await BuildConstraintsAsync(typeParameterSymbol, cancellationToken).ConfigureAwait(true); + } - if (fieldSymbol != null && - fieldSymbol.ContainingType.TypeKind == TypeKind.Enum) - { - return; - } + private async Task BuildGenericConstraintsAsync(IMethodSymbol methodSymbol, CancellationToken cancellationToken) + { + foreach (var typeParameterSymbol in methodSymbol.TypeParameters) + await BuildConstraintsAsync(typeParameterSymbol, cancellationToken).ConfigureAwait(true); + } - // TODO: 'new' modifier isn't exposed on symbols. Do we need it? + private async Task BuildConstraintsAsync(ITypeParameterSymbol typeParameterSymbol, CancellationToken cancellationToken) + { + if (typeParameterSymbol.ConstraintTypes.Length == 0 && + !typeParameterSymbol.HasConstructorConstraint && + !typeParameterSymbol.HasReferenceTypeConstraint && + !typeParameterSymbol.HasValueTypeConstraint && + !typeParameterSymbol.AllowsRefLikeType) + { + return; + } - // Note: we don't display the access modifier for static constructors - if (methodSymbol == null || - methodSymbol.MethodKind != MethodKind.StaticConstructor) - { - BuildAccessibility(memberSymbol); - } + AddLineBreak(); + AddText("\t"); + AddText("where "); + AddName(typeParameterSymbol.Name); + AddText(" : "); - if (memberSymbol.RequiresUnsafeModifier()) - { - AddText("unsafe "); - } + var isFirst = true; - // Note: we don't display 'static' for constant fields - if (memberSymbol.IsStatic && - (fieldSymbol == null || !fieldSymbol.IsConst)) + if (typeParameterSymbol.HasReferenceTypeConstraint) + { + if (!isFirst) { - AddText("static "); + AddComma(); } - if (memberSymbol.IsExtern) - { - AddText("extern "); - } + AddText("class"); + isFirst = false; + } - if (fieldSymbol != null && fieldSymbol.IsReadOnly) + if (typeParameterSymbol.HasValueTypeConstraint) + { + if (!isFirst) { - AddText("readonly "); + AddComma(); } - if (fieldSymbol != null && fieldSymbol.IsConst) - { - AddText("const "); - } + AddText("struct"); + isFirst = false; + } - if (fieldSymbol != null && fieldSymbol.IsVolatile) + foreach (var constraintType in typeParameterSymbol.ConstraintTypes) + { + if (!isFirst) { - AddText("volatile "); + AddComma(); } - if (memberSymbol.IsAbstract) - { - AddText("abstract "); - } - else if (memberSymbol.IsOverride) - { - if (memberSymbol.IsSealed) - { - AddText("sealed "); - } + await AddTypeLinkAsync(constraintType, LinkFlags.None, cancellationToken).ConfigureAwait(true); + isFirst = false; + } - AddText("override "); - } - else if (memberSymbol.IsVirtual) + if (typeParameterSymbol.HasConstructorConstraint) + { + if (!isFirst) { - AddText("virtual "); + AddComma(); } + + AddText("new()"); + isFirst = false; } - private void BuildGenericConstraints(INamedTypeSymbol typeSymbol) + if (typeParameterSymbol.AllowsRefLikeType) { - foreach (var typeParameterSymbol in typeSymbol.TypeParameters) + if (!isFirst) { - BuildConstraints(typeParameterSymbol); + AddComma(); } + + AddText("allows ref struct"); } + } - private void BuildGenericConstraints(IMethodSymbol methodSymbol) + private async Task BuildParameterListAsync( + ImmutableArray parameters, CancellationToken cancellationToken) + { + var count = parameters.Length; + if (count == 0) { - foreach (var typeParameterSymbol in methodSymbol.TypeParameters) - { - BuildConstraints(typeParameterSymbol); - } + return; } - private void BuildConstraints(ITypeParameterSymbol typeParameterSymbol) + for (var i = 0; i < count; i++) { - if (typeParameterSymbol.ConstraintTypes.Length == 0 && - !typeParameterSymbol.HasConstructorConstraint && - !typeParameterSymbol.HasReferenceTypeConstraint && - !typeParameterSymbol.HasValueTypeConstraint && - !typeParameterSymbol.AllowsRefLikeType) + if (i > 0) { - return; + AddComma(); } - AddLineBreak(); - AddText("\t"); - AddText("where "); - AddName(typeParameterSymbol.Name); - AddText(" : "); - - var isFirst = true; + var current = parameters[i]; - if (typeParameterSymbol.HasReferenceTypeConstraint) + if (current.IsOptional) { - if (!isFirst) - { - AddComma(); - } - - AddText("class"); - isFirst = false; + AddText("["); } - if (typeParameterSymbol.HasValueTypeConstraint) + if (current.RefKind == RefKind.Ref) { - if (!isFirst) - { - AddComma(); - } - - AddText("struct"); - isFirst = false; + AddText("ref "); } - - foreach (var constraintType in typeParameterSymbol.ConstraintTypes) + else if (current.RefKind == RefKind.Out) { - if (!isFirst) - { - AddComma(); - } - - AddTypeLink(constraintType, LinkFlags.None); - isFirst = false; + AddText("out "); } - if (typeParameterSymbol.HasConstructorConstraint) + if (current.IsParams) { - if (!isFirst) - { - AddComma(); - } - - AddText("new()"); - isFirst = false; + AddText("params "); } - if (typeParameterSymbol.AllowsRefLikeType) + await AddTypeLinkAsync(current.Type, LinkFlags.None, cancellationToken).ConfigureAwait(true); + AddText(" "); + AddParam(current.Name); + + if (current.HasExplicitDefaultValue) { - if (!isFirst) + AddText(" = "); + if (current.ExplicitDefaultValue == null) { - AddComma(); + AddText("null"); + } + else + { + AddText(current.ExplicitDefaultValue.ToString()); } - - AddText("allows ref struct"); } - } - private void BuildParameterList(ImmutableArray parameters) - { - var count = parameters.Length; - if (count == 0) + if (current.IsOptional) { - return; + AddText("]"); } + } + } - for (var i = 0; i < count; i++) - { - if (i > 0) - { - AddComma(); - } - - var current = parameters[i]; - - if (current.IsOptional) - { - AddText("["); - } - - if (current.RefKind == RefKind.Ref) - { - AddText("ref "); - } - else if (current.RefKind == RefKind.Out) - { - AddText("out "); - } + protected override async Task BuildFieldDeclarationAsync( + IFieldSymbol fieldSymbol, _VSOBJDESCOPTIONS options, CancellationToken cancellationToken) + { + BuildMemberModifiers(fieldSymbol); - if (current.IsParams) - { - AddText("params "); - } + if (fieldSymbol.ContainingType.TypeKind != TypeKind.Enum) + { + await AddTypeLinkAsync(fieldSymbol.Type, LinkFlags.None, cancellationToken).ConfigureAwait(true); + AddText(" "); + } - AddTypeLink(current.Type, LinkFlags.None); - AddText(" "); - AddParam(current.Name); + AddName(fieldSymbol.Name); + } - if (current.HasExplicitDefaultValue) - { - AddText(" = "); - if (current.ExplicitDefaultValue == null) - { - AddText("null"); - } - else - { - AddText(current.ExplicitDefaultValue.ToString()); - } - } + protected override async Task BuildPropertyDeclarationAsync( + IPropertySymbol propertySymbol, _VSOBJDESCOPTIONS options, CancellationToken cancellationToken) + { + BuildMemberModifiers(propertySymbol); - if (current.IsOptional) - { - AddText("]"); - } - } - } + await AddTypeLinkAsync(propertySymbol.Type, LinkFlags.None, cancellationToken).ConfigureAwait(true); + AddText(" "); - protected override void BuildFieldDeclaration(IFieldSymbol fieldSymbol, _VSOBJDESCOPTIONS options) + if (propertySymbol.IsIndexer) { - BuildMemberModifiers(fieldSymbol); - - if (fieldSymbol.ContainingType.TypeKind != TypeKind.Enum) - { - AddTypeLink(fieldSymbol.Type, LinkFlags.None); - AddText(" "); - } - - AddName(fieldSymbol.Name); + AddName("this"); + AddText("["); + await BuildParameterListAsync(propertySymbol.Parameters, cancellationToken).ConfigureAwait(true); + AddText("]"); } - - protected override void BuildPropertyDeclaration(IPropertySymbol propertySymbol, _VSOBJDESCOPTIONS options) + else { - BuildMemberModifiers(propertySymbol); + AddName(propertySymbol.Name); + } - AddTypeLink(propertySymbol.Type, LinkFlags.None); - AddText(" "); + AddText(" { "); - if (propertySymbol.IsIndexer) - { - AddName("this"); - AddText("["); - BuildParameterList(propertySymbol.Parameters); - AddText("]"); - } - else + if (propertySymbol.GetMethod != null) + { + if (propertySymbol.GetMethod.DeclaredAccessibility != propertySymbol.DeclaredAccessibility) { - AddName(propertySymbol.Name); + BuildAccessibility(propertySymbol.GetMethod); } - AddText(" { "); - - if (propertySymbol.GetMethod != null) - { - if (propertySymbol.GetMethod.DeclaredAccessibility != propertySymbol.DeclaredAccessibility) - { - BuildAccessibility(propertySymbol.GetMethod); - } - - AddText("get; "); - } + AddText("get; "); + } - if (propertySymbol.SetMethod != null) + if (propertySymbol.SetMethod != null) + { + if (propertySymbol.SetMethod.DeclaredAccessibility != propertySymbol.DeclaredAccessibility) { - if (propertySymbol.SetMethod.DeclaredAccessibility != propertySymbol.DeclaredAccessibility) - { - BuildAccessibility(propertySymbol.SetMethod); - } - - AddText("set; "); + BuildAccessibility(propertySymbol.SetMethod); } - AddText("}"); + AddText("set; "); } - protected override void BuildEventDeclaration(IEventSymbol eventSymbol, _VSOBJDESCOPTIONS options) - { - BuildMemberModifiers(eventSymbol); + AddText("}"); + } - AddText("event "); + protected override async Task BuildEventDeclarationAsync( + IEventSymbol eventSymbol, _VSOBJDESCOPTIONS options, CancellationToken cancellationToken) + { + BuildMemberModifiers(eventSymbol); - AddTypeLink(eventSymbol.Type, LinkFlags.None); - AddText(" "); + AddText("event "); - AddName(eventSymbol.Name); - } + await AddTypeLinkAsync(eventSymbol.Type, LinkFlags.None, cancellationToken).ConfigureAwait(true); + AddText(" "); + + AddName(eventSymbol.Name); } } diff --git a/src/VisualStudio/Core/Def/Library/AbstractLibraryManager_IVsSimpleLibrary2.cs b/src/VisualStudio/Core/Def/Library/AbstractLibraryManager_IVsSimpleLibrary2.cs index e51594f7c63a2..273af5f942103 100644 --- a/src/VisualStudio/Core/Def/Library/AbstractLibraryManager_IVsSimpleLibrary2.cs +++ b/src/VisualStudio/Core/Def/Library/AbstractLibraryManager_IVsSimpleLibrary2.cs @@ -5,6 +5,8 @@ #nullable disable using System; +using System.Threading; +using System.Threading.Tasks; using Microsoft.VisualStudio.OLE.Interop; using Microsoft.VisualStudio.Shell.Interop; @@ -14,7 +16,7 @@ internal partial class AbstractLibraryManager : IVsSimpleLibrary2 { public abstract uint GetLibraryFlags(); protected abstract uint GetSupportedCategoryFields(uint category); - protected abstract IVsSimpleObjectList2 GetList(uint listType, uint flags, VSOBSEARCHCRITERIA2[] pobSrch); + protected abstract Task GetListAsync(uint listType, uint flags, VSOBSEARCHCRITERIA2[] pobSrch, CancellationToken cancellationToken); protected abstract uint GetUpdateCounter(); protected virtual int CreateNavInfo(SYMBOL_DESCRIPTION_NODE[] rgSymbolNodes, uint ulcNodes, out IVsNavInfo ppNavInfo) @@ -50,7 +52,8 @@ int IVsSimpleLibrary2.GetLibFlags2(out uint pgrfFlags) int IVsSimpleLibrary2.GetList2(uint listType, uint flags, VSOBSEARCHCRITERIA2[] pobSrch, out IVsSimpleObjectList2 ppIVsSimpleObjectList2) { - ppIVsSimpleObjectList2 = GetList(listType, flags, pobSrch); + ppIVsSimpleObjectList2 = this.ThreadingContext.JoinableTaskFactory.Run( + () => GetListAsync(listType, flags, pobSrch, CancellationToken.None)); return ppIVsSimpleObjectList2 != null ? VSConstants.S_OK diff --git a/src/VisualStudio/Core/Def/Library/AbstractObjectList.cs b/src/VisualStudio/Core/Def/Library/AbstractObjectList.cs index 669fc16803438..b7cef249a7e36 100644 --- a/src/VisualStudio/Core/Def/Library/AbstractObjectList.cs +++ b/src/VisualStudio/Core/Def/Library/AbstractObjectList.cs @@ -62,11 +62,8 @@ protected virtual bool TryGetContextMenu(uint index, out Guid menuGuid, out int return false; } - protected virtual bool TryGetProperty(uint index, _VSOBJLISTELEMPROPID propertyId, out object pvar) - { - pvar = null; - return false; - } + protected virtual Task<(bool success, object pvar)> TryGetPropertyAsync(uint index, _VSOBJLISTELEMPROPID propertyId, CancellationToken cancellationToken) + => SpecializedTasks.Default<(bool success, object pvar)>(); protected virtual bool TryCountSourceItems(uint index, out IVsHierarchy hierarchy, out uint itemid, out uint items) { @@ -101,8 +98,8 @@ protected virtual bool SupportsDescription get { return false; } } - protected virtual bool TryFillDescription(uint index, _VSOBJDESCOPTIONS options, IVsObjectBrowserDescription3 description) - => false; + protected virtual Task TryFillDescriptionAsync(uint index, _VSOBJDESCOPTIONS options, IVsObjectBrowserDescription3 description, CancellationToken cancellationToken) + => SpecializedTasks.False; int IVsSimpleObjectList2.CanDelete(uint index, out int pfOK) { @@ -147,11 +144,11 @@ int IVsSimpleObjectList2.EnumClipboardFormats(uint index, uint grfFlags, uint ce int IVsSimpleObjectList2.FillDescription2(uint index, uint grfOptions, IVsObjectBrowserDescription3 pobDesc) { if (!SupportsDescription) - { return VSConstants.E_NOTIMPL; - } - return TryFillDescription(index, (_VSOBJDESCOPTIONS)grfOptions, pobDesc) + var result = this.LibraryManager.ThreadingContext.JoinableTaskFactory.Run( + () => TryFillDescriptionAsync(index, (_VSOBJDESCOPTIONS)grfOptions, pobDesc, CancellationToken.None)); + return result ? VSConstants.S_OK : VSConstants.E_FAIL; } @@ -270,11 +267,15 @@ int IVsSimpleObjectList2.GetNavInfoNode(uint index, out IVsNavInfoNode ppNavInfo int IVsSimpleObjectList2.GetProperty(uint index, int propid, out object pvar) { - if (TryGetProperty(index, (_VSOBJLISTELEMPROPID)propid, out pvar)) + var (success, obj) = this.LibraryManager.ThreadingContext.JoinableTaskFactory.Run(() => + TryGetPropertyAsync(index, (_VSOBJLISTELEMPROPID)propid, CancellationToken.None)); + if (success) { + pvar = obj; return VSConstants.S_OK; } + pvar = null; return VSConstants.E_FAIL; } diff --git a/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractDescriptionBuilder.cs b/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractDescriptionBuilder.cs index 2477a7e015de2..cb11885370585 100644 --- a/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractDescriptionBuilder.cs +++ b/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractDescriptionBuilder.cs @@ -7,6 +7,7 @@ using System; using System.Diagnostics; using System.Threading; +using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.DocumentationComments; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -37,12 +38,8 @@ protected AbstractDescriptionBuilder( _project = project; } - private Compilation GetCompilation() - { - return _project - .GetCompilationAsync(CancellationToken.None) - .WaitAndGetResult_ObjectBrowser(CancellationToken.None); - } + private Task GetCompilationAsync(CancellationToken cancellationToken) + => _project.GetCompilationAsync(cancellationToken); protected void AddAssemblyLink(IAssemblySymbol assemblySymbol) { @@ -67,7 +64,7 @@ protected void AddLineBreak() protected void AddName(string text) => _description.AddDescriptionText3(text, VSOBDESCRIPTIONSECTION.OBDS_NAME, null); - protected void AddNamespaceLink(INamespaceSymbol namespaceSymbol) + protected async Task AddNamespaceLinkAsync(INamespaceSymbol namespaceSymbol, CancellationToken cancellationToken) { if (namespaceSymbol.IsGlobalNamespace) { @@ -75,7 +72,8 @@ protected void AddNamespaceLink(INamespaceSymbol namespaceSymbol) } var text = namespaceSymbol.ToDisplayString(); - var navInfo = _libraryManager.LibraryService.NavInfoFactory.CreateForNamespace(namespaceSymbol, _project, GetCompilation(), useExpandedHierarchy: false); + var navInfo = _libraryManager.LibraryService.NavInfoFactory.CreateForNamespace( + namespaceSymbol, _project, await GetCompilationAsync(cancellationToken).ConfigureAwait(true), useExpandedHierarchy: false); _description.AddDescriptionText3(text, VSOBDESCRIPTIONSECTION.OBDS_TYPE, navInfo); } @@ -86,7 +84,8 @@ protected void AddParam(string text) protected void AddText(string text) => _description.AddDescriptionText3(text, VSOBDESCRIPTIONSECTION.OBDS_MISC, null); - protected void AddTypeLink(ITypeSymbol typeSymbol, LinkFlags flags) + protected async Task AddTypeLinkAsync( + ITypeSymbol typeSymbol, LinkFlags flags, CancellationToken cancellationToken) { if (typeSymbol.TypeKind is TypeKind.Unknown or TypeKind.Error or TypeKind.TypeParameter || typeSymbol.SpecialType == SpecialType.System_Void) @@ -100,7 +99,7 @@ protected void AddTypeLink(ITypeSymbol typeSymbol, LinkFlags flags) if (splitLink && !typeSymbol.ContainingNamespace.IsGlobalNamespace) { - AddNamespaceLink(typeSymbol.ContainingNamespace); + await AddNamespaceLinkAsync(typeSymbol.ContainingNamespace, cancellationToken).ConfigureAwait(true); AddText("."); } @@ -118,7 +117,8 @@ protected void AddTypeLink(ITypeSymbol typeSymbol, LinkFlags flags) miscellaneousOptions: miscellaneousOptions); var text = typeSymbol.ToDisplayString(typeDisplayFormat); - var navInfo = _libraryManager.LibraryService.NavInfoFactory.CreateForType(typeSymbol, _project, GetCompilation(), useExpandedHierarchy: false); + var navInfo = _libraryManager.LibraryService.NavInfoFactory.CreateForType( + typeSymbol, _project, await GetCompilationAsync(cancellationToken).ConfigureAwait(true), useExpandedHierarchy: false); _description.AddDescriptionText3(text, VSOBDESCRIPTIONSECTION.OBDS_TYPE, navInfo); } @@ -142,9 +142,10 @@ private void BuildReference(ReferenceListItem referenceListItem) } } - private void BuildNamespace(NamespaceListItem namespaceListItem, _VSOBJDESCOPTIONS options) + private async Task BuildNamespaceAsync( + NamespaceListItem namespaceListItem, _VSOBJDESCOPTIONS options, CancellationToken cancellationToken) { - var compilation = GetCompilation(); + var compilation = await GetCompilationAsync(cancellationToken).ConfigureAwait(true); if (compilation == null) { return; @@ -159,12 +160,12 @@ private void BuildNamespace(NamespaceListItem namespaceListItem, _VSOBJDESCOPTIO BuildNamespaceDeclaration(namespaceSymbol, options); AddEndDeclaration(); - BuildMemberOf(namespaceSymbol.ContainingAssembly); + await BuildMemberOfAsync(namespaceSymbol.ContainingAssembly, cancellationToken).ConfigureAwait(true); } - private void BuildType(TypeListItem typeListItem, _VSOBJDESCOPTIONS options) + private async Task BuildTypeAsync(TypeListItem typeListItem, _VSOBJDESCOPTIONS options, CancellationToken cancellationToken) { - var compilation = GetCompilation(); + var compilation = await GetCompilationAsync(cancellationToken).ConfigureAwait(true); if (compilation == null) { return; @@ -178,49 +179,44 @@ private void BuildType(TypeListItem typeListItem, _VSOBJDESCOPTIONS options) if (symbol.TypeKind == TypeKind.Delegate) { - BuildDelegateDeclaration(symbol, options); + await BuildDelegateDeclarationAsync(symbol, options, cancellationToken).ConfigureAwait(true); } else { - BuildTypeDeclaration(symbol, options); + await BuildTypeDeclarationAsync(symbol, options, cancellationToken).ConfigureAwait(true); } AddEndDeclaration(); - BuildMemberOf(symbol.ContainingNamespace); - - BuildXmlDocumentation(symbol, compilation); + await BuildMemberOfAsync(symbol.ContainingNamespace, cancellationToken).ConfigureAwait(true); + await BuildXmlDocumentationAsync(symbol, compilation, cancellationToken).ConfigureAwait(true); } - private void BuildMember(MemberListItem memberListItem, _VSOBJDESCOPTIONS options) + private async Task BuildMemberAsync(MemberListItem memberListItem, _VSOBJDESCOPTIONS options, CancellationToken cancellationToken) { - var compilation = GetCompilation(); + var compilation = await GetCompilationAsync(cancellationToken).ConfigureAwait(true); if (compilation == null) - { return; - } var symbol = memberListItem.ResolveTypedSymbol(compilation); if (symbol == null) - { return; - } switch (symbol.Kind) { case SymbolKind.Method: - BuildMethodDeclaration((IMethodSymbol)symbol, options); + await BuildMethodDeclarationAsync((IMethodSymbol)symbol, options, cancellationToken).ConfigureAwait(true); break; case SymbolKind.Field: - BuildFieldDeclaration((IFieldSymbol)symbol, options); + await BuildFieldDeclarationAsync((IFieldSymbol)symbol, options, cancellationToken).ConfigureAwait(true); break; case SymbolKind.Property: - BuildPropertyDeclaration((IPropertySymbol)symbol, options); + await BuildPropertyDeclarationAsync((IPropertySymbol)symbol, options, cancellationToken).ConfigureAwait(true); break; case SymbolKind.Event: - BuildEventDeclaration((IEventSymbol)symbol, options); + await BuildEventDeclarationAsync((IEventSymbol)symbol, options, cancellationToken).ConfigureAwait(true); break; default: @@ -229,20 +225,19 @@ private void BuildMember(MemberListItem memberListItem, _VSOBJDESCOPTIONS option } AddEndDeclaration(); - BuildMemberOf(symbol.ContainingType); - - BuildXmlDocumentation(symbol, compilation); + await BuildMemberOfAsync(symbol.ContainingType, cancellationToken).ConfigureAwait(true); + await BuildXmlDocumentationAsync(symbol, compilation, cancellationToken).ConfigureAwait(true); } protected abstract void BuildNamespaceDeclaration(INamespaceSymbol namespaceSymbol, _VSOBJDESCOPTIONS options); - protected abstract void BuildDelegateDeclaration(INamedTypeSymbol typeSymbol, _VSOBJDESCOPTIONS options); - protected abstract void BuildTypeDeclaration(INamedTypeSymbol typeSymbol, _VSOBJDESCOPTIONS options); - protected abstract void BuildMethodDeclaration(IMethodSymbol methodSymbol, _VSOBJDESCOPTIONS options); - protected abstract void BuildFieldDeclaration(IFieldSymbol fieldSymbol, _VSOBJDESCOPTIONS options); - protected abstract void BuildPropertyDeclaration(IPropertySymbol propertySymbol, _VSOBJDESCOPTIONS options); - protected abstract void BuildEventDeclaration(IEventSymbol eventSymbol, _VSOBJDESCOPTIONS options); - - private void BuildMemberOf(ISymbol containingSymbol) + protected abstract Task BuildDelegateDeclarationAsync(INamedTypeSymbol typeSymbol, _VSOBJDESCOPTIONS options, CancellationToken cancellationToken); + protected abstract Task BuildTypeDeclarationAsync(INamedTypeSymbol typeSymbol, _VSOBJDESCOPTIONS options, CancellationToken cancellationToken); + protected abstract Task BuildMethodDeclarationAsync(IMethodSymbol methodSymbol, _VSOBJDESCOPTIONS options, CancellationToken cancellationToken); + protected abstract Task BuildFieldDeclarationAsync(IFieldSymbol fieldSymbol, _VSOBJDESCOPTIONS options, CancellationToken cancellationToken); + protected abstract Task BuildPropertyDeclarationAsync(IPropertySymbol propertySymbol, _VSOBJDESCOPTIONS options, CancellationToken cancellationToken); + protected abstract Task BuildEventDeclarationAsync(IEventSymbol eventSymbol, _VSOBJDESCOPTIONS options, CancellationToken cancellationToken); + + private async Task BuildMemberOfAsync(ISymbol containingSymbol, CancellationToken cancellationToken) { if (containingSymbol is INamespaceSymbol && ((INamespaceSymbol)containingSymbol).IsGlobalNamespace) @@ -272,18 +267,20 @@ private void BuildMemberOf(ISymbol containingSymbol) } else if (containingSymbol is ITypeSymbol typeSymbol) { - AddTypeLink(typeSymbol, LinkFlags.SplitNamespaceAndType | LinkFlags.ExpandPredefinedTypes); + await AddTypeLinkAsync( + typeSymbol, LinkFlags.SplitNamespaceAndType | LinkFlags.ExpandPredefinedTypes, cancellationToken).ConfigureAwait(true); } else if (containingSymbol is INamespaceSymbol namespaceSymbol) { - AddNamespaceLink(namespaceSymbol); + await AddNamespaceLinkAsync(namespaceSymbol, cancellationToken).ConfigureAwait(true); } AddText(right); AddEndDeclaration(); } - private void BuildXmlDocumentation(ISymbol symbol, Compilation compilation) + private async Task BuildXmlDocumentationAsync( + ISymbol symbol, Compilation compilation, CancellationToken cancellationToken) { var documentationComment = symbol.GetDocumentationComment(compilation, expandIncludes: true, expandInheritdoc: true, cancellationToken: CancellationToken.None); if (documentationComment == null) @@ -425,13 +422,13 @@ private void BuildXmlDocumentation(ISymbol symbol, Compilation compilation) var exceptionTexts = documentationComment.GetExceptionTexts(exceptionType); if (exceptionTexts.Length == 0) { - AddTypeLink(exceptionTypeSymbol, LinkFlags.None); + await AddTypeLinkAsync(exceptionTypeSymbol, LinkFlags.None, cancellationToken).ConfigureAwait(true); } else { foreach (var exceptionText in exceptionTexts) { - AddTypeLink(exceptionTypeSymbol, LinkFlags.None); + await AddTypeLinkAsync(exceptionTypeSymbol, LinkFlags.None, cancellationToken).ConfigureAwait(true); AddText(": "); AddText(formattingService.Format(exceptionText, compilation)); } @@ -455,7 +452,7 @@ private static bool ShowValueDocumentation(ISymbol symbol) return ShowReturnsDocumentation(symbol); } - internal bool TryBuild(_VSOBJDESCOPTIONS options) + internal async Task TryBuildAsync(_VSOBJDESCOPTIONS options, CancellationToken cancellationToken) { switch (_listItem) { @@ -466,13 +463,13 @@ internal bool TryBuild(_VSOBJDESCOPTIONS options) BuildReference(referenceListItem); return true; case NamespaceListItem namespaceListItem: - BuildNamespace(namespaceListItem, options); + await BuildNamespaceAsync(namespaceListItem, options, cancellationToken).ConfigureAwait(true); return true; case TypeListItem typeListItem: - BuildType(typeListItem, options); + await BuildTypeAsync(typeListItem, options, cancellationToken).ConfigureAwait(true); return true; case MemberListItem memberListItem: - BuildMember(memberListItem, options); + await BuildMemberAsync(memberListItem, options, cancellationToken).ConfigureAwait(true); return true; } diff --git a/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager.cs b/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager.cs index 3191429c71811..aba4e28fe4c90 100644 --- a/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager.cs +++ b/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager.cs @@ -195,17 +195,14 @@ internal Project GetProject(ObjectListItem listItem) return this.GetProject(projectId); } - internal Compilation GetCompilation(ProjectId projectId) + internal async Task GetCompilationAsync( + ProjectId projectId, CancellationToken cancellationToken) { var project = GetProject(projectId); if (project == null) - { return null; - } - return project - .GetCompilationAsync(CancellationToken.None) - .WaitAndGetResult_ObjectBrowser(CancellationToken.None); + return await project.GetCompilationAsync(cancellationToken).ConfigureAwait(true); } public override uint GetLibraryFlags() @@ -301,30 +298,26 @@ protected override uint GetSupportedCategoryFields(uint category) return 0; } - protected override IVsSimpleObjectList2 GetList(uint listType, uint flags, VSOBSEARCHCRITERIA2[] pobSrch) + protected override async Task GetListAsync( + uint listType, uint flags, VSOBSEARCHCRITERIA2[] pobSrch, CancellationToken cancellationToken) { - return this.ThreadingContext.JoinableTaskFactory.Run(() => GetListAsync()); + var listKind = Helpers.ListTypeToObjectListKind(listType); - async Task GetListAsync() + if (Helpers.IsFindSymbol(flags)) { - var listKind = Helpers.ListTypeToObjectListKind(listType); - - if (Helpers.IsFindSymbol(flags)) - { - var projectAndAssemblySet = await this.GetAssemblySetAsync( - this.Workspace.CurrentSolution, _languageName, CancellationToken.None).ConfigureAwait(true); - return GetSearchList(listKind, flags, pobSrch, projectAndAssemblySet); - } + var projectAndAssemblySet = await this.GetAssemblySetAsync( + this.Workspace.CurrentSolution, _languageName, CancellationToken.None).ConfigureAwait(true); + return await GetSearchListAsync(listKind, flags, pobSrch, projectAndAssemblySet, cancellationToken).ConfigureAwait(true); + } - if (listKind == ObjectListKind.Hierarchy) - { - return null; - } + if (listKind == ObjectListKind.Hierarchy) + { + return null; + } - Debug.Assert(listKind == ObjectListKind.Projects); + Debug.Assert(listKind == ObjectListKind.Projects); - return new ObjectList(ObjectListKind.Projects, flags, this, this.GetProjectListItems(this.Workspace.CurrentSolution, _languageName, flags)); - } + return new ObjectList(ObjectListKind.Projects, flags, this, this.GetProjectListItems(this.Workspace.CurrentSolution, _languageName, flags)); } protected override uint GetUpdateCounter() diff --git a/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager_Description.cs b/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager_Description.cs index 98ffc9fef6ccc..dfce8ffdb2c53 100644 --- a/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager_Description.cs +++ b/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager_Description.cs @@ -4,20 +4,26 @@ #nullable disable +using System.Threading; +using System.Threading.Tasks; using Microsoft.VisualStudio.Shell.Interop; namespace Microsoft.VisualStudio.LanguageServices.Implementation.Library.ObjectBrowser; internal abstract partial class AbstractObjectBrowserLibraryManager { - internal bool TryFillDescription(ObjectListItem listItem, IVsObjectBrowserDescription3 description, _VSOBJDESCOPTIONS options) + internal async Task TryFillDescriptionAsync( + ObjectListItem listItem, + IVsObjectBrowserDescription3 description, + _VSOBJDESCOPTIONS options, + CancellationToken cancellationToken) { var project = GetProject(listItem); if (project == null) - { return false; - } - return CreateDescriptionBuilder(description, listItem, project).TryBuild(options); + return await CreateDescriptionBuilder(description, listItem, project) + .TryBuildAsync(options, cancellationToken) + .ConfigureAwait(true); } } diff --git a/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager_Search.cs b/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager_Search.cs index 22e3b392e50f2..1e1398be7e774 100644 --- a/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager_Search.cs +++ b/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager_Search.cs @@ -6,6 +6,8 @@ using System; using System.Collections.Immutable; +using System.Threading; +using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.VisualStudio.Shell.Interop; @@ -32,17 +34,16 @@ private static string GetSearchText(VSOBSEARCHCRITERIA2[] pobSrch) return searchText; } - public IVsSimpleObjectList2 GetSearchList( + public async Task GetSearchListAsync( ObjectListKind listKind, uint flags, VSOBSEARCHCRITERIA2[] pobSrch, - ImmutableHashSet<(ProjectId, IAssemblySymbol)> projectAndAssemblySet) + ImmutableHashSet<(ProjectId, IAssemblySymbol)> projectAndAssemblySet, + CancellationToken cancellationToken) { var searchText = GetSearchText(pobSrch); if (searchText == null) - { return null; - } // TODO: Support wildcards (e.g. *xyz, *xyz* and xyz*) like the old language service did. @@ -72,11 +73,9 @@ public IVsSimpleObjectList2 GetSearchList( var projectId = projectIdAndAssembly.Item1; var assemblySymbol = projectIdAndAssembly.Item2; - var compilation = this.GetCompilation(projectId); + var compilation = await this.GetCompilationAsync(projectId, cancellationToken).ConfigureAwait(true); if (compilation == null) - { return null; - } CollectTypeListItems(assemblySymbol, compilation, projectId, builder, searchText); } @@ -93,11 +92,9 @@ public IVsSimpleObjectList2 GetSearchList( var projectId = projectIdAndAssembly.Item1; var assemblySymbol = projectIdAndAssembly.Item2; - var compilation = this.GetCompilation(projectId); + var compilation = await this.GetCompilationAsync(projectId, cancellationToken).ConfigureAwait(true); if (compilation == null) - { return null; - } CollectMemberListItems(assemblySymbol, compilation, projectId, builder, searchText); } diff --git a/src/VisualStudio/Core/Def/Library/ObjectBrowser/ObjectBrowserTaskExtensions.cs b/src/VisualStudio/Core/Def/Library/ObjectBrowser/ObjectBrowserTaskExtensions.cs deleted file mode 100644 index 5ab1329523c81..0000000000000 --- a/src/VisualStudio/Core/Def/Library/ObjectBrowser/ObjectBrowserTaskExtensions.cs +++ /dev/null @@ -1,27 +0,0 @@ -// 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. - -#nullable disable - -using System.Threading.Tasks; -using Roslyn.Utilities; -using System.Threading; - -namespace Microsoft.VisualStudio.LanguageServices.Implementation.Library.ObjectBrowser; - -internal static class ObjectBrowserTaskExtensions -{ - /// - /// Does a for ObjectBrowser. - /// - /// - /// This function is the exact same as , except it opts out - /// of enforcement that it can be called on non-UI threads. ObjectBrowser, since it must implement a highly blocking API, - /// has no choice but to use WaitAndGetResult in a bunch of places. But that's not a good reason to require the tests - /// to have thread affinity, since the tests have no specific threading requirements. Thus, it's acceptable for ObjectBrowser - /// to call the _CanCallOnBackground variant. We hope to audit _CanCallOnBackground periodically, and so rather than - /// having to understand that each of those uses are ObjectBrowser and thus get a special pass. - public static T WaitAndGetResult_ObjectBrowser(this Task task, CancellationToken cancellationToken) - => task.WaitAndGetResult_CanCallOnBackground(cancellationToken); -} diff --git a/src/VisualStudio/Core/Def/Library/ObjectBrowser/ObjectList.cs b/src/VisualStudio/Core/Def/Library/ObjectBrowser/ObjectList.cs index 4c67cb05c6404..4c2cf1851cb5f 100644 --- a/src/VisualStudio/Core/Def/Library/ObjectBrowser/ObjectList.cs +++ b/src/VisualStudio/Core/Def/Library/ObjectBrowser/ObjectList.cs @@ -501,7 +501,8 @@ protected override async Task GetListAsync( var projectAndAssemblySet = await this.LibraryManager.GetAssemblySetAsync( project, lookInReferences, cancellationToken).ConfigureAwait(true); - return this.LibraryManager.GetSearchList(listKind, flags, pobSrch, projectAndAssemblySet); + return await this.LibraryManager.GetSearchListAsync( + listKind, flags, pobSrch, projectAndAssemblySet, cancellationToken).ConfigureAwait(true); } var compilation = await listItem.GetCompilationAsync( @@ -653,28 +654,26 @@ protected override bool SupportsDescription get { return true; } } - protected override bool TryFillDescription(uint index, _VSOBJDESCOPTIONS options, IVsObjectBrowserDescription3 description) + protected override Task TryFillDescriptionAsync( + uint index, _VSOBJDESCOPTIONS options, IVsObjectBrowserDescription3 description, CancellationToken cancellationToken) { var listItem = GetListItem(index); - return this.LibraryManager.TryFillDescription(listItem, description, options); + return this.LibraryManager.TryFillDescriptionAsync( + listItem, description, options, cancellationToken); } - protected override bool TryGetProperty(uint index, _VSOBJLISTELEMPROPID propertyId, out object pvar) + protected override async Task<(bool success, object pvar)> TryGetPropertyAsync( + uint index, _VSOBJLISTELEMPROPID propertyId, CancellationToken cancellationToken) { - pvar = null; - var listItem = GetListItem(index); if (listItem == null) - { - return false; - } + return default; switch (propertyId) { case _VSOBJLISTELEMPROPID.VSOBJLISTELEMPROPID_FULLNAME: - pvar = listItem.FullNameText; - return true; + return (true, listItem.FullNameText); case _VSOBJLISTELEMPROPID.VSOBJLISTELEMPROPID_HELPKEYWORD: if (listItem is SymbolListItem symbolListItem) @@ -682,25 +681,21 @@ protected override bool TryGetProperty(uint index, _VSOBJLISTELEMPROPID property var project = this.LibraryManager.Workspace.CurrentSolution.GetProject(symbolListItem.ProjectId); if (project != null) { - var compilation = project - .GetCompilationAsync(CancellationToken.None) - .WaitAndGetResult_ObjectBrowser(CancellationToken.None); + var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(true); var symbol = symbolListItem.ResolveSymbol(compilation); if (symbol != null) { var helpContextService = project.Services.GetService(); - - pvar = helpContextService.FormatSymbol(symbol); - return true; + return (true, helpContextService.FormatSymbol(symbol)); } } } - return false; + return default; } - return false; + return default; } protected override bool TryCountSourceItems(uint index, out IVsHierarchy hierarchy, out uint itemid, out uint items) diff --git a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs index 192d4fcc48c6d..94a232ae87998 100644 --- a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs +++ b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs @@ -20,7 +20,6 @@ using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Progress; -using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem; using Microsoft.VisualStudio.LanguageServices.Implementation.TableDataSource; @@ -40,54 +39,33 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.Suppression; /// [Export(typeof(IVisualStudioSuppressionFixService))] [Export(typeof(VisualStudioSuppressionFixService))] -internal sealed class VisualStudioSuppressionFixService : IVisualStudioSuppressionFixService +[method: ImportingConstructor] +[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] +internal sealed class VisualStudioSuppressionFixService( + IThreadingContext threadingContext, + VisualStudioWorkspaceImpl workspace, + IDiagnosticAnalyzerService diagnosticService, + ICodeFixService codeFixService, + ICodeActionEditHandlerService editHandlerService, + VisualStudioDiagnosticListSuppressionStateService suppressionStateService, + IUIThreadOperationExecutor uiThreadOperationExecutor, + IVsHierarchyItemManager vsHierarchyItemManager, + IAsynchronousOperationListenerProvider listenerProvider) : IVisualStudioSuppressionFixService { - private readonly IThreadingContext _threadingContext; - private readonly VisualStudioWorkspaceImpl _workspace; - private readonly IAsynchronousOperationListener _listener; - private readonly IDiagnosticAnalyzerService _diagnosticService; - private readonly ExternalErrorDiagnosticUpdateSource _buildErrorDiagnosticService; - private readonly ICodeFixService _codeFixService; - private readonly IFixMultipleOccurrencesService _fixMultipleOccurencesService; - private readonly ICodeActionEditHandlerService _editHandlerService; - private readonly VisualStudioDiagnosticListSuppressionStateService _suppressionStateService; - private readonly IUIThreadOperationExecutor _uiThreadOperationExecutor; - private readonly IVsHierarchyItemManager _vsHierarchyItemManager; - private readonly IHierarchyItemToProjectIdMap _projectMap; - private readonly IGlobalOptionService _globalOptions; + private readonly IThreadingContext _threadingContext = threadingContext; + private readonly VisualStudioWorkspaceImpl _workspace = workspace; + private readonly IAsynchronousOperationListener _listener = listenerProvider.GetListener(FeatureAttribute.ErrorList); + private readonly IDiagnosticAnalyzerService _diagnosticService = diagnosticService; + private readonly ICodeFixService _codeFixService = codeFixService; + private readonly IFixMultipleOccurrencesService _fixMultipleOccurencesService = workspace.Services.GetRequiredService(); + private readonly ICodeActionEditHandlerService _editHandlerService = editHandlerService; + private readonly VisualStudioDiagnosticListSuppressionStateService _suppressionStateService = suppressionStateService; + private readonly IUIThreadOperationExecutor _uiThreadOperationExecutor = uiThreadOperationExecutor; + private readonly IVsHierarchyItemManager _vsHierarchyItemManager = vsHierarchyItemManager; + private readonly IHierarchyItemToProjectIdMap _projectMap = workspace.Services.GetRequiredService(); private IWpfTableControl? _tableControl; - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public VisualStudioSuppressionFixService( - IThreadingContext threadingContext, - SVsServiceProvider serviceProvider, - VisualStudioWorkspaceImpl workspace, - IDiagnosticAnalyzerService diagnosticService, - ICodeFixService codeFixService, - ICodeActionEditHandlerService editHandlerService, - VisualStudioDiagnosticListSuppressionStateService suppressionStateService, - IUIThreadOperationExecutor uiThreadOperationExecutor, - IVsHierarchyItemManager vsHierarchyItemManager, - IAsynchronousOperationListenerProvider listenerProvider, - IGlobalOptionService globalOptions) - { - _threadingContext = threadingContext; - _workspace = workspace; - _diagnosticService = diagnosticService; - _buildErrorDiagnosticService = workspace.ExternalErrorDiagnosticUpdateSource; - _codeFixService = codeFixService; - _suppressionStateService = suppressionStateService; - _editHandlerService = editHandlerService; - _uiThreadOperationExecutor = uiThreadOperationExecutor; - _vsHierarchyItemManager = vsHierarchyItemManager; - _fixMultipleOccurencesService = workspace.Services.GetRequiredService(); - _projectMap = workspace.Services.GetRequiredService(); - _listener = listenerProvider.GetListener(FeatureAttribute.ErrorList); - _globalOptions = globalOptions; - } - public async Task InitializeAsync(IAsyncServiceProvider serviceProvider) { var errorList = await serviceProvider.GetServiceAsync(_threadingContext.JoinableTaskFactory, throwOnFailure: false).ConfigureAwait(false); @@ -96,44 +74,57 @@ public async Task InitializeAsync(IAsyncServiceProvider serviceProvider) public bool AddSuppressions(IVsHierarchy? projectHierarchy) { - if (_tableControl == null) + return _threadingContext.JoinableTaskFactory.Run(async () => { - return false; - } + if (_tableControl == null) + return false; - var shouldFixInProject = GetShouldFixInProjectDelegate(_vsHierarchyItemManager, _projectMap, projectHierarchy); + var shouldFixInProject = GetShouldFixInProjectDelegate(_vsHierarchyItemManager, _projectMap, projectHierarchy); - // Apply suppressions fix in global suppressions file for non-compiler diagnostics and - // in source only for compiler diagnostics. - var diagnosticsToFix = GetDiagnosticsToFix(selectedEntriesOnly: false, isAddSuppression: true); - if (!ApplySuppressionFix(diagnosticsToFix, shouldFixInProject, filterStaleDiagnostics: false, isAddSuppression: true, isSuppressionInSource: false, onlyCompilerDiagnostics: false, showPreviewChangesDialog: false)) - { - return false; - } + // Apply suppressions fix in global suppressions file for non-compiler diagnostics and + // in source only for compiler diagnostics. + var diagnosticsToFix = await GetDiagnosticsToFixAsync(selectedEntriesOnly: false, isAddSuppression: true).ConfigureAwait(true); + if (!ApplySuppressionFix(diagnosticsToFix, shouldFixInProject, filterStaleDiagnostics: false, isAddSuppression: true, isSuppressionInSource: false, onlyCompilerDiagnostics: false, showPreviewChangesDialog: false)) + return false; - return ApplySuppressionFix(diagnosticsToFix, shouldFixInProject, filterStaleDiagnostics: false, isAddSuppression: true, isSuppressionInSource: true, onlyCompilerDiagnostics: true, showPreviewChangesDialog: false); + return ApplySuppressionFix(diagnosticsToFix, shouldFixInProject, filterStaleDiagnostics: false, isAddSuppression: true, isSuppressionInSource: true, onlyCompilerDiagnostics: true, showPreviewChangesDialog: false); + }); } public bool AddSuppressions(bool selectedErrorListEntriesOnly, bool suppressInSource, IVsHierarchy? projectHierarchy) { - if (_tableControl == null) + return _threadingContext.JoinableTaskFactory.Run(async () => { - return false; - } - - var shouldFixInProject = GetShouldFixInProjectDelegate(_vsHierarchyItemManager, _projectMap, projectHierarchy); - return ApplySuppressionFix(shouldFixInProject, selectedErrorListEntriesOnly, isAddSuppression: true, isSuppressionInSource: suppressInSource, onlyCompilerDiagnostics: false, showPreviewChangesDialog: true); + if (_tableControl == null) + return false; + + var shouldFixInProject = GetShouldFixInProjectDelegate(_vsHierarchyItemManager, _projectMap, projectHierarchy); + return await ApplySuppressionFixAsync( + shouldFixInProject, + selectedErrorListEntriesOnly, + isAddSuppression: true, + isSuppressionInSource: suppressInSource, + onlyCompilerDiagnostics: false, + showPreviewChangesDialog: true).ConfigureAwait(true); + }); } public bool RemoveSuppressions(bool selectedErrorListEntriesOnly, IVsHierarchy? projectHierarchy) { - if (_tableControl == null) + return _threadingContext.JoinableTaskFactory.Run(async () => { - return false; - } - - var shouldFixInProject = GetShouldFixInProjectDelegate(_vsHierarchyItemManager, _projectMap, projectHierarchy); - return ApplySuppressionFix(shouldFixInProject, selectedErrorListEntriesOnly, isAddSuppression: false, isSuppressionInSource: false, onlyCompilerDiagnostics: false, showPreviewChangesDialog: true); + if (_tableControl == null) + return false; + + var shouldFixInProject = GetShouldFixInProjectDelegate(_vsHierarchyItemManager, _projectMap, projectHierarchy); + return await ApplySuppressionFixAsync( + shouldFixInProject, + selectedErrorListEntriesOnly, + isAddSuppression: false, + isSuppressionInSource: false, + onlyCompilerDiagnostics: false, + showPreviewChangesDialog: true).ConfigureAwait(true); + }); } private static Func GetShouldFixInProjectDelegate(IVsHierarchyItemManager vsHierarchyItemManager, IHierarchyItemToProjectIdMap projectMap, IVsHierarchy? projectHierarchy) @@ -157,38 +148,39 @@ private static string GetFixTitle(bool isAddSuppression) private static string GetWaitDialogMessage(bool isAddSuppression) => isAddSuppression ? ServicesVSResources.Computing_suppressions_fix : ServicesVSResources.Computing_remove_suppressions_fix; - private IEnumerable? GetDiagnosticsToFix(bool selectedEntriesOnly, bool isAddSuppression) + private async Task?> GetDiagnosticsToFixAsync( + bool selectedEntriesOnly, + bool isAddSuppression) { var diagnosticsToFix = ImmutableHashSet.Empty; - void computeDiagnosticsToFix(IUIThreadOperationContext context) - { - var cancellationToken = context.UserCancellationToken; + var result = await InvokeWithWaitDialogAsync(async cancellationToken => + { // If we are fixing selected diagnostics in error list, then get the diagnostics from error list entry // snapshots. Otherwise, get all diagnostics from the diagnostic service. - var diagnosticsToFixTask = selectedEntriesOnly - ? _suppressionStateService.GetSelectedItemsAsync(isAddSuppression, cancellationToken) - : Task.FromResult>([]); + var diagnosticsToFixArray = selectedEntriesOnly + ? await _suppressionStateService.GetSelectedItemsAsync(isAddSuppression, cancellationToken).ConfigureAwait(true) + : []; - diagnosticsToFix = diagnosticsToFixTask.WaitAndGetResult(cancellationToken).ToImmutableHashSet(); - } + diagnosticsToFix = diagnosticsToFixArray.ToImmutableHashSet(); - var title = GetFixTitle(isAddSuppression); - var waitDialogMessage = GetWaitDialogMessage(isAddSuppression); - var result = InvokeWithWaitDialog(computeDiagnosticsToFix, title, waitDialogMessage); + }, GetFixTitle(isAddSuppression), GetWaitDialogMessage(isAddSuppression)).ConfigureAwait(true); - // Bail out if the user cancelled. if (result == UIThreadOperationStatus.Canceled) - { return null; - } return diagnosticsToFix; } - private bool ApplySuppressionFix(Func shouldFixInProject, bool selectedEntriesOnly, bool isAddSuppression, bool isSuppressionInSource, bool onlyCompilerDiagnostics, bool showPreviewChangesDialog) + private async Task ApplySuppressionFixAsync( + Func shouldFixInProject, + bool selectedEntriesOnly, + bool isAddSuppression, + bool isSuppressionInSource, + bool onlyCompilerDiagnostics, + bool showPreviewChangesDialog) { - var diagnosticsToFix = GetDiagnosticsToFix(selectedEntriesOnly, isAddSuppression); + var diagnosticsToFix = await GetDiagnosticsToFixAsync(selectedEntriesOnly, isAddSuppression).ConfigureAwait(true); return ApplySuppressionFix(diagnosticsToFix, shouldFixInProject, selectedEntriesOnly, isAddSuppression, isSuppressionInSource, onlyCompilerDiagnostics, showPreviewChangesDialog); } @@ -395,28 +387,22 @@ private static IEnumerable FilterDiagnostics(IEnumerable action, string waitDialogTitle, string waitDialogMessage) + private async Task InvokeWithWaitDialogAsync( + Func action, string waitDialogTitle, string waitDialogMessage) { + using var waitContext = _uiThreadOperationExecutor.BeginExecute(waitDialogTitle, waitDialogMessage, allowCancellation: true, showProgress: true); + var cancelled = false; - var result = _uiThreadOperationExecutor.Execute( - waitDialogTitle, - waitDialogMessage, - allowCancellation: true, - showProgress: true, - action: waitContext => - { - try - { - action(waitContext); - } - catch (OperationCanceledException) - { - cancelled = true; - } - }); + try + { + await action(waitContext.UserCancellationToken).ConfigureAwait(true); + } + catch (OperationCanceledException) + { + cancelled = true; + } - return cancelled ? UIThreadOperationStatus.Canceled : result; + return cancelled ? UIThreadOperationStatus.Canceled : UIThreadOperationStatus.Completed; } private static ImmutableDictionary> GetDocumentDiagnosticsMappedToNewSolution(ImmutableDictionary> documentDiagnosticsToFixMap, Solution newSolution, string language) diff --git a/src/VisualStudio/VisualBasic/Impl/ObjectBrowser/DescriptionBuilder.vb b/src/VisualStudio/VisualBasic/Impl/ObjectBrowser/DescriptionBuilder.vb index bc464b0bf38c6..33ca08992143d 100644 --- a/src/VisualStudio/VisualBasic/Impl/ObjectBrowser/DescriptionBuilder.vb +++ b/src/VisualStudio/VisualBasic/Impl/ObjectBrowser/DescriptionBuilder.vb @@ -6,17 +6,17 @@ Imports System.Collections.Immutable Imports Microsoft.CodeAnalysis Imports Microsoft.VisualStudio.Shell.Interop Imports Microsoft.VisualStudio.LanguageServices.Implementation.Library.ObjectBrowser +Imports System.Threading Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ObjectBrowser - Friend Class DescriptionBuilder + Friend NotInheritable Class DescriptionBuilder Inherits AbstractDescriptionBuilder Public Sub New( description As IVsObjectBrowserDescription3, libraryManager As ObjectBrowserLibraryManager, listItem As ObjectListItem, - project As Project - ) + project As Project) MyBase.New(description, libraryManager, listItem, project) End Sub @@ -26,7 +26,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ObjectBrowser AddName(namespaceSymbol.ToDisplayString()) End Sub - Protected Overrides Sub BuildDelegateDeclaration(typeSymbol As INamedTypeSymbol, options As _VSOBJDESCOPTIONS) + Protected Overrides Async Function BuildDelegateDeclarationAsync( + typeSymbol As INamedTypeSymbol, + options As _VSOBJDESCOPTIONS, + cancellationToken As CancellationToken) As Task Debug.Assert(typeSymbol.TypeKind = TypeKind.Delegate) BuildTypeModifiers(typeSymbol) @@ -47,21 +50,24 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ObjectBrowser If typeSymbol.TypeParameters.Length > 0 Then AddText("(Of ") - BuildTypeParameterList(typeSymbol.TypeParameters) + Await BuildTypeParameterListAsync(typeSymbol.TypeParameters, cancellationToken).ConfigureAwait(True) AddText(")") End If AddText("(") - BuildParameterList(delegateInvokeMethod.Parameters) + Await BuildParameterListAsync(delegateInvokeMethod.Parameters, cancellationToken).ConfigureAwait(True) AddText(")") If Not delegateInvokeMethod.ReturnsVoid Then AddText(" As ") - AddTypeLink(delegateInvokeMethod.ReturnType, LinkFlags.None) + Await AddTypeLinkAsync(delegateInvokeMethod.ReturnType, LinkFlags.None, cancellationToken).ConfigureAwait(True) End If - End Sub + End Function - Protected Overrides Sub BuildTypeDeclaration(typeSymbol As INamedTypeSymbol, options As _VSOBJDESCOPTIONS) + Protected Overrides Async Function BuildTypeDeclarationAsync( + typeSymbol As INamedTypeSymbol, + options As _VSOBJDESCOPTIONS, + cancellationToken As CancellationToken) As Task BuildTypeModifiers(typeSymbol) Select Case typeSymbol.TypeKind @@ -87,7 +93,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ObjectBrowser If typeSymbol.TypeParameters.Length > 0 Then AddText("(Of ") - BuildTypeParameterList(typeSymbol.TypeParameters) + Await BuildTypeParameterListAsync(typeSymbol.TypeParameters, cancellationToken).ConfigureAwait(True) AddText(")") End If @@ -98,7 +104,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ObjectBrowser AddIndent() AddIndent() AddText("Inherits ") - AddTypeLink(baseType, LinkFlags.None) + Await AddTypeLinkAsync(baseType, LinkFlags.None, cancellationToken).ConfigureAwait(True) End If End If @@ -106,23 +112,28 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ObjectBrowser Dim underlyingType = typeSymbol.EnumUnderlyingType If underlyingType IsNot Nothing AndAlso underlyingType.SpecialType <> SpecialType.System_Int32 Then AddText(" As ") - AddTypeLink(underlyingType, LinkFlags.None) + Await AddTypeLinkAsync(underlyingType, LinkFlags.None, cancellationToken).ConfigureAwait(True) End If End If - End Sub + End Function - Protected Overrides Sub BuildMethodDeclaration(methodSymbol As IMethodSymbol, options As _VSOBJDESCOPTIONS) + Protected Overrides Async Function BuildMethodDeclarationAsync( + methodSymbol As IMethodSymbol, + options As _VSOBJDESCOPTIONS, + cancellationToken As CancellationToken) As Task Select Case methodSymbol.MethodKind Case MethodKind.Conversion, MethodKind.UserDefinedOperator - BuildOperatorDeclaration(methodSymbol) + Await BuildOperatorDeclarationAsync(methodSymbol, cancellationToken).ConfigureAwait(True) Case MethodKind.DeclareMethod - BuildDeclareMethodDeclaration(methodSymbol) + Await BuildDeclareMethodDeclarationAsync(methodSymbol, cancellationToken).ConfigureAwait(True) Case Else - BuildRegularMethodDeclaration(methodSymbol) + Await BuildRegularMethodDeclarationAsync(methodSymbol, cancellationToken).ConfigureAwait(True) End Select - End Sub + End Function - Private Sub BuildOperatorDeclaration(methodSymbol As IMethodSymbol) + Private Async Function BuildOperatorDeclarationAsync( + methodSymbol As IMethodSymbol, + cancellationToken As CancellationToken) As Task BuildMemberModifiers(methodSymbol) Select Case methodSymbol.Name @@ -138,16 +149,18 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ObjectBrowser AddName(methodSymbol.ToDisplayString(methodNameFormat)) AddText("(") - BuildParameterList(methodSymbol.Parameters) + Await BuildParameterListAsync(methodSymbol.Parameters, cancellationToken).ConfigureAwait(True) AddText(")") If Not methodSymbol.ReturnsVoid Then AddText(" As ") - AddTypeLink(methodSymbol.ReturnType, LinkFlags.None) + Await AddTypeLinkAsync(methodSymbol.ReturnType, LinkFlags.None, cancellationToken).ConfigureAwait(True) End If - End Sub + End Function - Private Sub BuildDeclareMethodDeclaration(methodSymbol As IMethodSymbol) + Private Async Function BuildDeclareMethodDeclarationAsync( + methodSymbol As IMethodSymbol, + cancellationToken As CancellationToken) As Task BuildMemberModifiers(methodSymbol) AddText("Declare ") @@ -185,16 +198,18 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ObjectBrowser End If AddText("(") - BuildParameterList(methodSymbol.Parameters) + Await BuildParameterListAsync(methodSymbol.Parameters, cancellationToken).ConfigureAwait(True) AddText(")") If Not methodSymbol.ReturnsVoid Then AddText(" As ") - AddTypeLink(methodSymbol.ReturnType, LinkFlags.None) + Await AddTypeLinkAsync(methodSymbol.ReturnType, LinkFlags.None, cancellationToken).ConfigureAwait(True) End If - End Sub + End Function - Private Sub BuildRegularMethodDeclaration(methodSymbol As IMethodSymbol) + Private Async Function BuildRegularMethodDeclarationAsync( + methodSymbol As IMethodSymbol, + cancellationToken As CancellationToken) As Task BuildMemberModifiers(methodSymbol) If methodSymbol.ReturnsVoid Then @@ -208,27 +223,30 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ObjectBrowser If methodSymbol.TypeParameters.Length > 0 Then AddText("(Of ") - BuildTypeParameterList(methodSymbol.TypeParameters) + Await BuildTypeParameterListAsync(methodSymbol.TypeParameters, cancellationToken).ConfigureAwait(True) AddText(")") End If AddText("(") - BuildParameterList(methodSymbol.Parameters) + Await BuildParameterListAsync(methodSymbol.Parameters, cancellationToken).ConfigureAwait(True) AddText(")") If Not methodSymbol.ReturnsVoid Then AddText(" As ") - AddTypeLink(methodSymbol.ReturnType, LinkFlags.None) + Await AddTypeLinkAsync(methodSymbol.ReturnType, LinkFlags.None, cancellationToken).ConfigureAwait(True) End If - End Sub + End Function - Protected Overrides Sub BuildFieldDeclaration(fieldSymbol As IFieldSymbol, options As _VSOBJDESCOPTIONS) + Protected Overrides Async Function BuildFieldDeclarationAsync( + fieldSymbol As IFieldSymbol, + options As _VSOBJDESCOPTIONS, + cancellationToken As CancellationToken) As Task BuildMemberModifiers(fieldSymbol) AddText(fieldSymbol.Name) AddText(" As ") - AddTypeLink(fieldSymbol.Type, LinkFlags.None) + Await AddTypeLinkAsync(fieldSymbol.Type, LinkFlags.None, cancellationToken).ConfigureAwait(True) If fieldSymbol.HasConstantValue Then AddText(" = ") @@ -239,9 +257,12 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ObjectBrowser AddText(fieldSymbol.ConstantValue.ToString()) End If End If - End Sub + End Function - Protected Overrides Sub BuildPropertyDeclaration(propertySymbol As IPropertySymbol, options As _VSOBJDESCOPTIONS) + Protected Overrides Async Function BuildPropertyDeclarationAsync( + propertySymbol As IPropertySymbol, + options As _VSOBJDESCOPTIONS, + cancellationToken As CancellationToken) As Task BuildMemberModifiers(propertySymbol) If propertySymbol.GetMethod IsNot Nothing Then @@ -258,15 +279,18 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ObjectBrowser If propertySymbol.Parameters.Length > 0 Then AddText("(") - BuildParameterList(propertySymbol.Parameters) + Await BuildParameterListAsync(propertySymbol.Parameters, cancellationToken).ConfigureAwait(True) AddText(")") End If AddText(" As ") - AddTypeLink(propertySymbol.Type, LinkFlags.None) - End Sub + Await AddTypeLinkAsync(propertySymbol.Type, LinkFlags.None, cancellationToken).ConfigureAwait(True) + End Function - Protected Overrides Sub BuildEventDeclaration(eventSymbol As IEventSymbol, options As _VSOBJDESCOPTIONS) + Protected Overrides Async Function BuildEventDeclarationAsync( + eventSymbol As IEventSymbol, + options As _VSOBJDESCOPTIONS, + cancellationToken As CancellationToken) As Task BuildMemberModifiers(eventSymbol) AddText("Event ") @@ -279,12 +303,12 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ObjectBrowser If eventType IsNot Nothing AndAlso eventType.TypeKind = TypeKind.Delegate Then Dim delegateInvokeMethod = CType(eventType, INamedTypeSymbol).DelegateInvokeMethod If delegateInvokeMethod IsNot Nothing Then - BuildParameterList(delegateInvokeMethod.Parameters) + Await BuildParameterListAsync(delegateInvokeMethod.Parameters, cancellationToken).ConfigureAwait(True) End If End If AddText(")") - End Sub + End Function Private Sub BuildAccessibility(symbol As ISymbol) Select Case symbol.DeclaredAccessibility @@ -369,7 +393,9 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ObjectBrowser End If End Sub - Private Sub BuildParameterList(parameters As ImmutableArray(Of IParameterSymbol)) + Private Async Function BuildParameterListAsync( + parameters As ImmutableArray(Of IParameterSymbol), + cancellationToken As CancellationToken) As Task Dim count = parameters.Length If count = 0 Then Return @@ -399,7 +425,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ObjectBrowser AddParam(current.Name) AddText(" As ") - AddTypeLink(current.Type, LinkFlags.None) + Await AddTypeLinkAsync(current.Type, LinkFlags.None, cancellationToken).ConfigureAwait(True) If current.HasExplicitDefaultValue Then AddText(" = ") @@ -410,9 +436,11 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ObjectBrowser End If End If Next - End Sub + End Function - Private Sub BuildTypeParameterList(typeParameters As ImmutableArray(Of ITypeParameterSymbol)) + Private Async Function BuildTypeParameterListAsync( + typeParameters As ImmutableArray(Of ITypeParameterSymbol), + cancellationToken As CancellationToken) As Task Dim count = typeParameters.Length If count = 0 Then Return @@ -426,24 +454,28 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ObjectBrowser Dim current = typeParameters(i) AddName(current.Name) - AddConstraints(current) + Await AddConstraintsAsync(current, cancellationToken).ConfigureAwait(True) Next - End Sub + End Function - Private Sub AddConstraints(typeParameter As ITypeParameterSymbol) + Private Async Function AddConstraintsAsync( + typeParameter As ITypeParameterSymbol, + cancellationToken As CancellationToken) As Task Dim count = CountConstraints(typeParameter) If count = 0 Then Return End If If count = 1 Then - AddSingleConstraint(typeParameter) + Await AddSingleConstraintAsync(typeParameter, cancellationToken).ConfigureAwait(True) Else - AddMultipleConstraints(typeParameter) + Await AddMultipleConstraintsAsync(typeParameter, cancellationToken).ConfigureAwait(True) End If - End Sub + End Function - Private Sub AddSingleConstraint(typeParameter As ITypeParameterSymbol) + Private Async Function AddSingleConstraintAsync( + typeParameter As ITypeParameterSymbol, + cancellationToken As CancellationToken) As Task AddName(" As ") If typeParameter.HasReferenceTypeConstraint Then @@ -454,11 +486,13 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ObjectBrowser AddName("New") Else Debug.Assert(typeParameter.ConstraintTypes.Length = 1) - AddTypeLink(typeParameter.ConstraintTypes(0), LinkFlags.None) + Await AddTypeLinkAsync(typeParameter.ConstraintTypes(0), LinkFlags.None, cancellationToken).ConfigureAwait(True) End If - End Sub + End Function - Private Sub AddMultipleConstraints(typeParameter As ITypeParameterSymbol) + Private Async Function AddMultipleConstraintsAsync( + typeParameter As ITypeParameterSymbol, + cancellationToken As CancellationToken) As Task AddName(" As {") Dim constraintAdded = False @@ -492,13 +526,13 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ObjectBrowser AddName(", ") End If - AddTypeLink(constraintType, LinkFlags.None) + Await AddTypeLinkAsync(constraintType, LinkFlags.None, cancellationToken).ConfigureAwait(True) constraintAdded = True Next End If AddName("}") - End Sub + End Function Private Shared Function CountConstraints(typeParameter As ITypeParameterSymbol) As Integer Dim result = typeParameter.ConstraintTypes.Length