Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
6 changes: 5 additions & 1 deletion .github/workflows/Build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,8 @@ jobs:
with:
dotnet-version: '5.0.100'
- name: Build
run: dotnet build || dotnet build || dotnet build
run: |
dotnet build AngouriMath/AngouriMath.csproj
dotnet build FSharp/AngouriMath.FSharp.fsproj
dotnet build Analyzers/Analyzers/Analyzers.csproj
dotnet build Utils/Utils/Utils.csproj
19 changes: 19 additions & 0 deletions Analyzers/Analyzers.CodeFixes/Analyzers.CodeFixes.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<IsPackable>false</IsPackable>
<RootNamespace>Analyzers</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.8.0-5.final" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0-5.final" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.8.0-5.final" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Analyzers\Analyzers.csproj" />
</ItemGroup>

</Project>
40 changes: 40 additions & 0 deletions Analyzers/Analyzers.CodeFixes/FieldThreadSafetyCodeFixProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Rename;
using Microsoft.CodeAnalysis.Text;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Analyzers
{
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(FieldThreadSafetyCodeFixProvider)), Shared]
public class FieldThreadSafetyCodeFixProvider : CodeFixProvider
{
public sealed override ImmutableArray<string> FixableDiagnosticIds
{
get { return ImmutableArray.Create(EitherAbstractOrSealed.DiagnosticId); }
}

public sealed override FixAllProvider GetFixAllProvider()
{
// See https://github.com/dotnet/roslyn/blob/master/docs/analyzers/FixAllProvider.md for more information on Fix All Providers
return WellKnownFixAllProviders.BatchFixer;
}

#pragma warning disable CS1998 // To be implemented yet
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
#pragma warning restore CS1998
{

}

}
}
48 changes: 48 additions & 0 deletions Analyzers/Analyzers.Debug/Analyzers.Debug.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.props" />

<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<RootNamespace>Analyzers.Debug</RootNamespace>
<AssemblyName>Analyzers.Debug</AssemblyName>
<RuntimeIdentifiers>win</RuntimeIdentifiers>
</PropertyGroup>

<PropertyGroup>
<GeneratePkgDefFile>false</GeneratePkgDefFile>
<IncludeAssemblyInVSIXContainer>false</IncludeAssemblyInVSIXContainer>
<IncludeDebugSymbolsInVSIXContainer>false</IncludeDebugSymbolsInVSIXContainer>
<IncludeDebugSymbolsInLocalVSIXDeployment>false</IncludeDebugSymbolsInLocalVSIXDeployment>
<CopyBuildOutputToOutputDirectory>false</CopyBuildOutputToOutputDirectory>
<CopyOutputSymbolsToOutputDirectory>false</CopyOutputSymbolsToOutputDirectory>
<VSSDKTargetPlatformRegRootSuffix>Roslyn</VSSDKTargetPlatformRegRootSuffix>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.VSSDK.BuildTools" Version="16.8.3038" PrivateAssets="all" />
</ItemGroup>

<PropertyGroup>
<StartAction>Program</StartAction>
<StartProgram>$(DevEnvDir)devenv.exe</StartProgram>
<StartArguments>/rootsuffix $(VSSDKTargetPlatformRegRootSuffix)</StartArguments>
</PropertyGroup>

<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.targets" />

<Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="Exists('$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets')" />

<ItemGroup>
<ProjectReference Include="..\Analyzers\Analyzers.csproj" />
</ItemGroup>

<ItemGroup>
<!-- https://github.com/dotnet/sdk/issues/433 -->
<ProjectReference Update="@(ProjectReference)" AdditionalProperties="TargetFramework=netstandard2.0" />

<!-- https://github.com/Microsoft/extendvs/issues/57 -->
<ProjectReference Update="@(ProjectReference)" Name="%(Filename)" />
</ItemGroup>

