diff --git a/src/Microsoft.VisualStudio.Threading.Analyzers.Tests/Microsoft.VisualStudio.Threading.Analyzers.Tests.csproj b/src/Microsoft.VisualStudio.Threading.Analyzers.Tests/Microsoft.VisualStudio.Threading.Analyzers.Tests.csproj index c4303ea9e..12a3c6390 100644 --- a/src/Microsoft.VisualStudio.Threading.Analyzers.Tests/Microsoft.VisualStudio.Threading.Analyzers.Tests.csproj +++ b/src/Microsoft.VisualStudio.Threading.Analyzers.Tests/Microsoft.VisualStudio.Threading.Analyzers.Tests.csproj @@ -20,7 +20,7 @@ - + diff --git a/src/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD010MainThreadUsageAnalyzerTests.cs b/src/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD010MainThreadUsageAnalyzerTests.cs index b4f1be3b0..36af35d56 100644 --- a/src/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD010MainThreadUsageAnalyzerTests.cs +++ b/src/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD010MainThreadUsageAnalyzerTests.cs @@ -964,6 +964,25 @@ void F() { await Verify.VerifyAnalyzerAsync(test, expected); } + [Fact] + public async Task CastToVsSolutionViaIsWithPatternMatching() + { + var test = @" +using System; +using Microsoft.VisualStudio.Shell.Interop; + +class Test { + void F() { + object obj1 = null; + if (obj1 is IVsSolution solution) { + } + } +} +"; + var expected = Verify.Diagnostic(DescriptorSync).WithSpan(8, 18, 8, 32).WithArguments("IVsSolution", "Test.VerifyOnUIThread"); + await Verify.VerifyAnalyzerAsync(test, expected); + } + /// /// Verifies that the as cast operator does not produce a diagnostic when the type is to a managed type. /// diff --git a/src/Microsoft.VisualStudio.Threading.Analyzers/Microsoft.VisualStudio.Threading.Analyzers.csproj b/src/Microsoft.VisualStudio.Threading.Analyzers/Microsoft.VisualStudio.Threading.Analyzers.csproj index 33ea56c12..af7895d67 100644 --- a/src/Microsoft.VisualStudio.Threading.Analyzers/Microsoft.VisualStudio.Threading.Analyzers.csproj +++ b/src/Microsoft.VisualStudio.Threading.Analyzers/Microsoft.VisualStudio.Threading.Analyzers.csproj @@ -1,7 +1,6 @@  - netstandard1.1 - $(PackageTargetFallback);portable-net45+win8 + netstandard1.3 true $(NoWarn);CS1591 Microsoft.VisualStudio.Threading.Analyzers.ruleset @@ -13,7 +12,7 @@ © Microsoft Corporation. All rights reserved. https://github.com/Microsoft/vs-threading https://aka.ms/VsExtensibilityIcon - In the v15.8 release, analyzers are incomplete in the context of Visual Studio without the Microsoft.VisualStudio.Sdk.Analyzers 15.8 package also installed. + In the v16.0 release, analyzers require at least C# 7.3 (Visual Studio 2017 Update 7). full @@ -58,7 +57,7 @@ - + @@ -81,4 +80,4 @@ https://raw.githubusercontent.com/Microsoft/vs-threading/$(GitCommitIdShort)/LICENSE - \ No newline at end of file + diff --git a/src/Microsoft.VisualStudio.Threading.Analyzers/VSTHRD010MainThreadUsageAnalyzer.cs b/src/Microsoft.VisualStudio.Threading.Analyzers/VSTHRD010MainThreadUsageAnalyzer.cs index d5021f375..c526f4f93 100644 --- a/src/Microsoft.VisualStudio.Threading.Analyzers/VSTHRD010MainThreadUsageAnalyzer.cs +++ b/src/Microsoft.VisualStudio.Threading.Analyzers/VSTHRD010MainThreadUsageAnalyzer.cs @@ -9,7 +9,6 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; - using Microsoft.CodeAnalysis.Semantics; using Microsoft.CodeAnalysis.Text; /// @@ -133,6 +132,7 @@ public override void Initialize(AnalysisContext context) codeBlockStartContext.RegisterSyntaxNodeAction(Utils.DebuggableWrapper(methodAnalyzer.AnalyzeCast), SyntaxKind.CastExpression); codeBlockStartContext.RegisterSyntaxNodeAction(Utils.DebuggableWrapper(methodAnalyzer.AnalyzeAs), SyntaxKind.AsExpression); codeBlockStartContext.RegisterSyntaxNodeAction(Utils.DebuggableWrapper(methodAnalyzer.AnalyzeAs), SyntaxKind.IsExpression); + codeBlockStartContext.RegisterSyntaxNodeAction(Utils.DebuggableWrapper(methodAnalyzer.AnalyzeIsPattern), SyntaxKind.IsPatternExpression); }); compilationStartContext.RegisterSyntaxNodeAction(Utils.DebuggableWrapper(c => AddToCallerCalleeMap(c, callerToCalleeMap)), SyntaxKind.InvocationExpression); @@ -369,6 +369,23 @@ internal void AnalyzeAs(SyntaxNodeAnalysisContext context) } } + internal void AnalyzeIsPattern(SyntaxNodeAnalysisContext context) + { + var patternSyntax = (IsPatternExpressionSyntax)context.Node; + if (patternSyntax.Pattern is DeclarationPatternSyntax declarationPatternSyntax && declarationPatternSyntax.Type != null) + { + var type = context.SemanticModel.GetSymbolInfo(declarationPatternSyntax.Type, context.CancellationToken).Symbol as ITypeSymbol; + if (type != null && IsObjectLikelyToBeCOMObject(type)) + { + Location isAndTypeSide = Location.Create( + context.Node.SyntaxTree, + TextSpan.FromBounds(patternSyntax.IsKeyword.SpanStart, + declarationPatternSyntax.Type.Span.End)); + this.AnalyzeMemberWithinContext(type, null, context, isAndTypeSide); + } + } + } + /// /// Determines whether a given type is likely to be (or implemented by) a COM object. /// diff --git a/src/Microsoft.VisualStudio.Threading/Microsoft.VisualStudio.Threading.csproj b/src/Microsoft.VisualStudio.Threading/Microsoft.VisualStudio.Threading.csproj index da2848216..1dadde7cc 100644 --- a/src/Microsoft.VisualStudio.Threading/Microsoft.VisualStudio.Threading.csproj +++ b/src/Microsoft.VisualStudio.Threading/Microsoft.VisualStudio.Threading.csproj @@ -69,9 +69,15 @@ - + but have a package dependency so users of this library will automatically get the analyzers. + This requires an MSBuild workaround as documented here: https://github.com/Microsoft/msbuild/issues/2661#issuecomment-338808137 + --> + + none + false + true + TargetFramework +