private static bool TryLoadNUnitTypes( Compilation compilation, out NUnitTypes types ) { ImmutableHashSet <INamedTypeSymbol> testAttributes = ImmutableHashSet .Create( compilation.GetTypeByMetadataName("NUnit.Framework.TestAttribute"), compilation.GetTypeByMetadataName("NUnit.Framework.TestCaseAttribute"), compilation.GetTypeByMetadataName("NUnit.Framework.TestCaseSourceAttribute"), compilation.GetTypeByMetadataName("NUnit.Framework.TheoryAttribute") ); ImmutableHashSet <INamedTypeSymbol> setupTeardownAttributes = ImmutableHashSet .Create( compilation.GetTypeByMetadataName("NUnit.Framework.SetUpAttribute"), compilation.GetTypeByMetadataName("NUnit.Framework.OneTimeSetUpAttribute"), compilation.GetTypeByMetadataName("NUnit.Framework.TearDownAttribute"), compilation.GetTypeByMetadataName("NUnit.Framework.OneTimeTearDownAttribute") ); INamedTypeSymbol testFixtureAttribute = compilation.GetTypeByMetadataName("NUnit.Framework.TestFixtureAttribute"); types = new NUnitTypes(testAttributes, setupTeardownAttributes, testFixtureAttribute); return(true); }
private static bool TryLoadNUnitTypes( Compilation compilation, out NUnitTypes types ) { INamedTypeSymbol categoryAttribute = compilation.GetTypeByMetadataName("NUnit.Framework.CategoryAttribute"); if (categoryAttribute == null || categoryAttribute.TypeKind == TypeKind.Error) { types = null; return(false); } ImmutableHashSet <INamedTypeSymbol> testAttributes = ImmutableHashSet .Create( compilation.GetTypeByMetadataName("NUnit.Framework.TestAttribute"), compilation.GetTypeByMetadataName("NUnit.Framework.TestCaseAttribute"), compilation.GetTypeByMetadataName("NUnit.Framework.TestCaseSourceAttribute"), compilation.GetTypeByMetadataName("NUnit.Framework.TheoryAttribute") ); INamedTypeSymbol testFixtureAttribute = compilation.GetTypeByMetadataName("NUnit.Framework.TestFixtureAttribute"); types = new NUnitTypes(categoryAttribute, testAttributes, testFixtureAttribute); return(true); }
private static void AnalyzeMethod( SyntaxNodeAnalysisContext context, NUnitTypes types, MethodDeclarationSyntax syntax ) { SemanticModel model = context.SemanticModel; IMethodSymbol method = model.GetDeclaredSymbol(syntax, context.CancellationToken); if (method == null) { return; } if (!IsTestMethod(types, method)) { return; } ImmutableSortedSet <string> categories = GatherTestMethodCategories(types, method); if (categories.Overlaps(RequiredCategories)) { return; } context.ReportDiagnostic(Diagnostic.Create( Diagnostics.NUnitCategory, syntax.Identifier.GetLocation(), $"Test must be categorized as one of [{string.Join( ", ", RequiredCategories )}], but saw [{string.Join( ", ", categories )}]. See http://docs.dev.d2l/index.php/Test_Categories." )); }
private static void VisitCategories( NUnitTypes types, ISymbol symbol, Action <string, AttributeData> visitor ) { foreach (AttributeData attribute in symbol.GetAttributes()) { INamedTypeSymbol attributeType = attribute.AttributeClass; if (types.CategoryAttribute == attributeType) { VisitCategoryAttribute(attribute, visitor); continue; } if (types.TestFixtureAttribute == attributeType) { VisitTestFixtureAttribute(attribute, visitor); continue; } } if (symbol is INamedTypeSymbol typeSymbol) { if (typeSymbol.BaseType != null) { VisitCategories(types, typeSymbol.BaseType, visitor); } } }
private static ImmutableSortedSet <string> GetCategories( NUnitTypes types, ISymbol symbol ) { var categories = ImmutableSortedSet.CreateBuilder <string>(StringComparer.OrdinalIgnoreCase); VisitCategories(types, symbol, (category, _) => categories.Add(category)); return(categories.ToImmutable()); }
private static void AnalyzeMethod( SyntaxNodeAnalysisContext context, NUnitTypes types, MethodDeclarationSyntax syntax ) { SemanticModel model = context.SemanticModel; IMethodSymbol method = model.GetDeclaredSymbol(syntax, context.CancellationToken); if (method == null) { return; } // Any private/helper methods should be private/internal and can be ignored if (method.DeclaredAccessibility != Accessibility.Public) { return; } ImmutableSortedSet <string> categories = GatherTestMethodCategories(types, method); if (!categories.Overlaps(RequiredCategories)) { context.ReportDiagnostic(Diagnostic.Create( Diagnostics.NUnitCategory, syntax.Identifier.GetLocation(), $"Test must be categorized as one of [{string.Join( ", ", RequiredCategories )}], but saw [{string.Join( ", ", categories )}]. See http://docs.dev.d2l/index.php/Test_Categories." )); } // We need the declaring class to be a [TestFixture] to continue INamedTypeSymbol declaringClass = method.ContainingType; if (!declaringClass.GetAttributes().Any(attr => attr.AttributeClass == types.TestFixtureAttribute)) { return; } // If we don't have a Test type attribute on the method, report a diagnostic bool isTest = IsTestMethod(types, method); if (!isTest) { context.ReportDiagnostic(Diagnostic.Create( Diagnostics.TestAttributeMissed, syntax.Identifier.GetLocation(), method.Name) ); return; } }
private static void AnalyzeMethod( SyntaxNodeAnalysisContext context, NUnitTypes types, MethodDeclarationSyntax syntax, ImmutableHashSet <string> disallowedList ) { SemanticModel model = context.SemanticModel; IMethodSymbol method = model.GetDeclaredSymbol(syntax, context.CancellationToken); if (method == null) { return; } // Any private/helper methods should be private/internal and can be ignored if (method.DeclaredAccessibility != Accessibility.Public) { return; } // We need the declaring class to be a [TestFixture] to continue INamedTypeSymbol declaringClass = method.ContainingType; if (!declaringClass.GetAttributes().Any( attr => attr.AttributeClass.Equals(types.TestFixtureAttribute, SymbolEqualityComparer.Default) )) { return; } // Ignore any classes which are disallowed if (IsClassAllowed(disallowedList, method.ContainingType)) { return; } bool isTest = IsTestMethod(types, method); if (!isTest) { context.ReportDiagnostic(Diagnostic.Create( Diagnostics.TestAttributeMissed, syntax.Identifier.GetLocation(), method.Name) ); return; } }
private static bool IsTestMethod( NUnitTypes types, IMethodSymbol method ) { foreach (AttributeData attribute in method.GetAttributes()) { INamedTypeSymbol attributeType = attribute.AttributeClass; if (types.TestAttributes.Contains(attributeType) || types.SetupTeardownAttributes.Contains(attributeType)) { return(true); } } return(false); }
private static ImmutableSortedSet <string> GatherTestMethodCategories( NUnitTypes types, IMethodSymbol method ) { ImmutableSortedSet <string> methodCategories = GetCategories(types, method); ImmutableSortedSet <string> fixtureCategories = GetCategories(types, method.ContainingType); ImmutableSortedSet <string> assemblyCategories = GetCategories(types, method.ContainingAssembly); ImmutableSortedSet <string> categories = methodCategories .Union(fixtureCategories) .Union(assemblyCategories); return(categories); }