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, 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); } } } } } }
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); } } }
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; 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); } } } }