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
4 changes: 2 additions & 2 deletions src/Meziantou.Analyzer.CodeFixers/Rules/EqualityShouldBeCorrectlyImplementedFixer.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
var nodeToFix = root?.FindNode(context.Span, getInnermostNodeForTie: true);
if (nodeToFix is null)
return;

var title = "Implement System.IEquatable";
var codeAction = CodeAction.Create(
title,
Expand All @@ -36,7 +36,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
private static async Task<Document> ImplementIEquatable(Document document, SyntaxNode nodeToFix, CancellationToken cancellationToken)
{
var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

if (semanticModel is null || semanticModel.GetDeclaredSymbol(nodeToFix, cancellationToken: cancellationToken) is not ITypeSymbol declaredTypeSymbol)
return document;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)

private static async Task<Document> UseThis(Document document, SyntaxNode nodeToFix, CancellationToken cancellationToken)
{
var editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false);
var editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false);
editor.ReplaceNode(nodeToFix, editor.Generator.ThisExpression());
return editor.GetChangedDocument();
}
Expand Down
2 changes: 1 addition & 1 deletion src/Meziantou.Analyzer.CodeFixers/Rules/ValidateArgumentsCorrectlyFixer.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ private static ParameterListSyntax RemoveEnumeratorCancellationAttribute(Paramet

ParameterSyntax UpdateParameter(ParameterSyntax parameter)
{
return parameter.WithAttributeLists(new SyntaxList<AttributeListSyntax>(parameter.AttributeLists.Select(UpdateAttributeList).Where(list=>list.Attributes.Count > 0)));
return parameter.WithAttributeLists(new SyntaxList<AttributeListSyntax>(parameter.AttributeLists.Select(UpdateAttributeList).Where(list => list.Attributes.Count > 0)));
}

AttributeListSyntax UpdateAttributeList(AttributeListSyntax attributes)
Expand Down
2 changes: 1 addition & 1 deletion src/Meziantou.Analyzer/Internals/ContextExtensions.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public static void ReportDiagnostic(this DiagnosticReporter context, DiagnosticD
ReportDiagnostic(context, descriptor, properties, location, messageArgs);
}
}

