Skip to content

Commit

Permalink
cleaning up
Browse files Browse the repository at this point in the history
  • Loading branch information
Aaronontheweb committed Dec 22, 2023
1 parent 117be1c commit 055d009
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 16 deletions.
18 changes: 15 additions & 3 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<Copyright>Copyright © 2023 Your Company</Copyright>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<VersionPrefix>1.0.0</VersionPrefix>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>

<PropertyGroup Label="Build">
Expand All @@ -11,7 +12,18 @@
<Nullable>enable</Nullable>
</PropertyGroup>

<PropertyGroup Label="Dependencies">
<PbmVersion>1.3.0</PbmVersion>
</PropertyGroup>
<!-- ======================================== -->
<!-- Production-specific properties and items -->

<Choose>
<When Condition=" !$(MSBuildProjectName.Contains('.tests')) ">
<PropertyGroup>
<AnalysisLevel>latest-All</AnalysisLevel>
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)signing.snk</AssemblyOriginatorKeyFile>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
</PropertyGroup>
</When>
</Choose>
</Project>
8 changes: 8 additions & 0 deletions akka.analyzers.sln
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Analyzers", "src\Akka.Analyzers\Akka.Analyzers.csproj", "{C9D5BDA8-E4AF-4A83-948B-C1010A5592CE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{B67B6FBE-1946-404D-BE35-462B6EEAF1E2}"
ProjectSection(SolutionItems) = preProject
Directory.Build.props = Directory.Build.props
Directory.Packages.props = Directory.Packages.props
global.json = global.json
nuget.config = nuget.config
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down
36 changes: 36 additions & 0 deletions src/Akka.Analyzers/AK1000/MustNotUseNewKeywordOnActors.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// -----------------------------------------------------------------------
// <copyright file="MustNotUseNewKeywordOnActors.cs" company="Akka.NET Project">
// Copyright (C) 2015-2023 .NET Petabridge, LLC
// </copyright>
// -----------------------------------------------------------------------

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;

namespace Akka.Analyzers;

[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class MustNotUseNewKeywordOnActors() : AkkaDiagnosticAnalyzer(RuleDescriptors.Ak1000DoNotNewActors)
{
public override void AnalyzeCompilation(CompilationStartAnalysisContext context, AkkaContext akkaContext)
{
Guard.AssertIsNotNull(context);
Guard.AssertIsNotNull(akkaContext);

context.RegisterSyntaxNodeAction(ctx =>
{
var objectCreation = (ObjectCreationExpressionSyntax) ctx.Node;

var typeSymbol = ModelExtensions.GetTypeInfo(ctx.SemanticModel, objectCreation).Type;
if (typeSymbol is null)
return;

if (typeSymbol.IsActorType(akkaContext.AkkaCore))

Check failure on line 30 in src/Akka.Analyzers/AK1000/MustNotUseNewKeywordOnActors.cs

View workflow job for this annotation

GitHub Actions / Test-ubuntu-latest

'ITypeSymbol' does not contain a definition for 'IsActorType' and no accessible extension method 'IsActorType' accepting a first argument of type 'ITypeSymbol' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 30 in src/Akka.Analyzers/AK1000/MustNotUseNewKeywordOnActors.cs

View workflow job for this annotation

GitHub Actions / Test-ubuntu-latest

'ITypeSymbol' does not contain a definition for 'IsActorType' and no accessible extension method 'IsActorType' accepting a first argument of type 'ITypeSymbol' could be found (are you missing a using directive or an assembly reference?)
{
ctx.ReportDiagnostic(Diagnostic.Create(RuleDescriptors.Ak1000DoNotNewActors, objectCreation.GetLocation()));
}
}, SyntaxKind.ObjectCreationExpression);
}
}
1 change: 1 addition & 0 deletions src/Akka.Analyzers/Akka.Analyzers.csproj.DotSettings
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=ak1000/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=utility/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// -----------------------------------------------------------------------
// <copyright file="IAkkaContext.cs" company="Akka.NET Project">
// <copyright file="AkkaContext.cs" company="Akka.NET Project">
// Copyright (C) 2015-2023 .NET Petabridge, LLC
// </copyright>
// -----------------------------------------------------------------------
Expand All @@ -13,25 +13,32 @@ namespace Akka.Analyzers;
/// </summary>
public class AkkaContext
{
private IAkkaCoreContext? _akkaCore;

/// <summary>
/// Initializes a new instance of the <see cref="AkkaContext"/> class.
/// </summary>
/// <param name="compilation">The Roslyn compilation object used to look up types and
/// inspect references</param>
public AkkaContext(Compilation compilation)
{
AkkaCore = AkkaCoreContext.Get(compilation);
_akkaCore = AkkaCoreContext.Get(compilation);
}

private AkkaContext()
{
}

private AkkaContext(){}


/// <summary>
/// Data about the core Akka.NET library.
/// </summary>
public IAkkaCoreContext? AkkaCore { get; private set; }

public IAkkaCoreContext AkkaCore
{
get { return _akkaCore ??= EmptyCoreContext.Instance; }
}

/// <summary>
/// Does the current compilation context even have Akka.NET installed?
/// </summary>
public bool HasAkkaInstalled => AkkaCore is not null;
public bool HasAkkaInstalled => AkkaCore is not null;
}
22 changes: 20 additions & 2 deletions src/Akka.Analyzers/Utility/AkkaCoreContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ public interface IAkkaCoreContext
/// Gets the version number of the core Akka.NET assembly.
/// </summary>
Version Version { get; }

public INamedTypeSymbol? ActorBaseType { get; }
public INamedTypeSymbol? ActorRefType { get; }
public INamedTypeSymbol? PropsType { get; }
}

/// <summary>
Expand All @@ -25,6 +29,9 @@ private EmptyCoreContext()
public static EmptyCoreContext Instance { get; } = new();

public Version Version { get; } = new();
public INamedTypeSymbol? ActorBaseType => null;
public INamedTypeSymbol? ActorRefType => null;
public INamedTypeSymbol? PropsType => null;
}

