static string GetContextName(RoslynReflectionAllowedContext context) { switch (context) { case RoslynReflectionAllowedContext.Analyzers: return("analyzers"); case RoslynReflectionAllowedContext.CodeFixes: return("code fixes/refactorings"); } return(""); }
static RoslynReflectionAllowedContext GetContextFromClass(INamedTypeSymbol symbol) { RoslynReflectionAllowedContext surroundingContext = RoslynReflectionAllowedContext.None; var surroundingClassAttributes = symbol.GetAttributes(); if (surroundingClassAttributes.Any(a => a.AttributeClass.GetFullName() == typeof(DiagnosticAnalyzerAttribute).FullName)) { surroundingContext = RoslynReflectionAllowedContext.Analyzers; } else if (surroundingClassAttributes.Any(a => a.AttributeClass.GetFullName() == typeof(ExportCodeFixProviderAttribute).FullName)) { surroundingContext = RoslynReflectionAllowedContext.CodeFixes; } else if (surroundingClassAttributes.Any(a => a.AttributeClass.GetFullName() == typeof(ExportCodeRefactoringProviderAttribute).FullName)) { surroundingContext = RoslynReflectionAllowedContext.CodeFixes; } return(surroundingContext); }
public RoslynReflectionUsageAttribute(RoslynReflectionAllowedContext allowedContexts = RoslynReflectionAllowedContext.None) { AllowedContexts = allowedContexts; }
static bool TryGetDiagnostic(SyntaxNodeAnalysisContext nodeContext, out Diagnostic diagnostic) { diagnostic = default(Diagnostic); var semanticModel = nodeContext.SemanticModel; var node = nodeContext.Node as MemberAccessExpressionSyntax; var symbol = semanticModel.GetSymbolInfo(node.Name).Symbol; if (symbol == null) { return(false); } RoslynReflectionAllowedContext surroundingContext = RoslynReflectionAllowedContext.None; var surroundingClass = node.Ancestors().OfType <ClassDeclarationSyntax>().FirstOrDefault(); if (surroundingClass == null) { return(false); } var surroundingClassSymbol = semanticModel.GetDeclaredSymbol(surroundingClass); if (surroundingClassSymbol == null) { return(false); } surroundingContext = GetContextFromClass(surroundingClassSymbol); if (surroundingContext == RoslynReflectionAllowedContext.None) { return(false); } var reflectionUsageAttributeData = symbol.GetAttributes().FirstOrDefault(a => a.AttributeClass.GetFullName() == typeof(RoslynReflectionUsageAttribute).FullName); if (reflectionUsageAttributeData == null) { var containingTypeSymbol = symbol.ContainingType; if (containingTypeSymbol != null) { reflectionUsageAttributeData = containingTypeSymbol.GetAttributes().FirstOrDefault(a => a.AttributeClass.GetFullName() == typeof(RoslynReflectionUsageAttribute).FullName); } } string diagnosticMessage = ""; RoslynReflectionAllowedContext allowedContext = RoslynReflectionAllowedContext.None; if (reflectionUsageAttributeData != null) { var attributeParam = reflectionUsageAttributeData.ConstructorArguments.FirstOrDefault(); if (attributeParam.Value is int) { allowedContext = (RoslynReflectionAllowedContext)attributeParam.Value; } diagnosticMessage = "This call accesses Roslyn features through reflection, although not allowed in {0}."; } else { if (surroundingContext == RoslynReflectionAllowedContext.Analyzers) { var symbolContainingType = symbol.ContainingType; if (symbolContainingType != null) { allowedContext = GetContextFromClass(symbolContainingType); } } else { allowedContext = RoslynReflectionAllowedContext.Analyzers | RoslynReflectionAllowedContext.CodeFixes; } diagnosticMessage = "Accessing members from code fixes/refactorings is not allowed in {0}."; } if ((allowedContext == RoslynReflectionAllowedContext.None) || (allowedContext.HasFlag(surroundingContext))) { return(false); } diagnostic = Diagnostic.Create( descriptor, node.Name.GetLocation(), string.Format(diagnosticMessage, GetContextName(surroundingContext)) ); return(true); }
static string GetContextName(RoslynReflectionAllowedContext context) { switch (context) { case RoslynReflectionAllowedContext.Analyzers: return "analyzers"; case RoslynReflectionAllowedContext.CodeFixes: return "code fixes/refactorings"; } return ""; }