public static void ReportDiagnostic(this DiagnosticReporter context, DiagnosticDescriptor descriptor, IPropertySymbol symbol, DiagnosticPropertyReportOptions reportOptions, string?[]? messageArgs = null) => ReportDiagnostic(context, descriptor, ImmutableDictionary<string, string?>.Empty, symbol, reportOptions, messageArgs);
public static void ReportDiagnostic(this DiagnosticReporter context, DiagnosticDescriptor descriptor, ImmutableDictionary<string, string?>? properties, IPropertySymbol symbol, DiagnosticPropertyReportOptions reportOptions, string?[]? messageArgs = null)
{
Expand Down
6 changes: 3 additions & 3 deletions src/Meziantou.Analyzer/Internals/CultureSensitiveFormattingContext.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -183,10 +183,10 @@ public bool IsCultureSensitiveOperation(IOperation operation, CultureSensitiveOp

if (operation is IDefaultValueOperation defaultValue)
return IsCultureSensitiveType(defaultValue.Type, format: null, instance: null, options);

if (operation is IArrayElementReferenceOperation arrayElementReference)
return IsCultureSensitiveType(arrayElementReference.Type, format: null, instance: null, options);

if (operation is IBinaryOperation binaryOperation)
return IsCultureSensitiveType(binaryOperation.Type, format: null, instance: null, options);

Expand Down Expand Up @@ -288,7 +288,7 @@ private static bool IsInvariantDateTimeFormat(IOperation? valueOperation)
private static bool IsInvariantTimeSpanFormat(IOperation? valueOperation)
{
// note: "c" format is case-sensitive
return valueOperation is null || valueOperation is { ConstantValue: { HasValue: true, Value: null or "" or "c" or "t" or "T" } };
return valueOperation is null or { ConstantValue: { HasValue: true, Value: null or "" or "c" or "t" or "T" } };
}

// Only negative numbers are culture-sensitive (negative sign)
Expand Down
18 changes: 9 additions & 9 deletions src/Meziantou.Analyzer/Internals/MethodSymbolExtensions.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,28 @@ internal static class MethodSymbolExtensions
private static readonly string[] NunitNamespaceParts = ["NUnit", "Framework"];
private static readonly string[] XunitNamespaceParts = ["Xunit"];

public static bool IsInterfaceImplementation(this IMethodSymbol method)
public static bool IsInterfaceImplementation(this IMethodSymbol symbol)
{
if (method.ExplicitInterfaceImplementations.Length > 0)
if (symbol.ExplicitInterfaceImplementations.Length > 0)
return true;

return IsInterfaceImplementation((ISymbol)method);
return IsInterfaceImplementation((ISymbol)symbol);
}

public static bool IsInterfaceImplementation(this IPropertySymbol property)
public static bool IsInterfaceImplementation(this IPropertySymbol symbol)
{
if (property.ExplicitInterfaceImplementations.Length > 0)
if (symbol.ExplicitInterfaceImplementations.Length > 0)
return true;

return IsInterfaceImplementation((ISymbol)property);
return IsInterfaceImplementation((ISymbol)symbol);
}

public static bool IsInterfaceImplementation(this IEventSymbol method)
public static bool IsInterfaceImplementation(this IEventSymbol symbol)
{
if (method.ExplicitInterfaceImplementations.Length > 0)
if (symbol.ExplicitInterfaceImplementations.Length > 0)
return true;

return IsInterfaceImplementation((ISymbol)method);
return IsInterfaceImplementation((ISymbol)symbol);
}

private static bool IsInterfaceImplementation(this ISymbol symbol)
Expand Down
4 changes: 2 additions & 2 deletions src/Meziantou.Analyzer/Internals/TypeSymbolExtensions.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ public static bool Implements(this ITypeSymbol classSymbol, ITypeSymbol? interfa
if (interfaceType is null)
return false;

return classSymbol.AllInterfaces.Any(i => interfaceType.IsEqualTo(i));
return classSymbol.AllInterfaces.Any(interfaceType.IsEqualTo);
}

public static bool IsOrImplements(this ITypeSymbol symbol, ITypeSymbol? interfaceType)
{
if (interfaceType is null)
return false;

return GetAllInterfacesIncludingThis(symbol).Any(i => interfaceType.IsEqualTo(i));
return GetAllInterfacesIncludingThis(symbol).Any(interfaceType.IsEqualTo);
}

public static AttributeData? GetAttribute(this ISymbol symbol, ITypeSymbol? attributeType, bool inherits = true)
Expand Down
1 change: 1 addition & 0 deletions src/Meziantou.Analyzer/RuleIdentifiers.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ internal static class RuleIdentifiers
public const string UseTaskUnwrap = "MA0152";
public const string DoNotLogClassifiedData = "MA0153";
public const string UseLangwordInXmlComment = "MA0154";
public const string DoNotUseAsyncVoid = "MA0155";

public static string GetHelpUri(string identifier)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Meziantou.Analyzer/Rules/AbstractTypesShouldNotHaveConstructorsAnalyzer.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context)

foreach (var ctor in symbol.InstanceConstructors)
{
if (ctor.DeclaredAccessibility == Accessibility.Public || ctor.DeclaredAccessibility == Accessibility.Internal)
if (ctor.DeclaredAccessibility is Accessibility.Public or Accessibility.Internal)
{
context.ReportDiagnostic(Rule, ctor);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ private static void AnalyzeOperation(OperationAnalysisContext context)
handler = op.Operand;
}

if (handler is not null && handler is IDelegateCreationOperation delegateCreation)
if (handler is IDelegateCreationOperation delegateCreation)
{
if (delegateCreation.Target is IAnonymousFunctionOperation)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Meziantou.Analyzer/Rules/DoNotUseBlockingCallInAsyncContextAnalyzer.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ private bool HasAsyncEquivalent(IInvocationOperation operation, [NotNullWhen(tru
}

// Console.Out|Error.Write
else if (targetMethod.Name == "WriteLine" || targetMethod.Name == "Write" || targetMethod.Name == "Flush")
else if (targetMethod.Name is "WriteLine" or "Write" or "Flush")
{
var left = operation.GetChildOperations().FirstOrDefault();
if (left is IMemberReferenceOperation memberReference)
Expand Down
2 changes: 1 addition & 1 deletion src/Meziantou.Analyzer/Rules/JSInteropMustNotBeUsedInOnInitializedAnalyzer.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public bool IsValid
{
if (WebAssemblyJSRuntimeSymbol is not null)
return false; // There is no issue in WebAssembly

if (WebViewJSRuntimeSymbol is not null)
return false; // There is no issue in WebView

Expand Down
2 changes: 1 addition & 1 deletion src/Meziantou.Analyzer/Rules/NamedParameterAnalyzerCommon.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Meziantou.Analyzer.Rules;

internal static class NamedParameterAnalyzerCommon
{
{
public static int ArgumentIndex(ArgumentSyntax argument)
{
var argumentListExpression = argument.FirstAncestorOrSelf<ArgumentListSyntax>();
Expand Down
4 changes: 2 additions & 2 deletions src/Meziantou.Analyzer/Rules/OptimizeLinqUsageAnalyzer.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ private void UseFindInsteadOfFirstOrDefault(OperationAnalysisContext context, II
context.ReportDiagnostic(ListMethodsRule, properties, operation, DiagnosticInvocationReportOptions.ReportOnMember, "Find()", operation.TargetMethod.Name);
}
}

private void UseTrueForAllInsteadOfAll(OperationAnalysisContext context, IInvocationOperation operation)
{
if (operation.TargetMethod.Name != nameof(Enumerable.All))
Expand Down Expand Up @@ -322,7 +322,7 @@ private void UseTrueForAllInsteadOfAll(OperationAnalysisContext context, IInvoca
context.ReportDiagnostic(ListMethodsRule, properties, operation, DiagnosticInvocationReportOptions.ReportOnMember, "TrueForAll()", operation.TargetMethod.Name);
}
}

private void UseExistsInsteadOfAny(OperationAnalysisContext context, IInvocationOperation operation)
{
if (operation.TargetMethod.Name != nameof(Enumerable.Any))
Expand Down
2 changes: 1 addition & 1 deletion src/Meziantou.Analyzer/Rules/ValidateArgumentsCorrectlyAnalyzer.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ private bool IsArgumentValidation(SyntaxNodeAnalysisContext context, SyntaxNode
{
if ((node.IsKind(SyntaxKind.ThrowStatement) || node.IsKind(SyntaxKind.ThrowExpression)) && IsArgumentException(context, node))
return true;

if (node is InvocationExpressionSyntax invocationExpression)
{
if (context.SemanticModel.GetOperation(invocationExpression, context.CancellationToken) is IInvocationOperation operation)
Expand Down
2 changes: 1 addition & 1 deletion tests/Meziantou.Analyzer.Test/Helpers/DiagnosticResult.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public sealed class DiagnosticResult

public IReadOnlyList<DiagnosticResultLocation> Locations
{
get => _locations ??= Array.Empty<DiagnosticResultLocation>();
get => _locations ??= [];
set => _locations = value;
}

Expand Down
4 changes: 2 additions & 2 deletions tests/Meziantou.Analyzer.Test/Helpers/ProjectBuilder.Validation.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ private Task<Project> CreateProject()
AddNuGetReference("Microsoft.NETCore.App.Ref", "7.0.0", "ref/net7.0/");
AddNuGetReference("Microsoft.AspNetCore.App.Ref", "7.0.0", "ref/net7.0/");
break;

case TargetFramework.AspNetCore8_0:
AddNuGetReference("Microsoft.NETCore.App.Ref", "8.0.0", "ref/net8.0/");
AddNuGetReference("Microsoft.AspNetCore.App.Ref", "8.0.0", "ref/net8.0/");
Expand Down Expand Up @@ -262,7 +262,7 @@ private static ReportDiagnostic GetReportDiagnostic(DiagnosticDescriptor descrip
};
}

[DebuggerStepThrough]
//[DebuggerStepThrough]
private async Task<Diagnostic[]> GetSortedDiagnosticsFromDocuments(IList<DiagnosticAnalyzer> analyzers, Document[] documents, bool compileSolution)
{
var projects = new HashSet<Project>();
Expand Down
14 changes: 13 additions & 1 deletion tests/Meziantou.Analyzer.Test/Helpers/ProjectBuilder.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,12 @@ public ProjectBuilder AddNuGetReference(string packageName, string version, stri

public ProjectBuilder WithAnalyzerFromNuGet(string packageName, string version, string[] paths, string[] ruleIds)
{
var ruleFound = false;
var references = GetNuGetReferences(packageName, version, paths).Result;
foreach (var reference in references)
{
var assembly = Assembly.LoadFrom(reference);
foreach (var type in assembly.GetExportedTypes())
foreach (var type in assembly.GetTypes())
{
if (type.IsAbstract || !typeof(DiagnosticAnalyzer).IsAssignableFrom(type))
continue;
Expand All @@ -118,10 +119,14 @@ public ProjectBuilder WithAnalyzerFromNuGet(string packageName, string version,
if (instance.SupportedDiagnostics.Any(d => ruleIds.Contains(d.Id, StringComparer.Ordinal)))
{
DiagnosticAnalyzer.Add(instance);
ruleFound = true;
}
}
}

if (!ruleFound)
throw new InvalidOperationException("Rule id not found");

return this;
}

Expand All @@ -132,6 +137,13 @@ public ProjectBuilder WithMicrosoftCodeAnalysisNetAnalyzers(params string[] rule
paths: ["analyzers/dotnet/cs/Microsoft.CodeAnalysis"],
ruleIds);

public ProjectBuilder WithMicrosoftCodeAnalysisCSharpCodeStyleAnalyzers(params string[] ruleIds) =>
WithAnalyzerFromNuGet(
"Microsoft.CodeAnalysis.CSharp.CodeStyle",
"4.10.0-2.final",
paths: ["analyzers/dotnet/cs/"],
ruleIds);

public ProjectBuilder AddMSTestApi() => AddNuGetReference("MSTest.TestFramework", "2.1.1", "lib/netstandard1.0/");

public ProjectBuilder AddNUnitApi() => AddNuGetReference("NUnit", "3.12.0", "lib/netstandard2.0/");
Expand Down
27 changes: 27 additions & 0 deletions tests/Meziantou.Analyzer.Test/RuleHelpUri.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;
using Meziantou.Analyzer.Rules;
using Microsoft.CodeAnalysis.Diagnostics;
using Xunit;

namespace Meziantou.Analyzer.Test;
public sealed class RuleHelpUri
{
[Fact]
public void HelpUriIsSet()
{
foreach (var type in typeof(AbstractTypesShouldNotHaveConstructorsAnalyzer).Assembly.GetExportedTypes())
{
if (type.IsAbstract)
continue;

if (!typeof(DiagnosticAnalyzer).IsAssignableFrom(type))
continue;

var instance = (DiagnosticAnalyzer)Activator.CreateInstance(type);
foreach (var diag in instance.SupportedDiagnostics)
{
Assert.Equal($"https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/{diag.Id}.md", diag.HelpLinkUri);
}
}
}
}
10 changes: 5 additions & 5 deletions tests/Meziantou.Analyzer.Test/Rules/AddOverloadWithSpanOrMemoryAnalyzerTests.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ await CreateProjectBuilder()
.WithSourceCode(SourceCode)
.ValidateAsync();
}

[Fact]
public async Task StringArrayWithoutSpanOverload_Out()
{
Expand All @@ -43,7 +43,7 @@ await CreateProjectBuilder()
.WithSourceCode(SourceCode)
.ValidateAsync();
}

[Fact]
public async Task StringArrayWithSpanOverload_Params()
{
Expand All @@ -58,7 +58,7 @@ await CreateProjectBuilder()
.WithSourceCode(SourceCode)
.ValidateAsync();
}

[Fact]
public async Task StringArrayWithoutSpanOverload()
{
Expand All @@ -74,7 +74,7 @@ await CreateProjectBuilder()
.WithSourceCode(SourceCode)
.ValidateAsync();
}

[Fact]
public async Task StringArrayWithoutSpanOverload_Complex()
{
Expand Down Expand Up @@ -111,7 +111,7 @@ await CreateProjectBuilder()
.WithSourceCode(sourceCode)
.ValidateAsync();
}

[Theory]
[InlineData("System.Span<char>")]
[InlineData("System.ReadOnlySpan<char>")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ await CreateProjectBuilder()
.WithSourceCode(sourceCode)
.ValidateAsync();
}

[Fact]
public async Task ArgumentNameIsSpecified_LocalFunction_Static_ShouldNotReportError()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ int A
""")
.ValidateAsync();
}

[Fact]
public async Task Report_TaskInLocalFunction()
{
Expand Down
8 changes: 4 additions & 4 deletions tests/Meziantou.Analyzer.Test/Rules/AwaitTaskBeforeDisposingResourcesAnalyzerTests.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ await CreateProjectBuilder()
.WithSourceCode(originalCode)
.ValidateAsync();
}

[Fact]
public async Task NotAwaitedTaskYieldMethod_InUsing()
{
Expand All @@ -82,7 +82,7 @@ await CreateProjectBuilder()
.WithSourceCode(originalCode)
.ValidateAsync();
}

[Fact]
public async Task NotAwaitedExtensionMethodOnInt32_InUsing()
{
Expand All @@ -107,7 +107,7 @@ await CreateProjectBuilder()
.WithSourceCode(originalCode)
.ValidateAsync();
}

[Fact]
public async Task NotAwaitedExtensionMethodOnValueTuple_InUsing()
{
Expand Down Expand Up @@ -325,7 +325,7 @@ await CreateProjectBuilder()
.WithSourceCode(originalCode)
.ValidateAsync();
}

[Fact]
public async Task NotAwaitedDefaultValueTask_InUsing()
{
Expand Down
Loading