in src/Microsoft.VisualStudio.SDK.Analyzers/VSSDK003SupportAsyncToolWindowAnalyzer.cs [72:122]
private void AnalyzeClassDeclaration(SyntaxNodeAnalysisContext context, INamedTypeSymbol asyncPackageType, INamedTypeSymbol provideToolWindowAttributeType)
{
var declaration = (ClassDeclarationSyntax)context.Node;
BaseTypeSyntax? baseType = declaration.BaseList?.Types.FirstOrDefault();
if (baseType == null)
{
return;
}
var baseTypeSymbol = context.SemanticModel.GetSymbolInfo(baseType.Type, context.CancellationToken).Symbol?.OriginalDefinition as ITypeSymbol;
if (!Utils.IsEqualToOrDerivedFrom(baseTypeSymbol, asyncPackageType))
{
return;
}
INamedTypeSymbol userClassSymbol = context.SemanticModel.GetDeclaredSymbol(declaration, context.CancellationToken);
AttributeData? packageRegistrationInstance = userClassSymbol?.GetAttributes().FirstOrDefault(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, provideToolWindowAttributeType));
TypedConstant? firstParameter = packageRegistrationInstance?.ConstructorArguments.FirstOrDefault();
if (firstParameter.HasValue && firstParameter.Value.Kind == TypedConstantKind.Type && firstParameter.Value.Value is INamedTypeSymbol typeOfUserToolWindow)
{
// If the tool window has a constructor that takes a parameter,
// then the tool window is probably created asynchronously, because you
// cannot easily pass a parameter when creating a synchronous tool window.
bool toolWindowHasCtorWithOneParameter = typeOfUserToolWindow.GetMembers(ConstructorInfo.ConstructorName).OfType<IMethodSymbol>().Any(c => c.Parameters.Length == 1);
if (toolWindowHasCtorWithOneParameter)
{
return;
}
// If the `GetAsyncToolWindowFactory` method has been overridden,
// then it's highly likely that the tool window will be created asynchronously.
var packageSymbol = context.SemanticModel.GetDeclaredSymbol(declaration, context.CancellationToken)?.OriginalDefinition as ITypeSymbol;
if (this.IsGetAsyncToolWindowFactoryOverridden(packageSymbol, asyncPackageType))
{
return;
}
if (packageRegistrationInstance!.ApplicationSyntaxReference?.GetSyntax(context.CancellationToken) is AttributeSyntax attributeSyntax)
{
AttributeArgumentSyntax firstArgumentSyntax = attributeSyntax.ArgumentList.Arguments.First();
Location diagnosticLocation = firstArgumentSyntax.GetLocation();
if (firstArgumentSyntax.Expression is TypeOfExpressionSyntax typeOfArg)
{
diagnosticLocation = typeOfArg.Type.GetLocation();
}
context.ReportDiagnostic(Diagnostic.Create(Descriptor, diagnosticLocation));
}
}
}