</Project>
22 changes: 22 additions & 0 deletions Analyzers/Analyzers.Debug/source.extension.vsixmanifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
<Metadata>
<Identity Id="Analyzers.c9a942cf-9b0a-42c5-919d-f19e6d6de801" Version="1.0" Language="en-US" Publisher="goose"/>
<DisplayName>Analyzers</DisplayName>
<Description xml:space="preserve">This extension allows to easily debug analyzers for AngouriMath</Description>
</Metadata>
<Installation>
<InstallationTarget Id="Microsoft.VisualStudio.Community" Version="[15.0,)" />
</Installation>
<Dependencies>
<Dependency Id="Microsoft.Framework.NDP" DisplayName="Microsoft .NET Framework" d:Source="Manual" Version="[4.5,)" />
</Dependencies>
<Assets>
<Asset Type="Microsoft.VisualStudio.MefComponent" d:Source="Project" d:ProjectName="Analyzers" Path="|Analyzers|"/>
<Asset Type="Microsoft.VisualStudio.Analyzer" d:Source="Project" d:ProjectName="Analyzers" Path="|Analyzers|"/>
</Assets>
<Prerequisites>
<Prerequisite Id="Microsoft.VisualStudio.Component.CoreEditor" Version="[15.0,)" DisplayName="Visual Studio core editor" />
<Prerequisite Id="Microsoft.VisualStudio.Component.Roslyn.LanguageServices" Version="[15.0,)" DisplayName="Roslyn Language Services" />
</Prerequisites>
</PackageManifest>
19 changes: 19 additions & 0 deletions Analyzers/Analyzers/Analyzers.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<IsPackable>false</IsPackable>

<!-- Avoid ID conflicts with the package project. -->
<PackageId>*$(MSBuildProjectFullPath)*</PackageId>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0-5.final" />
</ItemGroup>

</Project>
45 changes: 45 additions & 0 deletions Analyzers/Analyzers/EitherAbstractOrSealed.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;


namespace Analyzers
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class EitherAbstractOrSealed : DiagnosticAnalyzer
{
public const string DiagnosticId = "SealedOrAbstract";
private static readonly string Title = "AMAnalyzer";
private static readonly string MessageFormat = $"If a type is not sealed, it should be either static or abstract";
private static readonly string Description = "Unsafe type extension prevention.";
private const string Category = "Security";

private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Warning, isEnabledByDefault: true, description: Description);

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } }

public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();

context.RegisterSymbolAction(symbolContext =>
{
var typeDecl = (INamedTypeSymbol)symbolContext.Symbol;
var containingType = typeDecl.ContainingType;
if (!typeDecl.IsAbstract && !typeDecl.IsSealed && !typeDecl.IsStatic)
{
var diag = Diagnostic.Create(Rule, typeDecl.Locations.First());
symbolContext.ReportDiagnostic(diag);
}
}, SymbolKind.NamedType);
}
}
}
13 changes: 13 additions & 0 deletions Analyzers/Analyzers/GlobalSuppressions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.

using System.Diagnostics.CodeAnalysis;

// Most warnings about shipping are because we are not planning to ship
// this analyzer, it is exclusively for contributors of the project.

[assembly: SuppressMessage("MicrosoftCodeAnalysisReleaseTracking", "RS2008:Enable analyzer release tracking", Justification = "<Pending>", Scope = "member", Target = "~F:Analyzers.StaticFieldThreadSafety.RuleShouldBeNull")]
[assembly: SuppressMessage("MicrosoftCodeAnalysisReleaseTracking", "RS2008:Enable analyzer release tracking", Justification = "<Pending>", Scope = "member", Target = "~F:Analyzers.StaticFieldThreadSafety.RuleAddAttribute")]
[assembly: SuppressMessage("MicrosoftCodeAnalysisReleaseTracking", "RS2008:Enable analyzer release tracking", Justification = "<Pending>", Scope = "member", Target = "~F:Analyzers.EitherAbstractOrSealed.Rule")]
80 changes: 80 additions & 0 deletions Analyzers/Analyzers/StaticFieldThreadSafety.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;

namespace Analyzers
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class StaticFieldThreadSafety : DiagnosticAnalyzer
{
public const string DiagnosticId = "ThreadSafety";

private static readonly DiagnosticDescriptor RuleAddAttribute =
new DiagnosticDescriptor(
id: DiagnosticId,
title: "AMAnalyzer",
messageFormat: "A static field should have either [ConstantField] attribute or [ThreadStatic] (for cache)",
category: "Security",
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
description: "Data corruption prevention.");

private static readonly DiagnosticDescriptor RuleShouldBeNull =
new DiagnosticDescriptor(
id: DiagnosticId,
title: "AMAnalyzer",
messageFormat: "A thread static field should have no initialization (instead, should have an additional nullable backing field)",
category: "Security",
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
description: "Non-initialized field prevention.");

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(RuleAddAttribute); } }

