-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add analyzer to ensure public API doesn't use Action or Func
- Loading branch information
Showing
21 changed files
with
269 additions
and
189 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
108 changes: 108 additions & 0 deletions
108
codehelp/CodeHelpers/ActionFuncDetector/Analyzer/ActionFuncDetector.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
using System.Collections.Immutable; | ||
using System.Diagnostics; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
|
||
namespace WPILib.CodeHelpers.ActionFuncDetector.Analyzer; | ||
|
||
[DiagnosticAnalyzer(LanguageNames.CSharp)] | ||
public sealed class ActionFuncDetector : DiagnosticAnalyzer | ||
{ | ||
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create([ | ||
ActionFuncDiagnostics.UseOfActionFunc | ||
]); | ||
|
||
public override void Initialize(AnalysisContext context) | ||
{ | ||
context.EnableConcurrentExecution(); | ||
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); | ||
context.RegisterSymbolAction(AnalyzeMethod, SymbolKind.Method); | ||
context.RegisterSymbolAction(AnalyzeProperty, SymbolKind.Property); | ||
context.RegisterSymbolAction(AnalyzeField, SymbolKind.Field); | ||
} | ||
|
||
private static void AnalyzeMethod(SymbolAnalysisContext context) | ||
{ | ||
if (context.Symbol is not IMethodSymbol methodSymbol) | ||
{ | ||
return; | ||
} | ||
|
||
if (methodSymbol.DeclaredAccessibility != Accessibility.Public) | ||
{ | ||
return; | ||
} | ||
|
||
if (TypeCheck(methodSymbol.ReturnType)) | ||
{ | ||
ReportDiagnostic(context, methodSymbol.ReturnType); | ||
} | ||
|
||
foreach (var parameter in methodSymbol.Parameters) | ||
{ | ||
if (TypeCheck(parameter.Type)) | ||
{ | ||
ReportDiagnostic(context, parameter); | ||
} | ||
} | ||
} | ||
|
||
private static void ReportDiagnostic(SymbolAnalysisContext context, ISymbol symbol) | ||
{ | ||
foreach (var location in symbol.Locations) | ||
{ | ||
context.ReportDiagnostic(Diagnostic.Create(ActionFuncDiagnostics.UseOfActionFunc, location)); | ||
} | ||
} | ||
|
||
private static void AnalyzeProperty(SymbolAnalysisContext context) | ||
{ | ||
if (context.Symbol is not IPropertySymbol propertySymbol) | ||
{ | ||
return; | ||
} | ||
|
||
if (propertySymbol.DeclaredAccessibility != Accessibility.Public) | ||
{ | ||
return; | ||
} | ||
|
||
if (TypeCheck(propertySymbol.Type)) | ||
{ | ||
ReportDiagnostic(context, propertySymbol.Type); | ||
} | ||
} | ||
|
||
private static bool TypeCheck(ITypeSymbol typeSymbol) | ||
{ | ||
var containingNamespace = typeSymbol.ContainingNamespace; | ||
if (containingNamespace is null) | ||
{ | ||
return false; | ||
} | ||
if (containingNamespace.Name != "System") | ||
{ | ||
return false; | ||
} | ||
var name = typeSymbol.Name; | ||
return name == "Action" || name == "Func"; | ||
} | ||
|
||
private static void AnalyzeField(SymbolAnalysisContext context) | ||
{ | ||
if (context.Symbol is not IFieldSymbol fieldSymbol) | ||
{ | ||
return; | ||
} | ||
|
||
if (fieldSymbol.DeclaredAccessibility != Accessibility.Public) | ||
{ | ||
return; | ||
} | ||
|
||
if (TypeCheck(fieldSymbol.Type)) | ||
{ | ||
ReportDiagnostic(context, fieldSymbol.Type); | ||
} | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
codehelp/CodeHelpers/ActionFuncDetector/Analyzer/ActionFuncDiagnostics.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
namespace WPILib.CodeHelpers.ActionFuncDetector.Analyzer; | ||
|
||
#pragma warning disable RS2008 // Enable analyzer release tracking | ||
|
||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
using WPILib.CodeHelpers; | ||
|
||
public static class ActionFuncDiagnostics | ||
{ | ||
public class Ids | ||
{ | ||
public const string Prefix = "WPILIB"; | ||
public const string UseOfActionFunc = Prefix + "1100"; | ||
} | ||
|
||
private const string Category = "AllowedPublicTypes"; | ||
|
||
public static readonly DiagnosticDescriptor UseOfActionFunc = new( | ||
Ids.UseOfActionFunc, "Action/Func is used in a public API", "Use of Action or Func in a public API is disallowed", Category, DiagnosticSeverity.Warning, false); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,15 @@ | ||
<Project> | ||
<PropertyGroup> | ||
<IsPackable>false</IsPackable> | ||
</PropertyGroup> | ||
</Project> | ||
<Project> | ||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<IsPackable>false</IsPackable> | ||
<Nullable>enable</Nullable> | ||
<OutputType>Exe</OutputType> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\src\hal\hal.csproj" /> | ||
<ProjectReference Include="..\..\src\ntcore\ntcore.csproj" /> | ||
<ProjectReference Include="..\..\src\wpilibsharp\wpilibsharp.csproj" /> | ||
<ProjectReference Include="..\..\src\wpiutil\wpiutil.csproj" /> | ||
</ItemGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,123 +1,23 @@ | ||
using System; | ||
using System.Runtime.CompilerServices; | ||
using WPILib; | ||
using WPILib.Counters; | ||
using WPILib.SmartDashboardNS; | ||
|
||
namespace roboRIODev | ||
namespace TestRobot; | ||
|
||
internal class Program | ||
{ | ||
public class Robot : TimedRobot | ||
private static void Main(string[] args) | ||
{ | ||
//private TimeSpan lastTime = Timer.FPGATimestamp; | ||
//double[] buffer = new double[50]; | ||
//int idx = 0; | ||
|
||
//private int can = CANAPI.Initialize(CANManufacturer.kTeamUse, 1, CANDeviceType.kMiscellaneous); | ||
|
||
private readonly PWMSparkMax sparkMax = new PWMSparkMax(0); | ||
private readonly DigitalInput di = new DigitalInput(0); | ||
private Tachometer absoluteTach; | ||
private readonly DigitalInput quadDI = new DigitalInput(1); | ||
private readonly DigitalInput quadDIB = new DigitalInput(2); | ||
private Tachometer quadratureTach; | ||
private UpDownCounter quadratureCounter; | ||
|
||
private ExternalDirectionCounter externalDirectionCounter; | ||
private ExternalDirectionCounter externalDirectionCounter2x; | ||
|
||
AsynchronousInterrupt interrupt; | ||
|
||
int count = 0; | ||
|
||
public override void RobotInit() | ||
{ | ||
absoluteTach = new Tachometer(di); | ||
quadratureTach = new Tachometer(quadDI); | ||
quadratureTach.EdgesPerRevolution = 2048; | ||
quadratureCounter = new UpDownCounter(); | ||
quadratureCounter.UpSource = quadDI; | ||
quadratureCounter.UpEdgeConfiguration = EdgeConfiguration.kRisingEdge; | ||
|
||
externalDirectionCounter = new ExternalDirectionCounter(quadDI, quadDIB); | ||
|
||
externalDirectionCounter2x = new ExternalDirectionCounter(quadDI, quadDIB); | ||
externalDirectionCounter2x.EdgeConfiguration = EdgeConfiguration.kBothEdges; | ||
externalDirectionCounter2x.ReverseDirection = true; | ||
|
||
DigitalGlitchFilter filter = new DigitalGlitchFilter(); | ||
filter.SetPeriod(TimeSpan.FromSeconds(1)); | ||
//filter.Add(di); | ||
|
||
interrupt = new AsynchronousInterrupt(di, (r, f) => | ||
{ | ||
Console.WriteLine("Interrupt Occured " + count); | ||
count++; | ||
//Thread.Sleep(20); | ||
}); | ||
|
||
interrupt.SetInterruptEdges(true, false); | ||
|
||
interrupt.Enable(); | ||
} | ||
|
||
|
||
|
||
public override unsafe void RobotPeriodic() | ||
{ | ||
SmartDashboard.PutNumber("External Dir Tach", externalDirectionCounter.Count); | ||
|
||
SmartDashboard.PutNumber("External Dir Tach 2x", externalDirectionCounter2x.Count); | ||
|
||
|
||
SmartDashboard.PutNumber("Absolute Tach", absoluteTach.RotationalSpeed?.RevolutionsPerSecond ?? double.MaxValue); | ||
|
||
SmartDashboard.PutNumber("Quadrature Tach", quadratureTach.RotationalSpeed?.RevolutionsPerSecond ?? 0); | ||
|
||
SmartDashboard.PutNumber("Quadrature Counter", quadratureCounter.Count); | ||
|
||
SmartDashboard.PutNumber("Joystick", DriverStation.Instance.GetStickAxis(0, 1)); | ||
sparkMax.Set(DriverStation.Instance.GetStickAxis(0, 1)); | ||
|
||
if (DriverStation.Instance.GetStickButton(0, 1)) | ||
{ | ||
Console.WriteLine("Disable"); | ||
interrupt.Disable(); | ||
} | ||
|
||
if (DriverStation.Instance.GetStickButton(0, 2)) | ||
{ | ||
Console.WriteLine("Enable"); | ||
interrupt.Enable(); | ||
} | ||
//sparkMax.SetVoltage(ElectricPotential.FromVolts(5)); | ||
//int idxLocal = idx; | ||
//try | ||
//{ | ||
// CANAPI.WritePacket(can, new Span<byte>(&idxLocal, 4), 42); | ||
//} | ||
//catch (UncleanStatusException ex) | ||
//{ | ||
// ; | ||
//} | ||
|
||
//var current = Timer.FPGATimestamp; | ||
//var delta = current - lastTime; | ||
//lastTime = current; | ||
//buffer[idx] = delta.TotalMilliseconds; | ||
//idx++; | ||
//if (idx == 50) | ||
//{ | ||
// Console.WriteLine(buffer.Average()); | ||
// idx = 0; | ||
//} | ||
//base.RobotPeriodic(); | ||
} | ||
RobotRunner.StartRobot<Robot>(); | ||
} | ||
} | ||
|
||
class Program | ||
internal static class RobotInitializer | ||
{ | ||
[ModuleInitializer] | ||
public static void Initialize() | ||
{ | ||
static void Main(string[] args) | ||
{ | ||
RobotBase.StartRobot<Robot>(); | ||
} | ||
// Force load the HAL, because we can't guarantee it won't be | ||
// accidentally used too early later | ||
RobotRunner.InitializeHAL(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
using WPILib; | ||
|
||
namespace TestRobot; | ||
|
||
public class Robot : RobotBase | ||
{ | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,8 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
<Packable>false</Packable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\src\hal\hal.csproj" /> | ||
<!--<ProjectReference Include="..\..\src\newcommands\newcommands.csproj" />--> | ||
<ProjectReference Include="..\..\src\ntcore\ntcore.csproj" /> | ||
<!--<ProjectReference Include="..\..\src\thirdparty\oblog\oblog.csproj" /> | ||
<ProjectReference Include="..\..\src\thirdparty\SparkMax\SparkMax.csproj" />--> | ||
<ProjectReference Include="..\..\src\wpilibsharp\wpilibsharp.csproj" /> | ||
<ProjectReference Include="..\..\src\wpiutil\wpiutil.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<RootNamespace>TestRobot</RootNamespace> | ||
</PropertyGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.