mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-14 19:29:36 +01:00
Analyzer to make Task`1.Result scary. (#3069)
This commit is contained in:
committed by
GitHub
parent
0ec6995542
commit
ec70abe928
@@ -8,6 +8,7 @@ public static class Diagnostics
|
||||
public const string IdSerializable = "RA0001";
|
||||
public const string IdAccess = "RA0002";
|
||||
public const string IdExplicitVirtual = "RA0003";
|
||||
public const string IdTaskResult = "RA0004";
|
||||
|
||||
public static SuppressionDescriptor MeansImplicitAssignment =>
|
||||
new SuppressionDescriptor("RADC1000", "CS0649", "Marked as implicitly assigned.");
|
||||
|
||||
44
Robust.Analyzers/TaskResultAnalyzer.cs
Normal file
44
Robust.Analyzers/TaskResultAnalyzer.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.Diagnostics;
|
||||
using Microsoft.CodeAnalysis.Operations;
|
||||
|
||||
namespace Robust.Analyzers;
|
||||
|
||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||
public sealed class TaskResultAnalyzer : DiagnosticAnalyzer
|
||||
{
|
||||
[SuppressMessage("ReSharper", "RS2008")]
|
||||
private static readonly DiagnosticDescriptor ResultRule = new DiagnosticDescriptor(
|
||||
Diagnostics.IdTaskResult,
|
||||
"Risk of deadlock from accessing Task<T>.Result",
|
||||
"Accessing Task<T>.Result is dangerous and can cause deadlocks in some contexts. If you understand how this works and are certain that you aren't causing a deadlock here, mute this error with #pragma.",
|
||||
"Usage",
|
||||
DiagnosticSeverity.Error,
|
||||
true);
|
||||
|
||||
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics =>
|
||||
ImmutableArray.Create(ResultRule);
|
||||
|
||||
public override void Initialize(AnalysisContext context)
|
||||
{
|
||||
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
|
||||
context.EnableConcurrentExecution();
|
||||
context.RegisterOperationAction(Check, OperationKind.PropertyReference);
|
||||
}
|
||||
|
||||
private static void Check(OperationAnalysisContext context)
|
||||
{
|
||||
var taskType = context.Compilation.GetTypeByMetadataName("System.Threading.Tasks.Task`1");
|
||||
|
||||
var operation = (IPropertyReferenceOperation) context.Operation;
|
||||
var member = operation.Member;
|
||||
|
||||
if (member.Name == "Result" && taskType.Equals(member.ContainingType.ConstructedFrom, SymbolEqualityComparer.Default))
|
||||
{
|
||||
var diag = Diagnostic.Create(ResultRule, operation.Syntax.GetLocation());
|
||||
context.ReportDiagnostic(diag);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -132,7 +132,9 @@ namespace Robust.Client.Graphics.Clyde
|
||||
_cmdWriter.Complete();
|
||||
|
||||
// Drain command queue ignoring it until the window thread confirms completion.
|
||||
#pragma warning disable RA0004
|
||||
while (_eventReader.WaitToReadAsync().AsTask().Result)
|
||||
#pragma warning restore RA0004
|
||||
{
|
||||
_eventReader.TryRead(out _);
|
||||
}
|
||||
|
||||
@@ -260,8 +260,9 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
// Block the main thread (to avoid stuff like texture uploads being problematic).
|
||||
WaitWindowCreate(task);
|
||||
|
||||
#pragma warning disable RA0004
|
||||
var (reg, errorResult) = task.Result;
|
||||
#pragma warning restore RA0004
|
||||
|
||||
if (reg != null)
|
||||
{
|
||||
|
||||
@@ -113,7 +113,9 @@ internal partial class Clyde
|
||||
_cmdWriter.Complete();
|
||||
|
||||
// Drain command queue ignoring it until the window thread confirms completion.
|
||||
#pragma warning disable RA0004
|
||||
while (_eventReader.WaitToReadAsync().AsTask().Result)
|
||||
#pragma warning restore RA0004
|
||||
{
|
||||
_eventReader.TryRead(out _);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,10 @@ internal partial class Clyde
|
||||
// Block the main thread (to avoid stuff like texture uploads being problematic).
|
||||
WaitWindowCreate(task);
|
||||
|
||||
#pragma warning disable RA0004
|
||||
// Block above ensured task is done, this is safe.
|
||||
var (reg, error) = task.Result;
|
||||
#pragma warning restore RA0004
|
||||
if (reg != null)
|
||||
{
|
||||
reg.Owner = reg.Handle;
|
||||
|
||||
@@ -170,7 +170,9 @@ namespace Robust.Shared.ContentPack
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma warning disable RA0004
|
||||
var loadedConfig = _config.Result;
|
||||
#pragma warning restore RA0004
|
||||
|
||||
// We still do explicit type reference scanning, even though the actual whitelists work with raw members.
|
||||
// This is so that we can simplify handling of generic type specifications during member checking:
|
||||
@@ -233,7 +235,9 @@ namespace Robust.Shared.ContentPack
|
||||
}
|
||||
});
|
||||
|
||||
#pragma warning disable RA0004
|
||||
var loadedCfg = _config.Result;
|
||||
#pragma warning restore RA0004
|
||||
|
||||
var verifyErrors = false;
|
||||
foreach (var res in bag)
|
||||
|
||||
@@ -373,7 +373,7 @@ namespace Robust.Shared.Network
|
||||
Logger.DebugS("net", "First peer failed.");
|
||||
firstPeer.Peer.Shutdown("You failed.");
|
||||
_toCleanNetPeers.Add(firstPeer.Peer);
|
||||
firstReason = firstPeerChanged.Result;
|
||||
firstReason = await firstPeerChanged;
|
||||
await secondPeerChanged;
|
||||
winningPeer = secondPeer;
|
||||
winningConnection = secondConnection;
|
||||
|
||||
Reference in New Issue
Block a user