Example #1
0
        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));
                }
            }
        }
        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)
            {
                bool toolWindowHasCtorWithOneParameter = typeOfUserToolWindow.GetMembers(ConstructorInfo.ConstructorName).OfType <IMethodSymbol>().Any(c => c.Parameters.Length == 1);
                if (!toolWindowHasCtorWithOneParameter)
                {
                    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));
                    }
                }
            }
        }