diff --git a/src/Exercism.Analyzers.CSharp/Analysis.cs b/src/Exercism.Analyzers.CSharp/Analysis.cs index 41cf14d5..1d08b6e4 100644 --- a/src/Exercism.Analyzers.CSharp/Analysis.cs +++ b/src/Exercism.Analyzers.CSharp/Analysis.cs @@ -1,5 +1,3 @@ -using System.Collections.Generic; - using Exercism.Analyzers.CSharp.Analyzers; using Microsoft.CodeAnalysis; @@ -12,14 +10,11 @@ internal record Analysis(List Comments, List Tags) public static Analysis Empty => new(new List(), new List()); } -internal abstract class Analyzer : CSharpSyntaxWalker +internal abstract class Analyzer(Submission submission, SyntaxWalkerDepth syntaxWalkerDepth = SyntaxWalkerDepth.Token) + : CSharpSyntaxWalker(syntaxWalkerDepth) { - private readonly Submission _submission; - private SemanticModel _semanticModel; - private Analysis _analysis; - - protected Analyzer(Submission submission, SyntaxWalkerDepth syntaxWalkerDepth = SyntaxWalkerDepth.Token) : base(syntaxWalkerDepth) => - _submission = submission; + private SemanticModel? _semanticModel; + private Analysis? _analysis; public static Analysis Analyze(Submission submission) { @@ -34,21 +29,21 @@ public static Analysis Analyze(Submission submission) return analysis; } - protected void AddComment(Comment comment) => _analysis.Comments.Add(comment); + protected void AddComment(Comment comment) => _analysis!.Comments.Add(comment); protected void AddTags(params string[] tags) { foreach (var tag in tags) - _analysis.Tags.Add(tag); + _analysis!.Tags.Add(tag); } private void Analyze(Analysis analysis) { _analysis = analysis; - foreach (var syntaxTree in _submission.Compilation.SyntaxTrees) + foreach (var syntaxTree in submission.Compilation.SyntaxTrees) { - _semanticModel = _submission.Compilation.GetSemanticModel(syntaxTree); + _semanticModel = submission.Compilation.GetSemanticModel(syntaxTree); Visit(syntaxTree.GetRoot()); } } @@ -102,17 +97,17 @@ public static IEnumerable CreateAnalyzers(Submission submission) } } - protected SymbolInfo GetSymbolInfo(SyntaxNode node) => _semanticModel.GetSymbolInfo(node); - protected ISymbol GetSymbol(SyntaxNode node) => GetSymbolInfo(node).Symbol; - protected string GetSymbolName(SyntaxNode node) => GetSymbol(node)?.ToDisplayString(); + protected SymbolInfo GetSymbolInfo(SyntaxNode node) => _semanticModel!.GetSymbolInfo(node); + protected ISymbol? GetSymbol(SyntaxNode node) => GetSymbolInfo(node).Symbol; + protected string? GetSymbolName(SyntaxNode node) => GetSymbol(node)?.ToDisplayString(); - protected ISymbol GetDeclaredSymbol(SyntaxNode node) => _semanticModel.GetDeclaredSymbol(node); - protected string GetDeclaredSymbolName(SyntaxNode node) => GetDeclaredSymbol(node)?.ToDisplayString(); + protected ISymbol? GetDeclaredSymbol(SyntaxNode node) => _semanticModel!.GetDeclaredSymbol(node); + protected string? GetDeclaredSymbolName(SyntaxNode node) => GetDeclaredSymbol(node)?.ToDisplayString(); - protected TypeInfo GetTypeInfo(SyntaxNode node) => _semanticModel.GetTypeInfo(node); - protected IOperation GetOperation(SyntaxNode node) => _semanticModel.GetOperation(node); + protected TypeInfo GetTypeInfo(SyntaxNode node) => _semanticModel!.GetTypeInfo(node); + protected IOperation? GetOperation(SyntaxNode node) => _semanticModel!.GetOperation(node); - protected IMethodSymbol GetConstructedFromSymbol(SyntaxNode node) => + protected IMethodSymbol? GetConstructedFromSymbol(SyntaxNode node) => GetSymbol(node) is IMethodSymbol methodSymbol ? methodSymbol.ConstructedFrom : null; - protected string GetConstructedFromSymbolName(SyntaxNode node) => GetConstructedFromSymbol(node)?.ToDisplayString(); + protected string? GetConstructedFromSymbolName(SyntaxNode node) => GetConstructedFromSymbol(node)?.ToDisplayString(); } \ No newline at end of file diff --git a/src/Exercism.Analyzers.CSharp/Analyzers/CollatzConjectureAnalyzer.cs b/src/Exercism.Analyzers.CSharp/Analyzers/CollatzConjectureAnalyzer.cs index bff40eff..c915259b 100644 --- a/src/Exercism.Analyzers.CSharp/Analyzers/CollatzConjectureAnalyzer.cs +++ b/src/Exercism.Analyzers.CSharp/Analyzers/CollatzConjectureAnalyzer.cs @@ -2,12 +2,8 @@ namespace Exercism.Analyzers.CSharp.Analyzers; -internal class CollatzConjectureAnalyzer : Analyzer +internal class CollatzConjectureAnalyzer(Submission submission) : Analyzer(submission) { - public CollatzConjectureAnalyzer(Submission submission) : base(submission) - { - } - public override void VisitInvocationExpression(InvocationExpressionSyntax node) { if (GetConstructedFromSymbolName(node) == "System.Collections.Generic.IEnumerable.Count()") diff --git a/src/Exercism.Analyzers.CSharp/Analyzers/CommonAnalyzer.cs b/src/Exercism.Analyzers.CSharp/Analyzers/CommonAnalyzer.cs index ec928c19..a6b9fa7a 100644 --- a/src/Exercism.Analyzers.CSharp/Analyzers/CommonAnalyzer.cs +++ b/src/Exercism.Analyzers.CSharp/Analyzers/CommonAnalyzer.cs @@ -1,13 +1,10 @@ -using System.Collections.Generic; -using System.Linq; - -using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Exercism.Analyzers.CSharp.Analyzers; -internal class CommonAnalyzer : Analyzer +internal class CommonAnalyzer(Submission submission) : Analyzer(submission) { public override void VisitMethodDeclaration(MethodDeclarationSyntax node) { @@ -90,10 +87,6 @@ public override void VisitAssignmentExpression(AssignmentExpressionSyntax node) "Console.Out.WriteLine" }; - public CommonAnalyzer(Submission submission) : base(submission) - { - } - private static class Comments { public static readonly Comment DoNotUseMainMethod = new("csharp.general.has_main_method", CommentType.Essential); diff --git a/src/Exercism.Analyzers.CSharp/Analyzers/DifferenceOfSquaresAnalyzer.cs b/src/Exercism.Analyzers.CSharp/Analyzers/DifferenceOfSquaresAnalyzer.cs index ffd35b7d..70d8215f 100644 --- a/src/Exercism.Analyzers.CSharp/Analyzers/DifferenceOfSquaresAnalyzer.cs +++ b/src/Exercism.Analyzers.CSharp/Analyzers/DifferenceOfSquaresAnalyzer.cs @@ -1,22 +1,16 @@ -using System.Linq; - -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Exercism.Analyzers.CSharp.Analyzers; -internal class DifferenceOfSquaresAnalyzer : Analyzer +internal class DifferenceOfSquaresAnalyzer(Submission submission) : Analyzer(submission) { - public DifferenceOfSquaresAnalyzer(Submission submission) : base(submission) - { - } - public override void VisitMethodDeclaration(MethodDeclarationSyntax node) { if (node.DescendantNodes() .OfType() .Select(GetSymbol) .Where(invocationSymbol => invocationSymbol is not null) - .All(invocationSymbol => invocationSymbol.ContainingType.ToDisplayString() == "System.Math")) + .All(invocationSymbol => invocationSymbol?.ContainingType.ToDisplayString() == "System.Math")) AddTags(Tags.TechniqueMath); base.VisitMethodDeclaration(node); diff --git a/src/Exercism.Analyzers.CSharp/Analyzers/GigasecondAnalyzer.cs b/src/Exercism.Analyzers.CSharp/Analyzers/GigasecondAnalyzer.cs index 1655a1b1..6428b112 100644 --- a/src/Exercism.Analyzers.CSharp/Analyzers/GigasecondAnalyzer.cs +++ b/src/Exercism.Analyzers.CSharp/Analyzers/GigasecondAnalyzer.cs @@ -1,22 +1,16 @@ -using System.Linq; - using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Exercism.Analyzers.CSharp.Analyzers; -internal class GigasecondAnalyzer : Analyzer +internal class GigasecondAnalyzer(Submission submission) : Analyzer(submission) { - public GigasecondAnalyzer(Submission submission) : base(submission) - { - } - public override void VisitCompilationUnit(CompilationUnitSyntax node) { if (node.DescendantNodes() .OfType() .Select(GetSymbol) .Where(symbol => symbol is not null) - .All(symbol => symbol.ToDisplayString() != "System.DateTime.AddSeconds(double)")) + .All(symbol => symbol?.ToDisplayString() != "System.DateTime.AddSeconds(double)")) AddComment(Comments.UseAddSeconds); base.VisitCompilationUnit(node); diff --git a/src/Exercism.Analyzers.CSharp/Analyzers/GrainsAnalyzer.cs b/src/Exercism.Analyzers.CSharp/Analyzers/GrainsAnalyzer.cs index b827778e..aebc989f 100644 --- a/src/Exercism.Analyzers.CSharp/Analyzers/GrainsAnalyzer.cs +++ b/src/Exercism.Analyzers.CSharp/Analyzers/GrainsAnalyzer.cs @@ -2,12 +2,8 @@ namespace Exercism.Analyzers.CSharp.Analyzers; -internal class GrainsAnalyzer : Analyzer +internal class GrainsAnalyzer(Submission submission) : Analyzer(submission) { - public GrainsAnalyzer(Submission submission) : base(submission) - { - } - public override void VisitInvocationExpression(InvocationExpressionSyntax node) { if (GetSymbolName(node.Expression) == "System.Math.Pow(double, double)") diff --git a/src/Exercism.Analyzers.CSharp/Analyzers/IsogramAnalyzer.cs b/src/Exercism.Analyzers.CSharp/Analyzers/IsogramAnalyzer.cs index 4578a93f..d43db7b4 100644 --- a/src/Exercism.Analyzers.CSharp/Analyzers/IsogramAnalyzer.cs +++ b/src/Exercism.Analyzers.CSharp/Analyzers/IsogramAnalyzer.cs @@ -3,12 +3,8 @@ namespace Exercism.Analyzers.CSharp.Analyzers; -internal class IsogramAnalyzer : Analyzer -{ - public IsogramAnalyzer(Submission submission) : base(submission) - { - } - +internal class IsogramAnalyzer(Submission submission) : Analyzer(submission) +{ public override void VisitInvocationExpression(InvocationExpressionSyntax node) { if (GetSymbolInfo(node).Symbol is IMethodSymbol methodSymbol) diff --git a/src/Exercism.Analyzers.CSharp/Analyzers/LeapAnalyzer.cs b/src/Exercism.Analyzers.CSharp/Analyzers/LeapAnalyzer.cs index 55ce9a46..0e8307b0 100644 --- a/src/Exercism.Analyzers.CSharp/Analyzers/LeapAnalyzer.cs +++ b/src/Exercism.Analyzers.CSharp/Analyzers/LeapAnalyzer.cs @@ -1,16 +1,10 @@ -using System.Linq; - -using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Exercism.Analyzers.CSharp.Analyzers; -internal class LeapAnalyzer : Analyzer +internal class LeapAnalyzer(Submission submission) : Analyzer(submission) { - public LeapAnalyzer(Submission submission) : base(submission) - { - } - public override void VisitMethodDeclaration(MethodDeclarationSyntax node) { if (GetDeclaredSymbolName(node) == "Leap.IsLeapYear(int)" && diff --git a/src/Exercism.Analyzers.CSharp/Analyzers/PangramAnalyzer.cs b/src/Exercism.Analyzers.CSharp/Analyzers/PangramAnalyzer.cs index ed0e53ac..ce67cf3d 100644 --- a/src/Exercism.Analyzers.CSharp/Analyzers/PangramAnalyzer.cs +++ b/src/Exercism.Analyzers.CSharp/Analyzers/PangramAnalyzer.cs @@ -2,12 +2,8 @@ namespace Exercism.Analyzers.CSharp.Analyzers; -internal class PangramAnalyzer : Analyzer -{ - public PangramAnalyzer(Submission submission) : base(submission) - { - } - +internal class PangramAnalyzer(Submission submission) : Analyzer(submission) +{ public override void VisitInvocationExpression(InvocationExpressionSyntax node) { switch (GetSymbolName(node)) diff --git a/src/Exercism.Analyzers.CSharp/Analyzers/ProteinTranslationAnalyzer.cs b/src/Exercism.Analyzers.CSharp/Analyzers/ProteinTranslationAnalyzer.cs index 87e649f5..6c0cd526 100644 --- a/src/Exercism.Analyzers.CSharp/Analyzers/ProteinTranslationAnalyzer.cs +++ b/src/Exercism.Analyzers.CSharp/Analyzers/ProteinTranslationAnalyzer.cs @@ -2,12 +2,8 @@ namespace Exercism.Analyzers.CSharp.Analyzers; -internal class ProteinTranslationAnalyzer : Analyzer -{ - public ProteinTranslationAnalyzer(Submission submission) : base(submission) - { - } - +internal class ProteinTranslationAnalyzer(Submission submission) : Analyzer(submission) +{ public override void VisitInvocationExpression(InvocationExpressionSyntax node) { switch (GetSymbolName(node)) diff --git a/src/Exercism.Analyzers.CSharp/Analyzers/RaindropsAnalyzer.cs b/src/Exercism.Analyzers.CSharp/Analyzers/RaindropsAnalyzer.cs index 498af3ec..76ca5e2d 100644 --- a/src/Exercism.Analyzers.CSharp/Analyzers/RaindropsAnalyzer.cs +++ b/src/Exercism.Analyzers.CSharp/Analyzers/RaindropsAnalyzer.cs @@ -3,12 +3,8 @@ namespace Exercism.Analyzers.CSharp.Analyzers; -internal class RaindropsAnalyzer : Analyzer +internal class RaindropsAnalyzer(Submission submission) : Analyzer(submission) { - public RaindropsAnalyzer(Submission submission) : base(submission) - { - } - public override void VisitInvocationExpression(InvocationExpressionSyntax node) { if (GetSymbol(node) is IMethodSymbol methodSymbol && diff --git a/src/Exercism.Analyzers.CSharp/Analyzers/ReverseStringAnalyzer.cs b/src/Exercism.Analyzers.CSharp/Analyzers/ReverseStringAnalyzer.cs index 72a8f0bc..c6ee3fde 100644 --- a/src/Exercism.Analyzers.CSharp/Analyzers/ReverseStringAnalyzer.cs +++ b/src/Exercism.Analyzers.CSharp/Analyzers/ReverseStringAnalyzer.cs @@ -2,12 +2,8 @@ namespace Exercism.Analyzers.CSharp.Analyzers; -internal class ReverseStringAnalyzer : Analyzer +internal class ReverseStringAnalyzer(Submission submission) : Analyzer(submission) { - public ReverseStringAnalyzer(Submission submission) : base(submission) - { - } - public override void VisitInvocationExpression(InvocationExpressionSyntax node) { if (GetConstructedFromSymbolName(node) == "System.Array.Reverse(T[])") diff --git a/src/Exercism.Analyzers.CSharp/Analyzers/TagAnalyzer.cs b/src/Exercism.Analyzers.CSharp/Analyzers/TagAnalyzer.cs index 399a9ef1..9b6f1583 100644 --- a/src/Exercism.Analyzers.CSharp/Analyzers/TagAnalyzer.cs +++ b/src/Exercism.Analyzers.CSharp/Analyzers/TagAnalyzer.cs @@ -1,7 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; - using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -9,12 +5,8 @@ namespace Exercism.Analyzers.CSharp.Analyzers; -internal class TagAnalyzer : Analyzer +internal class TagAnalyzer(Submission submission) : Analyzer(submission, SyntaxWalkerDepth.Trivia) { - public TagAnalyzer(Submission submission) : base(submission, SyntaxWalkerDepth.Trivia) - { - } - public override void VisitForStatement(ForStatementSyntax node) { AddTags(Tags.ConstructForLoop, Tags.TechniqueLooping); @@ -204,7 +196,7 @@ public override void VisitInvocationExpression(InvocationExpressionSyntax node) { AddTags(Tags.ConstructInvocation, Tags.ConstructMethod); - if (GetSymbol(node) is not null && GetSymbol(node).ContainingNamespace.ToDisplayString() == "System.Linq") + if (GetSymbol(node)?.ContainingNamespace.ToDisplayString() == "System.Linq") AddTags(Tags.ConstructLinq, Tags.ParadigmFunctional); if (GetSymbolName(node) == "object.GetType()") diff --git a/src/Exercism.Analyzers.CSharp/Analyzers/TwoFerAnalyzer.cs b/src/Exercism.Analyzers.CSharp/Analyzers/TwoFerAnalyzer.cs index d515ae6b..6abd682e 100644 --- a/src/Exercism.Analyzers.CSharp/Analyzers/TwoFerAnalyzer.cs +++ b/src/Exercism.Analyzers.CSharp/Analyzers/TwoFerAnalyzer.cs @@ -2,12 +2,8 @@ namespace Exercism.Analyzers.CSharp.Analyzers; -internal class TwoFerAnalyzer : Analyzer +internal class TwoFerAnalyzer(Submission submission) : Analyzer(submission) { - public TwoFerAnalyzer(Submission submission) : base(submission) - { - } - public override void VisitMethodDeclaration(MethodDeclarationSyntax node) { switch (GetDeclaredSymbolName(node)) diff --git a/src/Exercism.Analyzers.CSharp/Analyzers/WeighingMachineAnalyzer.cs b/src/Exercism.Analyzers.CSharp/Analyzers/WeighingMachineAnalyzer.cs index 977b23e9..196a806e 100644 --- a/src/Exercism.Analyzers.CSharp/Analyzers/WeighingMachineAnalyzer.cs +++ b/src/Exercism.Analyzers.CSharp/Analyzers/WeighingMachineAnalyzer.cs @@ -1,24 +1,18 @@ -using System.Linq; - -using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Exercism.Analyzers.CSharp.Analyzers; -internal class WeighingMachineAnalyzer : Analyzer +internal class WeighingMachineAnalyzer(Submission submission) : Analyzer(submission) { - public WeighingMachineAnalyzer(Submission submission) : base(submission) - { - } - public override void VisitPropertyDeclaration(PropertyDeclarationSyntax node) { switch (GetDeclaredSymbolName(node)) { case "WeighingMachine.DisplayWeight": { - SyntaxNode getter = node.ExpressionBody == null + SyntaxNode? getter = node.ExpressionBody == null ? node.DescendantNodes() .OfType() .FirstOrDefault( diff --git a/src/Exercism.Analyzers.CSharp/Exercism.Analyzers.CSharp.csproj b/src/Exercism.Analyzers.CSharp/Exercism.Analyzers.CSharp.csproj index 396b74d4..857f11f4 100644 --- a/src/Exercism.Analyzers.CSharp/Exercism.Analyzers.CSharp.csproj +++ b/src/Exercism.Analyzers.CSharp/Exercism.Analyzers.CSharp.csproj @@ -4,6 +4,8 @@ net10.0 Exe true + enable + enable diff --git a/src/Exercism.Analyzers.CSharp/Loader.cs b/src/Exercism.Analyzers.CSharp/Loader.cs index b86f98a1..31f8a429 100644 --- a/src/Exercism.Analyzers.CSharp/Loader.cs +++ b/src/Exercism.Analyzers.CSharp/Loader.cs @@ -1,10 +1,5 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; using System.Text.Json; using System.Text.Json.Nodes; -using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -51,7 +46,7 @@ private static HashSet NonSubmissionFiles(Options options) return nonSubmissionFileKeys .Where(filesConfig.ContainsKey) - .SelectMany(key => filesConfig[key].Deserialize>()) + .SelectMany(key => filesConfig[key].Deserialize>()!) .Select(relativePath => Path.Combine(options.InputDirectory, relativePath)) .ToHashSet(); } @@ -77,7 +72,7 @@ private static CSharpCompilationOptions CompilationOptions() => new(OutputKind.DynamicallyLinkedLibrary, optimizationLevel: OptimizationLevel.Debug); private static IEnumerable References() => - ((string)AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES"))!.Split(Path.PathSeparator) + ((string)AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES")!).Split(Path.PathSeparator) .Select(p => MetadataReference.CreateFromFile(p)); } } \ No newline at end of file diff --git a/src/Exercism.Analyzers.CSharp/Output.cs b/src/Exercism.Analyzers.CSharp/Output.cs index c8a8e99e..24f516a6 100644 --- a/src/Exercism.Analyzers.CSharp/Output.cs +++ b/src/Exercism.Analyzers.CSharp/Output.cs @@ -1,7 +1,3 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; using System.Text; using System.Text.Encodings.Web; using System.Text.Json; diff --git a/src/Exercism.Analyzers.CSharp/Program.cs b/src/Exercism.Analyzers.CSharp/Program.cs index e8cbe11d..f45f4b2b 100644 --- a/src/Exercism.Analyzers.CSharp/Program.cs +++ b/src/Exercism.Analyzers.CSharp/Program.cs @@ -1,6 +1,3 @@ -using System; -using System.Threading.Tasks; - namespace Exercism.Analyzers.CSharp; internal record Options(string Slug, string InputDirectory, string OutputDirectory);