Skip to content

Commit a5ab4b8

Browse files
committed
Handle CurrentDispatcher.Invoke
Fix #194
1 parent 70ad845 commit a5ab4b8

5 files changed

Lines changed: 38 additions & 49 deletions

File tree

IDisposableAnalyzers.Test/IDISP004DoNotIgnoreCreatedTests/Valid.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,5 +771,24 @@ public void Dispose()
771771
}".AssertReplace("await Task.FromResult(File.OpenRead(fileName))", statement);
772772
RoslynAssert.Valid(Analyzer, code);
773773
}
774+
775+
[Test]
776+
public static void DispatcherInvoke()
777+
{
778+
var code = @"
779+
namespace N
780+
{
781+
using System.Threading.Tasks;
782+
783+
public sealed class C
784+
{
785+
public async Task M()
786+
{
787+
await System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke(() => Task.FromResult(42)).ConfigureAwait(false);
788+
}
789+
}
790+
}";
791+
RoslynAssert.Valid(Analyzer, code);
792+
}
774793
}
775794
}

IDisposableAnalyzers/Helpers/Disposable.IsCreation.cs

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -89,26 +89,24 @@ internal static Result IsAlreadyAssignedWithCreated(ExpressionSyntax disposable,
8989
return Result.No;
9090
}
9191

92-
using (var assignedValues = AssignedValueWalker.Borrow(disposable, semanticModel, cancellationToken))
92+
using var assignedValues = AssignedValueWalker.Borrow(disposable, semanticModel, cancellationToken);
93+
assignedSymbol = assignedValues.CurrentSymbol;
94+
if (assignedValues.Count == 1 &&
95+
disposable.Parent is AssignmentExpressionSyntax { Parent: ParenthesizedExpressionSyntax { Parent: BinaryExpressionSyntax { } binary } } &&
96+
binary.IsKind(SyntaxKind.CoalesceExpression))
9397
{
94-
assignedSymbol = assignedValues.CurrentSymbol;
95-
if (assignedValues.Count == 1 &&
96-
disposable.Parent is AssignmentExpressionSyntax { Parent: ParenthesizedExpressionSyntax { Parent: BinaryExpressionSyntax { } binary } } &&
97-
binary.IsKind(SyntaxKind.CoalesceExpression))
98-
{
99-
// lazy
100-
return Result.No;
101-
}
102-
103-
if (symbol.IsEither<IParameterSymbol, ILocalSymbol>())
104-
{
105-
assignedValues.RemoveAll(x => IsReturnedBefore(x));
106-
}
98+
// lazy
99+
return Result.No;
100+
}
107101

108-
using var recursive = RecursiveValues.Borrow(assignedValues, semanticModel, cancellationToken);
109-
return IsAnyCreation(recursive, semanticModel, cancellationToken);
102+
if (symbol.IsEither<IParameterSymbol, ILocalSymbol>())
103+
{
104+
assignedValues.RemoveAll(x => IsReturnedBefore(x));
110105
}
111106

107+
using var recursive = RecursiveValues.Borrow(assignedValues, semanticModel, cancellationToken);
108+
return IsAnyCreation(recursive, semanticModel, cancellationToken);
109+
112110
bool IsReturnedBefore(ExpressionSyntax expression)
113111
{
114112
if (expression.TryFirstAncestor(out BlockSyntax? block) &&
@@ -358,9 +356,10 @@ candidate is IParameterSymbol ||
358356
return Result.No;
359357
}
360358

361-
if (method.ReturnType == KnownSymbol.TaskOfT)
359+
if (method.ReturnType is INamedTypeSymbol { IsGenericType: true } returnType &&
360+
method.ReturnType == KnownSymbol.TaskOfT)
362361
{
363-
return method.TypeArguments.TrySingle(out var typeArg) &&
362+
return returnType.TypeArguments.TrySingle(out var typeArg) &&
364363
IsAssignableFrom(typeArg, compilation)
365364
? Result.AssumeYes
366365
: Result.No;
Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
namespace IDisposableAnalyzers
22
{
33
using System.Diagnostics.CodeAnalysis;
4-
using System.Threading;
54
using Gu.Roslyn.AnalyzerExtensions;
65
using Microsoft.CodeAnalysis;
7-
using Microsoft.CodeAnalysis.CSharp.Syntax;
86

97
internal static class MethodSymbolExt
108
{
@@ -23,17 +21,5 @@ internal static bool TryGetThisParameter(this IMethodSymbol method, [NotNullWhen
2321
parameter = null;
2422
return false;
2523
}
26-
27-
internal static bool IsType(this ObjectCreationExpressionSyntax objectCreation, QualifiedType type, SemanticModel semanticModel, CancellationToken cancellationToken)
28-
{
29-
return objectCreation switch
30-
{
31-
{ Type: IdentifierNameSyntax identifierName } => identifierName == type &&
32-
semanticModel.TryGetType(objectCreation, cancellationToken, out var symbol) &&
33-
symbol == type,
34-
_ => semanticModel.TryGetType(objectCreation, cancellationToken, out var symbol) &&
35-
symbol == type,
36-
};
37-
}
3824
}
3925
}

IDisposableAnalyzers/Helpers/Temp/PooledSetExt.cs

Lines changed: 0 additions & 17 deletions
This file was deleted.

ValidCode/Async.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ public async Task Calls()
6969
}
7070

7171
using var disposable2 = Task.FromResult(new Disposable()).Result;
72+
73+
await System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke(() => Task.FromResult(42)).ConfigureAwait(false);
7274
}
7375

7476
public static async Task<string> Bar1Async()

0 commit comments

Comments
 (0)