diff --git a/src/Analyzer.Legacy/Analyzer.Legacy.csproj b/src/Analyzer.Legacy/Analyzer.Legacy.csproj
index 5aa6262..d333184 100644
--- a/src/Analyzer.Legacy/Analyzer.Legacy.csproj
+++ b/src/Analyzer.Legacy/Analyzer.Legacy.csproj
@@ -54,7 +54,7 @@
-
+
diff --git a/src/Analyzer.Tests/EventSources/LogFieldAndPropertyDoNotExistEventSource.cs b/src/Analyzer.Tests/EventSources/LogFieldAndPropertyDoNotExistEventSource.cs
new file mode 100644
index 0000000..5f7caad
--- /dev/null
+++ b/src/Analyzer.Tests/EventSources/LogFieldAndPropertyDoNotExistEventSource.cs
@@ -0,0 +1,10 @@
+using System.Diagnostics.Tracing;
+
+namespace Thor.Analyzer.Tests.EventSources
+{
+ [EventSource(Name = "LogFieldAndPropertyDoesNotExist")]
+ public sealed class LogFieldAndPropertyDoNotExistEventSource
+ : EventSource
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Analyzer.Tests/EventSources/LogFieldDoesNotExistEventSource.cs b/src/Analyzer.Tests/EventSources/LogFieldDoesNotExistEventSource.cs
deleted file mode 100644
index bf65102..0000000
--- a/src/Analyzer.Tests/EventSources/LogFieldDoesNotExistEventSource.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System.Diagnostics.Tracing;
-
-namespace Thor.Analyzer.Tests.EventSources
-{
- [EventSource(Name = "LogFieldDoesNotExist")]
- public sealed class LogFieldDoesNotExistEventSource
- : EventSource
- {
- }
-}
\ No newline at end of file
diff --git a/src/Analyzer.Tests/EventSources/LogFieldDoesNotHaveValueEventSource.cs b/src/Analyzer.Tests/EventSources/LogFieldDoesNotHaveValueEventSource.cs
deleted file mode 100644
index a7e243f..0000000
--- a/src/Analyzer.Tests/EventSources/LogFieldDoesNotHaveValueEventSource.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System.Diagnostics.Tracing;
-
-namespace Thor.Analyzer.Tests.EventSources
-{
- [EventSource(Name = "LogFieldDoesNotHaveValue")]
- public sealed class LogFieldDoesNotHaveValueEventSource
- : EventSource
- {
- public static readonly LogFieldDoesNotHaveValueEventSource Log;
- }
-}
\ No newline at end of file
diff --git a/src/Analyzer.Tests/EventSources/LogFieldNullEventSource.cs b/src/Analyzer.Tests/EventSources/LogFieldNullEventSource.cs
new file mode 100644
index 0000000..3b24784
--- /dev/null
+++ b/src/Analyzer.Tests/EventSources/LogFieldNullEventSource.cs
@@ -0,0 +1,11 @@
+using System.Diagnostics.Tracing;
+
+namespace Thor.Analyzer.Tests.EventSources
+{
+ [EventSource(Name = "LogFieldNull")]
+ public sealed class LogFieldNullEventSource
+ : EventSource
+ {
+ public static readonly LogFieldNullEventSource Log;
+ }
+}
\ No newline at end of file
diff --git a/src/Analyzer.Tests/EventSources/LogPropertyEventSource.cs b/src/Analyzer.Tests/EventSources/LogPropertyEventSource.cs
new file mode 100644
index 0000000..2d66726
--- /dev/null
+++ b/src/Analyzer.Tests/EventSources/LogPropertyEventSource.cs
@@ -0,0 +1,11 @@
+using System.Diagnostics.Tracing;
+
+namespace Thor.Analyzer.Tests.EventSources
+{
+ [EventSource(Name = "LogProperty")]
+ public sealed class LogPropertyEventSource
+ : EventSource
+ {
+ public static LogPropertyEventSource Log { get; } = new LogPropertyEventSource();
+ }
+}
\ No newline at end of file
diff --git a/src/Analyzer.Tests/EventSources/LogPropertyNotPublicEventSource.cs b/src/Analyzer.Tests/EventSources/LogPropertyNotPublicEventSource.cs
new file mode 100644
index 0000000..f5dc1bc
--- /dev/null
+++ b/src/Analyzer.Tests/EventSources/LogPropertyNotPublicEventSource.cs
@@ -0,0 +1,12 @@
+using System.Diagnostics.Tracing;
+
+namespace Thor.Analyzer.Tests.EventSources
+{
+ [EventSource(Name = "LogPropertyNotPublic")]
+ public sealed class LogPropertyNotPublicEventSource
+ : EventSource
+ {
+ internal static LogPropertyNotPublicEventSource Log { get; } =
+ new LogPropertyNotPublicEventSource();
+ }
+}
\ No newline at end of file
diff --git a/src/Analyzer.Tests/EventSources/LogPropertyNotReadOnlyEventSource.cs b/src/Analyzer.Tests/EventSources/LogPropertyNotReadOnlyEventSource.cs
new file mode 100644
index 0000000..edf47a6
--- /dev/null
+++ b/src/Analyzer.Tests/EventSources/LogPropertyNotReadOnlyEventSource.cs
@@ -0,0 +1,12 @@
+using System.Diagnostics.Tracing;
+
+namespace Thor.Analyzer.Tests.EventSources
+{
+ [EventSource(Name = "LogPropertyNotReadOnly")]
+ public sealed class LogPropertyNotReadOnlyEventSource
+ : EventSource
+ {
+ public static LogPropertyNotReadOnlyEventSource Log { get; set; } =
+ new LogPropertyNotReadOnlyEventSource();
+ }
+}
\ No newline at end of file
diff --git a/src/Analyzer.Tests/EventSources/LogPropertyNotStaticEventSource.cs b/src/Analyzer.Tests/EventSources/LogPropertyNotStaticEventSource.cs
new file mode 100644
index 0000000..7d2cc5e
--- /dev/null
+++ b/src/Analyzer.Tests/EventSources/LogPropertyNotStaticEventSource.cs
@@ -0,0 +1,12 @@
+using System.Diagnostics.Tracing;
+
+namespace Thor.Analyzer.Tests.EventSources
+{
+ [EventSource(Name = "LogPropertyNotStatic")]
+ public sealed class LogPropertyNotStaticEventSource
+ : EventSource
+ {
+ public LogPropertyNotStaticEventSource Log { get; } =
+ new LogPropertyNotStaticEventSource();
+ }
+}
\ No newline at end of file
diff --git a/src/Analyzer.Tests/EventSources/LogPropertyNullEventSource.cs b/src/Analyzer.Tests/EventSources/LogPropertyNullEventSource.cs
new file mode 100644
index 0000000..0623efe
--- /dev/null
+++ b/src/Analyzer.Tests/EventSources/LogPropertyNullEventSource.cs
@@ -0,0 +1,11 @@
+using System.Diagnostics.Tracing;
+
+namespace Thor.Analyzer.Tests.EventSources
+{
+ [EventSource(Name = "LogPropertyNull")]
+ public sealed class LogPropertyNullEventSource
+ : EventSource
+ {
+ public static LogPropertyNullEventSource Log { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/Analyzer.Tests/Rules/MustHaveStaticLogFieldOrPropertyTests.cs b/src/Analyzer.Tests/Rules/MustHaveStaticLogFieldOrPropertyTests.cs
new file mode 100644
index 0000000..1330569
--- /dev/null
+++ b/src/Analyzer.Tests/Rules/MustHaveStaticLogFieldOrPropertyTests.cs
@@ -0,0 +1,224 @@
+using Thor.Analyzer.Rules;
+using Thor.Analyzer.Tests.EventSources;
+using FluentAssertions;
+using Moq;
+using Xunit;
+
+namespace Thor.Analyzer.Tests.Rules
+{
+ public class MustHaveStaticLogFieldOrPropertyTests
+ : EventSourceRuleTestBase
+ {
+ protected override MustHaveStaticLogFieldOrProperty CreateRule(IRuleSet ruleSet)
+ {
+ return new MustHaveStaticLogFieldOrProperty(ruleSet);
+ }
+
+ [Fact(DisplayName = "Apply: Should return an error if log field and property does not exist")]
+ public void Apply_NoLogFieldAndProperty()
+ {
+ // arrange
+ LogFieldAndPropertyDoNotExistEventSource eventSource = new LogFieldAndPropertyDoNotExistEventSource();
+ SchemaReader reader = new SchemaReader(eventSource);
+ EventSourceSchema schema = reader.Read();
+ IRuleSet ruleSet = new Mock().Object;
+ IEventSourceRule rule = CreateRule(ruleSet);
+
+ // act
+ IResult result = rule.Apply(schema, eventSource);
+
+ // assert
+ result.Should().NotBeNull();
+ result.Should().BeOfType();
+ }
+
+ [Fact(DisplayName = "Apply: Should return an error if log field is not public")]
+ public void Apply_LogFieldNotPublic()
+ {
+ // arrange
+ LogFieldNotPublicEventSource eventSource = new LogFieldNotPublicEventSource();
+ SchemaReader reader = new SchemaReader(eventSource);
+ EventSourceSchema schema = reader.Read();
+ IRuleSet ruleSet = new Mock().Object;
+ IEventSourceRule rule = CreateRule(ruleSet);
+
+ // act
+ IResult result = rule.Apply(schema, eventSource);
+
+ // assert
+ result.Should().NotBeNull();
+ result.Should().BeOfType();
+ }
+
+ [Fact(DisplayName = "Apply: Should return an error if log field is not readonly")]
+ public void Apply_LogFieldNotReadOnly()
+ {
+ // arrange
+ LogFieldNotReadOnlyEventSource eventSource = new LogFieldNotReadOnlyEventSource();
+ SchemaReader reader = new SchemaReader(eventSource);
+ EventSourceSchema schema = reader.Read();
+ IRuleSet ruleSet = new Mock().Object;
+ IEventSourceRule rule = CreateRule(ruleSet);
+
+ // act
+ IResult result = rule.Apply(schema, eventSource);
+
+ // assert
+ result.Should().NotBeNull();
+ result.Should().BeOfType();
+ }
+
+ /*
+ todo: figure out why this test leads to StackOverflowException
+
+ [Fact(DisplayName = "Apply: Should return an error if log field is not static")]
+ public void Apply_LogFieldNotStatic()
+ {
+ // arrange
+ LogFieldNotStaticEventSource eventSource = new LogFieldNotStaticEventSource();
+ SchemaReader reader = new SchemaReader(eventSource);
+ EventSourceSchema schema = reader.Read();
+ IRuleSet ruleSet = new Mock().Object;
+ IEventSourceRule rule = CreateRule(ruleSet);
+
+ // act
+ IResult result = rule.Apply(schema, eventSource);
+
+ // assert
+ result.Should().NotBeNull();
+ result.Should().BeOfType();
+ }
+ */
+
+ [Fact(DisplayName = "Apply: Should return an error if log field returns no value")]
+ public void Apply_LogFieldNull()
+ {
+ // arrange
+ LogFieldNullEventSource eventSource = new LogFieldNullEventSource();
+ SchemaReader reader = new SchemaReader(eventSource);
+ EventSourceSchema schema = reader.Read();
+ IRuleSet ruleSet = new Mock().Object;
+ IEventSourceRule rule = CreateRule(ruleSet);
+
+ // act
+ IResult result = rule.Apply(schema, eventSource);
+
+ // assert
+ result.Should().NotBeNull();
+ result.Should().BeOfType();
+ }
+
+ [Fact(DisplayName = "Apply: Should return a success if the log field was found as expected")]
+ public void Apply_LogFieldAsExpected()
+ {
+ // arrange
+ LogFieldEventSource eventSource = new LogFieldEventSource();
+ SchemaReader reader = new SchemaReader(eventSource);
+ EventSourceSchema schema = reader.Read();
+ IRuleSet ruleSet = new Mock().Object;
+ IEventSourceRule rule = CreateRule(ruleSet);
+
+ // act
+ IResult result = rule.Apply(schema, eventSource);
+
+ // assert
+ result.Should().NotBeNull();
+ result.Should().BeOfType();
+ }
+
+ [Fact(DisplayName = "Apply: Should return an error if log property is not public")]
+ public void Apply_LogPropertyNotPublic()
+ {
+ // arrange
+ LogPropertyNotPublicEventSource eventSource = new LogPropertyNotPublicEventSource();
+ SchemaReader reader = new SchemaReader(eventSource);
+ EventSourceSchema schema = reader.Read();
+ IRuleSet ruleSet = new Mock().Object;
+ IEventSourceRule rule = CreateRule(ruleSet);
+
+ // act
+ IResult result = rule.Apply(schema, eventSource);
+
+ // assert
+ result.Should().NotBeNull();
+ result.Should().BeOfType();
+ }
+
+ [Fact(DisplayName = "Apply: Should return an error if log property is not readonly")]
+ public void Apply_LogPropertyNotReadOnly()
+ {
+ // arrange
+ LogPropertyNotReadOnlyEventSource eventSource = new LogPropertyNotReadOnlyEventSource();
+ SchemaReader reader = new SchemaReader(eventSource);
+ EventSourceSchema schema = reader.Read();
+ IRuleSet ruleSet = new Mock().Object;
+ IEventSourceRule rule = CreateRule(ruleSet);
+
+ // act
+ IResult result = rule.Apply(schema, eventSource);
+
+ // assert
+ result.Should().NotBeNull();
+ result.Should().BeOfType();
+ }
+
+ /*
+ todo: figure out why this test leads to StackOverflowException
+
+ [Fact(DisplayName = "Apply: Should return an error if log property is not static")]
+ public void Apply_LogPropertyNotStatic()
+ {
+ // arrange
+ LogPropertyNotStaticEventSource eventSource = new LogPropertyNotStaticEventSource();
+ SchemaReader reader = new SchemaReader(eventSource);
+ EventSourceSchema schema = reader.Read();
+ IRuleSet ruleSet = new Mock().Object;
+ IEventSourceRule rule = CreateRule(ruleSet);
+
+ // act
+ IResult result = rule.Apply(schema, eventSource);
+
+ // assert
+ result.Should().NotBeNull();
+ result.Should().BeOfType();
+ }
+ */
+
+ [Fact(DisplayName = "Apply: Should return an error if log property returns no value")]
+ public void Apply_LogPropertyNull()
+ {
+ // arrange
+ LogPropertyNullEventSource eventSource = new LogPropertyNullEventSource();
+ SchemaReader reader = new SchemaReader(eventSource);
+ EventSourceSchema schema = reader.Read();
+ IRuleSet ruleSet = new Mock().Object;
+ IEventSourceRule rule = CreateRule(ruleSet);
+
+ // act
+ IResult result = rule.Apply(schema, eventSource);
+
+ // assert
+ result.Should().NotBeNull();
+ result.Should().BeOfType();
+ }
+
+ [Fact(DisplayName = "Apply: Should return a success if the log property was found as expected")]
+ public void Apply_LogPropertyAsExpected()
+ {
+ // arrange
+ LogPropertyEventSource eventSource = new LogPropertyEventSource();
+ SchemaReader reader = new SchemaReader(eventSource);
+ EventSourceSchema schema = reader.Read();
+ IRuleSet ruleSet = new Mock().Object;
+ IEventSourceRule rule = CreateRule(ruleSet);
+
+ // act
+ IResult result = rule.Apply(schema, eventSource);
+
+ // assert
+ result.Should().NotBeNull();
+ result.Should().BeOfType();
+ }
+ }
+}
+
\ No newline at end of file
diff --git a/src/Analyzer.Tests/Rules/MustHaveStaticLogPropertyTests.cs b/src/Analyzer.Tests/Rules/MustHaveStaticLogPropertyTests.cs
deleted file mode 100644
index 6f56cfd..0000000
--- a/src/Analyzer.Tests/Rules/MustHaveStaticLogPropertyTests.cs
+++ /dev/null
@@ -1,130 +0,0 @@
-using Thor.Analyzer.Rules;
-using Thor.Analyzer.Tests.EventSources;
-using FluentAssertions;
-using Moq;
-using Xunit;
-
-namespace Thor.Analyzer.Tests.Rules
-{
- public class MustHaveStaticLogPropertyTests
- : EventSourceRuleTestBase
- {
- protected override MustHaveStaticLogProperty CreateRule(IRuleSet ruleSet)
- {
- return new MustHaveStaticLogProperty(ruleSet);
- }
-
- [Fact(DisplayName = "Apply: Should return an error if log field does not exist")]
- public void Apply_NoLogField()
- {
- // arrange
- LogFieldDoesNotExistEventSource eventSource = new LogFieldDoesNotExistEventSource();
- SchemaReader reader = new SchemaReader(eventSource);
- EventSourceSchema schema = reader.Read();
- IRuleSet ruleSet = new Mock().Object;
- IEventSourceRule rule = CreateRule(ruleSet);
-
- // act
- IResult result = rule.Apply(schema, eventSource);
-
- // assert
- result.Should().NotBeNull();
- result.Should().BeOfType();
- }
-
- [Fact(DisplayName = "Apply: Should return an error if log field is not public")]
- public void Apply_LogFieldNotPublic()
- {
- // arrange
- LogFieldNotPublicEventSource eventSource = new LogFieldNotPublicEventSource();
- SchemaReader reader = new SchemaReader(eventSource);
- EventSourceSchema schema = reader.Read();
- IRuleSet ruleSet = new Mock().Object;
- IEventSourceRule rule = CreateRule(ruleSet);
-
- // act
- IResult result = rule.Apply(schema, eventSource);
-
- // assert
- result.Should().NotBeNull();
- result.Should().BeOfType();
- }
-
- [Fact(DisplayName = "Apply: Should return an error if log field is not readonly")]
- public void Apply_LogFieldNotReadOnly()
- {
- // arrange
- LogFieldNotReadOnlyEventSource eventSource = new LogFieldNotReadOnlyEventSource();
- SchemaReader reader = new SchemaReader(eventSource);
- EventSourceSchema schema = reader.Read();
- IRuleSet ruleSet = new Mock().Object;
- IEventSourceRule rule = CreateRule(ruleSet);
-
- // act
- IResult result = rule.Apply(schema, eventSource);
-
- // assert
- result.Should().NotBeNull();
- result.Should().BeOfType();
- }
-
- /*
- todo: figure out why this test leads to StackOverflowException
-
- [Fact(DisplayName = "Apply: Should return an error if log field is not static")]
- public void Apply_LogFieldNotStatic()
- {
- // arrange
- LogFieldNotStaticEventSource eventSource = new LogFieldNotStaticEventSource();
- SchemaReader reader = new SchemaReader(eventSource);
- EventSourceSchema schema = reader.Read();
- IRuleSet ruleSet = new Mock().Object;
- IEventSourceRule rule = CreateRule(ruleSet);
-
- // act
- IResult result = rule.Apply(schema, eventSource);
-
- // assert
- result.Should().NotBeNull();
- result.Should().BeOfType();
- }
- */
-
- [Fact(DisplayName = "Apply: Should return an error if log field returns no value")]
- public void Apply_LogFieldNoValue()
- {
- // arrange
- LogFieldDoesNotHaveValueEventSource eventSource =
- new LogFieldDoesNotHaveValueEventSource();
- SchemaReader reader = new SchemaReader(eventSource);
- EventSourceSchema schema = reader.Read();
- IRuleSet ruleSet = new Mock().Object;
- IEventSourceRule rule = CreateRule(ruleSet);
-
- // act
- IResult result = rule.Apply(schema, eventSource);
-
- // assert
- result.Should().NotBeNull();
- result.Should().BeOfType();
- }
-
- [Fact(DisplayName = "Apply: Should return a success if a log field as defined was found")]
- public void Apply_Success()
- {
- // arrange
- LogFieldEventSource eventSource = new LogFieldEventSource();
- SchemaReader reader = new SchemaReader(eventSource);
- EventSourceSchema schema = reader.Read();
- IRuleSet ruleSet = new Mock().Object;
- IEventSourceRule rule = CreateRule(ruleSet);
-
- // act
- IResult result = rule.Apply(schema, eventSource);
-
- // assert
- result.Should().NotBeNull();
- result.Should().BeOfType();
- }
- }
-}
\ No newline at end of file
diff --git a/src/Analyzer/Rules/BestPracticeRuleSet.cs b/src/Analyzer/Rules/BestPracticeRuleSet.cs
index 7b6841d..5095600 100644
--- a/src/Analyzer/Rules/BestPracticeRuleSet.cs
+++ b/src/Analyzer/Rules/BestPracticeRuleSet.cs
@@ -17,7 +17,7 @@ public BestPracticeRuleSet()
{
new MustBeSealed(this),
new MustHaveSinglePrivateConstructor(this),
- new MustHaveStaticLogProperty(this),
+ new MustHaveStaticLogFieldOrProperty(this),
new MustHaveValidName(this)
};
}
diff --git a/src/Analyzer/Rules/MustHaveStaticLogProperty.cs b/src/Analyzer/Rules/MustHaveStaticLogFieldOrProperty.cs
similarity index 50%
rename from src/Analyzer/Rules/MustHaveStaticLogProperty.cs
rename to src/Analyzer/Rules/MustHaveStaticLogFieldOrProperty.cs
index a273612..4039665 100644
--- a/src/Analyzer/Rules/MustHaveStaticLogProperty.cs
+++ b/src/Analyzer/Rules/MustHaveStaticLogFieldOrProperty.cs
@@ -10,16 +10,16 @@
namespace Thor.Analyzer.Rules
{
///
- /// A rule which probes for missing Log properties.
+ /// A rule which probes for missing Log field or property.
///
- public class MustHaveStaticLogProperty
+ public class MustHaveStaticLogFieldOrProperty
: IEventSourceRule
{
///
- /// Initiates a new instance of the class.
+ /// Initiates a new instance of the class.
///
/// A ruleset which is the parent of this rule.
- public MustHaveStaticLogProperty(IRuleSet ruleSet)
+ public MustHaveStaticLogFieldOrProperty(IRuleSet ruleSet)
{
if (ruleSet == null)
{
@@ -45,16 +45,33 @@ public IResult Apply(EventSourceSchema schema, EventSource eventSource)
}
Type eventSourceType = eventSource.GetType();
- FieldInfo field = eventSourceType.GetField("Log");
+ PropertyInfo property = eventSourceType.GetProperty("Log");
- if (field == null || !field.IsStatic || !field.IsInitOnly ||
- !field.FieldType.IsAssignableFrom(eventSourceType) || field.GetValue(null) == null)
+ if (property == null)
{
- return new Error(this, "Did not found a public readonly 'Log' field which is " +
- "static and holds an instance of its own type.");
+ FieldInfo field = eventSourceType.GetField("Log");
+
+ if (field == null || !field.IsStatic || !field.IsInitOnly ||
+ !field.FieldType.IsAssignableFrom(eventSourceType) ||
+ field.GetValue(null) == null)
+ {
+ return CreateError();
+ }
+ }
+ else if (!property.CanRead || property.CanWrite || !property.GetGetMethod().IsStatic ||
+ !property.PropertyType.IsAssignableFrom(eventSourceType) ||
+ property.GetValue(null) == null)
+ {
+ return CreateError();
}
return new Success(this);
}
+
+ private Error CreateError()
+ {
+ return new Error(this, "Did not found a public readonly 'Log' field or property " +
+ "which is static and holds an instance of its own type.");
+ }
}
}
\ No newline at end of file