private void AnalyzeSymbol(SymbolAnalysisContext symbolContext, IEnumerable <INamedTypeSymbol> exportAttributes)
        {
            var namedType           = (INamedTypeSymbol)symbolContext.Symbol;
            var namedTypeAttributes = AttributeHelpers.GetApplicableAttributes(namedType);

            // Figure out which export attributes are being used here
            var appliedExportAttributes = exportAttributes.Where(e => namedTypeAttributes.Any(ad => AttributeHelpers.DerivesFrom(ad.AttributeClass, e))).ToList();

            // If we have no exports we're done
            if (appliedExportAttributes.Count == 0)
            {
                return;
            }

            var badNamespaces = exportAttributes.Except(appliedExportAttributes).Select(s => s.ContainingNamespace).ToList();

            // Now look at all attributes and see if any are metadata attributes
            foreach (var namedTypeAttribute in namedTypeAttributes)
            {
                if (AttributeHelpers.GetApplicableAttributes(namedTypeAttribute.AttributeClass).Any(ad => badNamespaces.Contains(ad.AttributeClass.ContainingNamespace) &&
                                                                                                    ad.AttributeClass.Name == "MetadataAttributeAttribute"))
                {
                    ReportDiagnostic(symbolContext, namedType, namedTypeAttribute);
                }
            }

            // Also look through all members and their attributes, and see if any are using from bad places
            foreach (var member in namedType.GetMembers())
            {
                foreach (var attribute in member.GetAttributes())
                {
                    if (badNamespaces.Contains(attribute.AttributeClass.ContainingNamespace))
                    {
                        ReportDiagnostic(symbolContext, namedType, attribute);
                    }
                }

                // if it's a constructor, we should also check parameters since they may have [ImportMany]
                var methodSymbol = member as IMethodSymbol;

                if (methodSymbol != null && methodSymbol.MethodKind == MethodKind.Constructor)
                {
                    foreach (var parameter in methodSymbol.Parameters)
                    {
                        foreach (var attribute in parameter.GetAttributes())
                        {
                            if (badNamespaces.Contains(attribute.AttributeClass.ContainingNamespace))
                            {
                                ReportDiagnostic(symbolContext, namedType, attribute);
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 2
0
            protected bool HasDiagnosticAnalyzerAttribute(INamedTypeSymbol namedType)
            {
                foreach (var attribute in AttributeHelpers.GetApplicableAttributes(namedType))
                {
                    if (AttributeHelpers.DerivesFrom(attribute.AttributeClass, DiagnosticAnalyzerAttribute))
                    {
                        return(true);
                    }
                }

                return(false);
            }
        private void AnalyzeSymbol(SymbolAnalysisContext symbolContext, INamedTypeSymbol exportAttribute)
        {
            var namedType           = (INamedTypeSymbol)symbolContext.Symbol;
            var namedTypeAttributes = AttributeHelpers.GetApplicableAttributes(namedType);

            var exportAttributeApplication = namedTypeAttributes.FirstOrDefault(ad => AttributeHelpers.DerivesFrom(ad.AttributeClass, exportAttribute));

            if (exportAttributeApplication != null)
            {
                if (!namedTypeAttributes.Any(ad => ad.AttributeClass.Name == "SharedAttribute" &&
                                             ad.AttributeClass.ContainingNamespace.Equals(exportAttribute.ContainingNamespace)))
                {
                    symbolContext.ReportDiagnostic(Diagnostic.Create(Rule, exportAttributeApplication.ApplicationSyntaxReference.GetSyntax().GetLocation()));
                }
            }
        }
            protected override void AnalyzeDiagnosticAnalyzer(SymbolAnalysisContext symbolContext)
            {
                var namedType = (INamedTypeSymbol)symbolContext.Symbol;

                if (namedType.IsAbstract)
                {
                    return;
                }

                // 1) MissingDiagnosticAnalyzerAttributeRule: DiagnosticAnalyzer has no DiagnosticAnalyzerAttribute.
                // 2) AddLanguageSupportToAnalyzerRule: For analyzer supporting only one of C# or VB languages, detect if it can support the other language.

                var        hasAttribute    = false;
                SyntaxNode attributeSyntax = null;
                bool       supportsCSharp  = false;
                bool       supportsVB      = false;

                var namedTypeAttributes = AttributeHelpers.GetApplicableAttributes(namedType);

                foreach (var attribute in namedTypeAttributes)
                {
                    if (AttributeHelpers.DerivesFrom(attribute.AttributeClass, DiagnosticAnalyzerAttribute))
                    {
                        hasAttribute = true;

                        // The attribute constructor's signature is "(string, params string[])",
                        // so process both string arguments and string[] arguments.
                        foreach (TypedConstant arg in attribute.ConstructorArguments)
                        {
                            CheckLanguage(arg, ref supportsCSharp, ref supportsVB);

                            if (arg.Kind == TypedConstantKind.Array)
                            {
                                foreach (TypedConstant element in arg.Values)
                                {
                                    CheckLanguage(element, ref supportsCSharp, ref supportsVB);
                                }
                            }
                        }

                        attributeSyntax = attribute.ApplicationSyntaxReference.GetSyntax(symbolContext.CancellationToken);
                    }
                }

                if (!hasAttribute)
                {
                    var diagnostic = Diagnostic.Create(MissingDiagnosticAnalyzerAttributeRule, namedType.Locations[0]);
                    symbolContext.ReportDiagnostic(diagnostic);
                }
                else if (supportsCSharp ^ supportsVB)
                {
                    Debug.Assert(attributeSyntax != null);

                    // If the analyzer assembly doesn't reference either C# or VB CodeAnalysis assemblies,
                    // then the analyzer is pretty likely a language-agnostic analyzer.
                    var compilation = symbolContext.Compilation;
                    var compilationTypeNameToCheck = supportsCSharp ? s_csharpCompilationFullName : s_basicCompilationFullName;
                    var compilationType            = compilation.GetTypeByMetadataName(compilationTypeNameToCheck);
                    if (compilationType == null)
                    {
                        var missingLanguage = supportsCSharp ? LanguageNames.VisualBasic : LanguageNames.CSharp;
                        var diagnostic      = Diagnostic.Create(AddLanguageSupportToAnalyzerRule, attributeSyntax.GetLocation(), namedType.Name, missingLanguage);
                        symbolContext.ReportDiagnostic(diagnostic);
                    }
                }
            }
Exemplo n.º 5
0
            protected override void AnalyzeDiagnosticAnalyzer(SymbolAnalysisContext symbolContext)
            {
                var namedType = (INamedTypeSymbol)symbolContext.Symbol;

                if (namedType.IsAbstract)
                {
                    return;
                }

                // 1) MissingDiagnosticAnalyzerAttributeRule: DiagnosticAnalyzer has no DiagnosticAnalyzerAttribute.
                // 2) AddLanguageSupportToAnalyzerRule: For analyzer supporting only one of C# or VB languages, detect if it can support the other language.

                var        hasAttribute          = false;
                var        hasMultipleAttributes = false;
                SyntaxNode attributeSyntax       = null;
                string     supportedLanguage     = null;

                var namedTypeAttributes = AttributeHelpers.GetApplicableAttributes(namedType);

                foreach (var attribute in namedTypeAttributes)
                {
                    if (AttributeHelpers.DerivesFrom(attribute.AttributeClass, DiagnosticAnalyzerAttribute))
                    {
                        hasMultipleAttributes |= hasAttribute;
                        hasAttribute           = true;

                        if (!hasMultipleAttributes)
                        {
                            foreach (var arg in attribute.ConstructorArguments)
                            {
                                if (arg.Kind == TypedConstantKind.Primitive &&
                                    arg.Type != null &&
                                    arg.Type.SpecialType == SpecialType.System_String)
                                {
                                    supportedLanguage = (string)arg.Value;
                                    attributeSyntax   = attribute.ApplicationSyntaxReference.GetSyntax(symbolContext.CancellationToken);
                                }
                            }
                        }
                    }
                }

                if (!hasAttribute)
                {
                    var diagnostic = Diagnostic.Create(MissingDiagnosticAnalyzerAttributeRule, namedType.Locations[0]);
                    symbolContext.ReportDiagnostic(diagnostic);
                }
                else if (!hasMultipleAttributes && supportedLanguage != null)
                {
                    Debug.Assert(attributeSyntax != null);

                    var supportsCSharp = supportedLanguage == LanguageNames.CSharp;
                    var supportsVB     = supportedLanguage == LanguageNames.VisualBasic;
                    if (supportsCSharp || supportsVB)
                    {
                        // If the analyzer assembly doesn't reference either C# or VB CodeAnalysis assemblies,
                        // then the analyzer is pretty likely a language-agnostic analyzer.
                        var compilation = symbolContext.Compilation;
                        var compilationTypeNameToCheck = supportsCSharp ? csharpCompilationFullName : basicCompilationFullName;
                        var compilationType            = compilation.GetTypeByMetadataName(compilationTypeNameToCheck);
                        if (compilationType == null)
                        {
                            var missingLanguage = supportsCSharp ? LanguageNames.VisualBasic : LanguageNames.CSharp;
                            var diagnostic      = Diagnostic.Create(AddLanguageSupportToAnalyzerRule, attributeSyntax.GetLocation(), namedType.Name, missingLanguage);
                            symbolContext.ReportDiagnostic(diagnostic);
                        }
                    }
                }
            }