/// <summary>
Expand All @@ -36,13 +43,24 @@ private EmptyCoreContext()
/// </remarks>
public class AkkaCoreContext : IAkkaCoreContext
{
private AkkaCoreContext(Version version)
private readonly Lazy<INamedTypeSymbol?> _lazyActorBaseType;
private readonly Lazy<INamedTypeSymbol?> _lazyActorRefType;
private readonly Lazy<INamedTypeSymbol?> _lazyPropsType;

private AkkaCoreContext(Compilation compilation, Version version)
{
Version = version;
_lazyActorBaseType = new(() => TypeSymbolFactory.ActorBase(compilation));
_lazyActorRefType = new(() => TypeSymbolFactory.ActorReference(compilation));
_lazyPropsType = new(() => TypeSymbolFactory.Props(compilation));
}

/// <inheritdoc/>
public Version Version { get; }

public INamedTypeSymbol? ActorBaseType => _lazyActorBaseType.Value;
public INamedTypeSymbol? ActorRefType => _lazyActorRefType.Value;
public INamedTypeSymbol? PropsType => _lazyPropsType.Value;

public static AkkaCoreContext? Get(
Compilation compilation,
Expand All @@ -58,6 +76,6 @@ private AkkaCoreContext(Version version)
.FirstOrDefault(a => a.Name.Equals("Akka", StringComparison.OrdinalIgnoreCase))
?.Version;

return version is null ? null : new AkkaCoreContext(version);
return version is null ? null : new AkkaCoreContext(compilation, version);
}
}
6 changes: 3 additions & 3 deletions src/Akka.Analyzers/Utility/AnalysisCategory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public enum AnalysisCategory

public static class RuleDescriptors
{
static DiagnosticDescriptor Rule(
private static DiagnosticDescriptor Rule(
string id,
string title,
AnalysisCategory category,
Expand All @@ -32,11 +32,11 @@ static DiagnosticDescriptor Rule(
isEnabledByDefault: true, helpLinkUri: helpLink);
}

public static DiagnosticDescriptor AK1000_DoNotNewActors { get; } = Rule("Akka1000",
public static DiagnosticDescriptor Ak1000DoNotNewActors { get; } = Rule("Akka1000",
"Do not use `new` to create actors", AnalysisCategory.ActorDesign, DiagnosticSeverity.Error,
"Actors must be instantiated using `ActorOf` or `ActorOfAsTestActorRef` via a `Props` class.");

public static DiagnosticDescriptor AK1001_CloseOverSenderUsingPipeTo { get; } = Rule("Akka1002",
public static DiagnosticDescriptor Ak1001CloseOverSenderUsingPipeTo { get; } = Rule("Akka1002",
"Should always close over `Sender` when using `PipeTo`", AnalysisCategory.ActorDesign, DiagnosticSeverity.Error,
"When using `PipeTo`, you must always close over `Sender` to ensure that the actor's `Sender` property " +
"is captured at the time you're scheduling the `PipeTo`, as this value may change asynchronously.");
Expand Down
24 changes: 24 additions & 0 deletions src/Akka.Analyzers/Utility/CodeAnalysisExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// -----------------------------------------------------------------------
// <copyright file="CodeAnalysisExtensions.cs" company="Akka.NET Project">
// Copyright (C) 2015-2023 .NET Petabridge, LLC
// </copyright>
// -----------------------------------------------------------------------

using Microsoft.CodeAnalysis;

namespace Akka.Analyzers;

internal static class CodeAnalysisExtensions
{
public static bool IsInsidePropsCreateMethod(this IOperation operation,
AkkaContext akkaContext)
{
Guard.AssertIsNotNull(operation);
Guard.AssertIsNotNull(akkaContext);

if (akkaContext.AkkaCore.PropsType is null)
return false;

return methodSymbol.IsPropsCreateMethod(akkaContext);

Check failure on line 22 in src/Akka.Analyzers/Utility/CodeAnalysisExtensions.cs

View workflow job for this annotation

GitHub Actions / Test-ubuntu-latest

The name 'methodSymbol' does not exist in the current context

Check failure on line 22 in src/Akka.Analyzers/Utility/CodeAnalysisExtensions.cs

View workflow job for this annotation

GitHub Actions / Test-ubuntu-latest

The name 'methodSymbol' does not exist in the current context
}
}
21 changes: 21 additions & 0 deletions src/Akka.Analyzers/Utility/TypeSymbolFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// -----------------------------------------------------------------------
// <copyright file="TypeSymbolFactory.cs" company="Akka.NET Project">
// Copyright (C) 2015-2023 .NET Petabridge, LLC
// </copyright>
// -----------------------------------------------------------------------

using Microsoft.CodeAnalysis;

namespace Akka.Analyzers;

public static class TypeSymbolFactory
{
public static INamedTypeSymbol? ActorBase(Compilation compilation) => Guard.AssertIsNotNull(compilation)
.GetTypeByMetadataName("Akka.Actor.ActorBase");

public static INamedTypeSymbol? ActorReference(Compilation compilation) => Guard.AssertIsNotNull(compilation)
.GetTypeByMetadataName("Akka.Actor.IActorRef");

public static INamedTypeSymbol? Props(Compilation compilation) => Guard.AssertIsNotNull(compilation)
.GetTypeByMetadataName("Akka.Actor.Props");
}

0 comments on commit 055d009

Please sign in to comment.