internal void AnalyzeInvocation(SyntaxNodeAnalysisContext context) { var invocationSyntax = (InvocationExpressionSyntax)context.Node; var invokeMethod = context.SemanticModel.GetSymbolInfo(context.Node).Symbol as IMethodSymbol; if (invokeMethod != null) { var methodDeclaration = context.Node.FirstAncestorOrSelf <SyntaxNode>(n => MethodSyntaxKinds.Contains(n.Kind())); if (methodDeclaration != null) { if (KnownMethodsToVerifyMainThread.Contains(invokeMethod.Name) || KnownMethodsToSwitchToMainThread.Contains(invokeMethod.Name)) { this.methodDeclarationNodes = this.methodDeclarationNodes.SetItem(methodDeclaration, ThreadingContext.MainThread); return; } } // The diagnostic (if any) should underline the method name only. var focusedNode = invocationSyntax.Expression; focusedNode = (focusedNode as MemberAccessExpressionSyntax)?.Name ?? focusedNode; if (!this.AnalyzeTypeWithinContext(invokeMethod.ContainingType, invokeMethod, context, focusedNode)) { foreach (var iface in invokeMethod.FindInterfacesImplemented()) { if (this.AnalyzeTypeWithinContext(iface, invokeMethod, context, focusedNode)) { // Just report the first diagnostic. break; } } } } }
private bool AnalyzeTypeWithinContext(ITypeSymbol type, ISymbol symbol, SyntaxNodeAnalysisContext context, SyntaxNode focusDiagnosticOn = null) { if (type == null) { throw new ArgumentNullException(nameof(type)); } bool requiresUIThread = type.TypeKind == TypeKind.Interface && type.ContainingAssembly != null && IsVisualStudioShellInteropAssembly(type.ContainingAssembly.Name); requiresUIThread |= symbol?.Name == "GetService" && type.Name == "Package" && type.BelongsToNamespace(Namespaces.MicrosoftVisualStudioShell); requiresUIThread |= symbol != null && !symbol.IsStatic && type.Name == "ServiceProvider" && type.BelongsToNamespace(Namespaces.MicrosoftVisualStudioShell); if (requiresUIThread) { var threadingContext = ThreadingContext.Unknown; var methodDeclaration = context.Node.FirstAncestorOrSelf <SyntaxNode>(n => MethodSyntaxKinds.Contains(n.Kind())); if (methodDeclaration != null) { threadingContext = this.methodDeclarationNodes.GetValueOrDefault(methodDeclaration); } if (threadingContext != ThreadingContext.MainThread) { Location location = (focusDiagnosticOn ?? context.Node).GetLocation(); context.ReportDiagnostic(Diagnostic.Create(Descriptor, location, type.Name)); return(true); } } return(false); }
private void AnalyzeTypeWithinContext(ITypeSymbol type, SyntaxNodeAnalysisContext context, SyntaxNode focusDiagnosticOn = null) { if (type.TypeKind == TypeKind.Interface && type.ContainingAssembly != null && IsVisualStudioShellInteropAssembly(type.ContainingAssembly.Name)) { var threadingContext = ThreadingContext.Unknown; var methodDeclaration = context.Node.FirstAncestorOrSelf <SyntaxNode>(n => MethodSyntaxKinds.Contains(n.Kind())); if (methodDeclaration != null) { threadingContext = this.methodDeclarationNodes.GetValueOrDefault(methodDeclaration); } if (threadingContext != ThreadingContext.MainThread) { Location location = (focusDiagnosticOn ?? context.Node).GetLocation(); context.ReportDiagnostic(Diagnostic.Create(Descriptor, location, type.Name)); } } }