Skip to content

Commit

Permalink
add analyzer for object parameter (#243)
Browse files Browse the repository at this point in the history
  • Loading branch information
dpvreony authored Mar 16, 2024
1 parent d99a8bd commit 6565825
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Copyright (c) 2019 DHGMS Solutions and Contributors. All rights reserved.
// This file is licensed to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using System.Collections.Immutable;
using Dhgms.GripeWithRoslyn.Analyzer.CodeCracker.Extensions;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;

namespace Dhgms.GripeWithRoslyn.Analyzer.Analyzers.Runtime
{
/// <summary>
/// Analyzer to ensure <see cref="object"/> is not used in a parameter declaration.
/// </summary>
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class DoNotUseObjectAsParameterTypeAnalyzer : DiagnosticAnalyzer
{
internal const string Title = "Do not use Object in a parameter declaration.";

private const string MessageFormat = Title;

private const string Category = SupportedCategories.Design;

private readonly DiagnosticDescriptor _rule;

/// <summary>
/// Initializes a new instance of the <see cref="DoNotUseObjectAsParameterTypeAnalyzer"/> class.
/// </summary>
public DoNotUseObjectAsParameterTypeAnalyzer()
{
_rule = new DiagnosticDescriptor(
DiagnosticIdsHelper.DoNotUseObjectAsParameterType,
Title,
MessageFormat,
Category,
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
description: DiagnosticResultDescriptionFactory.DoNotUseObjectAsParameterType());
}

/// <inheritdoc />
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(_rule);

/// <inheritdoc />
public sealed override void Initialize(AnalysisContext context)
{
context.EnableConcurrentExecution();
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
context.RegisterSyntaxNodeAction(AnalyzeParameter, SyntaxKind.Parameter);
}

private void AnalyzeParameter(SyntaxNodeAnalysisContext syntaxNodeAnalysisContext)
{
var parameterSyntax = (ParameterSyntax)syntaxNodeAnalysisContext.Node;

var semanticModel = syntaxNodeAnalysisContext.SemanticModel;
var type = parameterSyntax.Type;
if (type == null)
{
return;
}

var baseTypeInfo = semanticModel.GetTypeInfo(type);
var baseTypeSymbol = baseTypeInfo.Type;

if (baseTypeSymbol == null)
{
return;
}

var fullName = baseTypeSymbol.GetFullName(true);
if (fullName == "global::System.Object")
{
syntaxNodeAnalysisContext.ReportDiagnostic(Diagnostic.Create(_rule, type.GetLocation()));
}
}
}
}
2 changes: 2 additions & 0 deletions src/Dhgms.GripeWithRoslyn.Analyzer/DiagnosticIdsHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,7 @@ internal static class DiagnosticIdsHelper
internal static string MethodsThatUseReturnYieldShouldHaveNameThatBeginsWithEnumerate => "GR0031";

internal static string DoNotUseManualEventSubscriptions => "GR0032";

internal static string DoNotUseObjectAsParameterType => "GR0033";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@ internal static class DiagnosticResultDescriptionFactory
internal static string ConstructorShouldAcceptLoggingFrameworkArgument() => $"Constructors should have a final parameter of \nMicrosoft.Extensions.Logging.ILogging<T> or, \na sublass of Whipstaff.Core.ILogMessageActionsWrapper<T> or,\nXUnit.Abstractions.ITestOutputHelper.\n\nThis is to encourage a design that contains sufficient logging.";

internal static string TreatWarningsAsErrors() => $"Treat warnings as errors should be enabled on the build. This is to avoid issues that are reported as warnings being missed and piling up technical debt.";

internal static string DoNotUseObjectAsParameterType() => $"Do not use object as a parameter type. This is to avoid issues with type safety.";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright (c) 2019 DHGMS Solutions and Contributors. All rights reserved.
// This file is licensed to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using Dhgms.GripeWithRoslyn.Analyzer;
using Dhgms.GripeWithRoslyn.Analyzer.Analyzers.Runtime;
using Dhgms.GripeWithRoslyn.UnitTests.Helpers;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Xunit;

namespace Dhgms.GripeWithRoslyn.UnitTests.Analyzer.Analyzers.Runtime
{
/// <summary>
/// Unit Tests for <see cref="DoNotUseObjectAsParameterTypeAnalyzer"/>.
/// </summary>
public sealed class DoNotUseObjectAsParameterTypeAnalyzerTests : CodeFixVerifier
{
/// <summary>
/// Test to ensure bad code returns a warning.
/// </summary>
[Fact]
public void ReturnsWarning()
{
var test = @"
namespace ConsoleApplication1
{
class TypeName
{
public void MethodName(object arg)
{
var name = SomeEnum.SomeValue.ToString();
}
public void MethodName2(System.Object arg)
{
var name = SomeEnum.SomeValue.ToString();
}
}
}";
var expected = new[]
{
new DiagnosticResult
{
Id = DiagnosticIdsHelper.DoNotUseObjectAsParameterType,
Message = DoNotUseObjectAsParameterTypeAnalyzer.Title,
Severity = DiagnosticSeverity.Warning,
Locations =
[
new DiagnosticResultLocation("Test0.cs", 6, 36)
]
},
new DiagnosticResult
{
Id = DiagnosticIdsHelper.DoNotUseObjectAsParameterType,
Message = DoNotUseObjectAsParameterTypeAnalyzer.Title,
Severity = DiagnosticSeverity.Warning,
Locations =
[
new DiagnosticResultLocation("Test0.cs", 11, 37)
]
}
};

VerifyCSharpDiagnostic(
test,
expected);
}

/// <inheritdoc />
protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer()
{
return new DoNotUseObjectAsParameterTypeAnalyzer();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

<PropertyGroup>
<TargetFrameworks>net8.0;net48</TargetFrameworks>
<LangVersion>12</LangVersion>
</PropertyGroup>

<ItemGroup>
Expand Down

0 comments on commit 6565825

Please sign in to comment.