Skip to content

Commit

Permalink
Merge pull request #364 from manfred-brands/field_not_initialized
Browse files Browse the repository at this point in the history
NonNullableFieldIsUninitializedSuppressor didn't work when there was a constructor
  • Loading branch information
mikkelbu authored Feb 21, 2021
2 parents 1e0017d + 4a61646 commit d173b7c
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,38 @@ await DiagnosticsSuppressorAnalyzer.EnsureSuppressed(suppressor,
NonNullableFieldIsUninitializedSuppressor.NullableFieldInitializedInSetUp, testCode)
.ConfigureAwait(false);
}

[TestCase("SetUp", "")]
[TestCase("OneTimeSetUp", "this.")]
public async Task FieldNotAssignedInConstructor(string attribute, string prefix)
{
var testCode = TestUtility.WrapMethodInClassNamespaceAndAddUsings(@$"
#nullable enable
private string testName;
private string nunitField;
public TestClass(string name)
{{
{prefix}testName = name;
}}
[{attribute}]
public void Initialize()
{{
{prefix}nunitField = string.Empty;
}}
[Test]
public void Test()
{{
Assert.That({prefix}nunitField, Is.Not.Null);
}}
");

await DiagnosticsSuppressorAnalyzer.EnsureSuppressed(suppressor,
NonNullableFieldIsUninitializedSuppressor.NullableFieldInitializedInSetUp, testCode)
.ConfigureAwait(false);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#if !NETSTANDARD1_6

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
Expand Down Expand Up @@ -33,9 +34,44 @@ public override void ReportSuppressions(SuppressionAnalysisContext context)
continue;
}

string fieldName = node.ToString();

var classDeclaration = node.Ancestors().OfType<ClassDeclarationSyntax>().First();
var fieldDeclarations = classDeclaration.Members.OfType<FieldDeclarationSyntax>().ToArray();

string fieldName;

if (node is VariableDeclaratorSyntax variableDeclarator)
{
fieldName = variableDeclarator.Identifier.Text;
}
else if (node is ConstructorDeclarationSyntax)
{
// Unfortunately the actual field name is not directly accessible.
// It seems to be in Argument[1], but that field is an internal property.
// Resort to reflection.
IReadOnlyList<object?>? arguments = (IReadOnlyList<object?>?)diagnostic.GetType()
.GetProperty("Arguments", BindingFlags.NonPublic | BindingFlags.Instance)?
.GetValue(diagnostic);
if (arguments != null && arguments.Count == 2 && arguments[1] is string possibleFieldName)
{
fieldName = possibleFieldName;
}
else
{
// Don't know how to extract field name.
continue;
}
}
else
{
continue;
}

// Verify that the name found is actually a field name.
if (!fieldDeclarations.SelectMany(x => x.Declaration.Variables).Any(x => x.Identifier.Text == fieldName))
{
continue;
}

var methods = classDeclaration.Members.OfType<MethodDeclarationSyntax>().ToArray();

foreach (var method in methods)
Expand Down

0 comments on commit d173b7c

Please sign in to comment.