public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();

context.RegisterSymbolAction(symbolContext =>
{
var fieldDecl = (IFieldSymbol)symbolContext.Symbol;
var hasConstantFieldAttribute = fieldDecl.GetAttributes().Any(attr => attr.AttributeClass?.Name == "ConstantFieldAttribute");
var hasThreadStaticAttribute = fieldDecl.GetAttributes().Any(attr => attr.AttributeClass?.Name == "ThreadStaticAttribute");
if (fieldDecl.IsStatic &&
!fieldDecl.IsConst &&
!hasThreadStaticAttribute
&&
!hasConstantFieldAttribute
&&
fieldDecl.Type.Name != "ConditionalWeakTable"
)
{
var diag = Diagnostic.Create(RuleAddAttribute, fieldDecl.Locations.First());
symbolContext.ReportDiagnostic(diag);
}
if (hasThreadStaticAttribute)
{
var syntaxTree = fieldDecl.DeclaringSyntaxReferences.First().GetSyntax();
if (syntaxTree is VariableDeclaratorSyntax variableDeclarator)
{
if (variableDeclarator.Initializer is not null)
{
var diag = Diagnostic.Create(RuleShouldBeNull, fieldDecl.Locations.First());
#pragma warning disable RS1005 // ReportDiagnostic invoked with an unsupported DiagnosticDescriptor
symbolContext.ReportDiagnostic(diag);
#pragma warning restore RS1005 // ReportDiagnostic invoked with an unsupported DiagnosticDescriptor
}
}
}
}, SymbolKind.Field);
}
}
}
37 changes: 37 additions & 0 deletions AngouriMath.sln
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleNet5", "Samples\Sampl
EndProject
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharpSample", "Samples\FSharpSample\FSharpSample.fsproj", "{E1848158-0D50-4762-BC06-DAC5DF47DCB2}"
EndProject
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "AngouriMath.FSharp", "FSharp\AngouriMath.FSharp.fsproj", "{4EB32057-7AD8-4C58-A25C-A666ACBDAA12}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Analyzers", "Analyzers\Analyzers\Analyzers.csproj", "{A37A22C6-40C6-4B11-BCF4-65A61CBD4AD5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Analyzers.CodeFixes", "Analyzers\Analyzers.CodeFixes\Analyzers.CodeFixes.csproj", "{DBE2D86F-482E-418F-9A6B-298B4EF1DB27}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Analyzers", "Analyzers", "{7B0F7A1A-7C84-4B17-85D0-24BBCAA18826}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Analyzers.Debug", "Analyzers\Analyzers.Debug\Analyzers.Debug.csproj", "{DAE7E49D-A474-4776-91CF-3368E9C56F3D}"
EndProject
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "AngouriMath.FSharp", "Wrappers\FSharp\AngouriMath.FSharp.fsproj", "{4EB32057-7AD8-4C58-A25C-A666ACBDAA12}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Wrappers", "Wrappers", "{C82FFADF-2F2F-4B8D-BB32-2D2F149FED4D}"
Expand Down Expand Up @@ -134,6 +144,30 @@ Global
{4EB32057-7AD8-4C58-A25C-A666ACBDAA12}.Release|Any CPU.Build.0 = Release|Any CPU
{4EB32057-7AD8-4C58-A25C-A666ACBDAA12}.Release|x64.ActiveCfg = Release|Any CPU
{4EB32057-7AD8-4C58-A25C-A666ACBDAA12}.Release|x64.Build.0 = Release|Any CPU
{A37A22C6-40C6-4B11-BCF4-65A61CBD4AD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A37A22C6-40C6-4B11-BCF4-65A61CBD4AD5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A37A22C6-40C6-4B11-BCF4-65A61CBD4AD5}.Debug|x64.ActiveCfg = Debug|Any CPU
{A37A22C6-40C6-4B11-BCF4-65A61CBD4AD5}.Debug|x64.Build.0 = Debug|Any CPU
{A37A22C6-40C6-4B11-BCF4-65A61CBD4AD5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A37A22C6-40C6-4B11-BCF4-65A61CBD4AD5}.Release|Any CPU.Build.0 = Release|Any CPU
{A37A22C6-40C6-4B11-BCF4-65A61CBD4AD5}.Release|x64.ActiveCfg = Release|Any CPU
{A37A22C6-40C6-4B11-BCF4-65A61CBD4AD5}.Release|x64.Build.0 = Release|Any CPU
{DBE2D86F-482E-418F-9A6B-298B4EF1DB27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DBE2D86F-482E-418F-9A6B-298B4EF1DB27}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DBE2D86F-482E-418F-9A6B-298B4EF1DB27}.Debug|x64.ActiveCfg = Debug|Any CPU
{DBE2D86F-482E-418F-9A6B-298B4EF1DB27}.Debug|x64.Build.0 = Debug|Any CPU
{DBE2D86F-482E-418F-9A6B-298B4EF1DB27}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DBE2D86F-482E-418F-9A6B-298B4EF1DB27}.Release|Any CPU.Build.0 = Release|Any CPU
{DBE2D86F-482E-418F-9A6B-298B4EF1DB27}.Release|x64.ActiveCfg = Release|Any CPU
{DBE2D86F-482E-418F-9A6B-298B4EF1DB27}.Release|x64.Build.0 = Release|Any CPU
{DAE7E49D-A474-4776-91CF-3368E9C56F3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DAE7E49D-A474-4776-91CF-3368E9C56F3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DAE7E49D-A474-4776-91CF-3368E9C56F3D}.Debug|x64.ActiveCfg = Debug|Any CPU
{DAE7E49D-A474-4776-91CF-3368E9C56F3D}.Debug|x64.Build.0 = Debug|Any CPU
{DAE7E49D-A474-4776-91CF-3368E9C56F3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DAE7E49D-A474-4776-91CF-3368E9C56F3D}.Release|Any CPU.Build.0 = Release|Any CPU
{DAE7E49D-A474-4776-91CF-3368E9C56F3D}.Release|x64.ActiveCfg = Release|Any CPU
{DAE7E49D-A474-4776-91CF-3368E9C56F3D}.Release|x64.Build.0 = Release|Any CPU
{13618971-EDBB-4C64-A0FF-F66AE17778E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{13618971-EDBB-4C64-A0FF-F66AE17778E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{13618971-EDBB-4C64-A0FF-F66AE17778E3}.Debug|x64.ActiveCfg = Debug|Any CPU
Expand All @@ -154,6 +188,9 @@ Global
{B7D28355-A342-4E6E-AD45-3D47F4A054A5} = {D15528F2-AB50-46E2-9DB1-821B278C4931}
{0116746A-3B68-4B75-A926-D9B8E7E87571} = {D15528F2-AB50-46E2-9DB1-821B278C4931}
{E1848158-0D50-4762-BC06-DAC5DF47DCB2} = {D15528F2-AB50-46E2-9DB1-821B278C4931}
{A37A22C6-40C6-4B11-BCF4-65A61CBD4AD5} = {7B0F7A1A-7C84-4B17-85D0-24BBCAA18826}
{DBE2D86F-482E-418F-9A6B-298B4EF1DB27} = {7B0F7A1A-7C84-4B17-85D0-24BBCAA18826}
{DAE7E49D-A474-4776-91CF-3368E9C56F3D} = {7B0F7A1A-7C84-4B17-85D0-24BBCAA18826}
{4EB32057-7AD8-4C58-A25C-A666ACBDAA12} = {C82FFADF-2F2F-4B8D-BB32-2D2F149FED4D}
{13618971-EDBB-4C64-A0FF-F66AE17778E3} = {C82FFADF-2F2F-4B8D-BB32-2D2F149FED4D}
EndGlobalSection
Expand Down
4 changes: 4 additions & 0 deletions AngouriMath/AngouriMath.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,9 @@ Preview 3: Derive -&gt; Differentiate, now all calculus functions apply InnerSim
<PackageReference Include="PeterO.Numbers" Version="1.7.4" />
<PackageReference Include="System.Memory" Version="4.5.4" />
<PackageReference Include="Nullable" Version="1.3.0" PrivateAssets="all" />
<ProjectReference Include="../Analyzers/Analyzers/Analyzers.csproj"
PrivateAssets="all"
ReferenceOutputAssembly="false"
OutputItemType="Analyzer" />
</ItemGroup>
</Project>
Loading