Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/xunit.analyzers/PublicMethodShouldBeMarkedAsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ internal override void AnalyzeCompilation(CompilationStartAnalysisContext compil
var type = (INamedTypeSymbol)symbolContext.Symbol;

if (type.TypeKind != TypeKind.Class ||
type.DeclaredAccessibility != Accessibility.Public)
type.DeclaredAccessibility != Accessibility.Public ||
type.IsAbstract)
return;

var methodsToIgnore = interfacesToIgnore.Where(i => i != null && type.AllInterfaces.Contains(i))
Expand All @@ -42,7 +43,11 @@ internal override void AnalyzeCompilation(CompilationStartAnalysisContext compil
symbolContext.CancellationToken.ThrowIfCancellationRequested();

var method = (IMethodSymbol)member;
if (method.MethodKind != MethodKind.Ordinary)
// Check for method.IsAbstract and earlier for type.IsAbstract is done
// twice to enable better diagnostics during code editing. It is useful with
// incomplete code for abstract types - missing abstract keyword on type
// or on abstract method
if (method.MethodKind != MethodKind.Ordinary || method.IsAbstract)
continue;

var isTestMethod = method.GetAttributes().ContainsAttributeType(xunitContext.FactAttributeType);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.CodeAnalysis;
using System;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;

namespace Xunit.Analyzers
Expand Down Expand Up @@ -37,6 +38,29 @@ public void Dispose() { }
Assert.Empty(diagnostics);
}

[Fact]
public async void DoesNotFindErrorForPublicAbstractMethod()
{
var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer,
@"public abstract class TestClass {
[Xunit.Fact] public void TestMethod() { }
public abstract void AbstractMethod();
}");

Assert.Empty(diagnostics);
}

Copy link
Contributor

@jamesqo jamesqo Sep 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to also add this test:

        [Fact]
        public async void DoesNotFindErrorForPublicAbstractMethodMarkedWithFact()
        {
            var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer,
@"public abstract class TestClass {
    [Xunit.Fact] public void TestMethod() { }
    [Xunit.Fact] public abstract void AbstractTestMethod();
}");
            Assert.Empty(diagnostics);
        }

I can't test right now but that should work fine at runtime, since the [Fact] attribute is inherited on overriding members.

Copy link
Contributor Author

@4creators 4creators Oct 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK it makes sense

[Fact]
public async void DoesNotFindErrorForPublicAbstractMethodMarkedWithFact()
{
var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer,
@"public abstract class TestClass {
[Xunit.Fact] public void TestMethod() { }
[Xunit.Fact] public abstract void AbstractMethod();
}");
Assert.Empty(diagnostics);
}

[Fact]
public async void DoesNotFindErrorForIDisposableDisposeMethodOverrideFromParentClass()
{
Expand Down