static void Analyze([NotNull] IMethodDeclaration methodDeclaration, [NotNull] IHighlightingConsumer consumer) { if (!methodDeclaration.IsAsync || !methodDeclaration.IsVoidMethodDeclaration()) { return; // not an "async void" method } var method = methodDeclaration.DeclaredElement; if (method == null) { return; // cannot analyze } if (method.GetImmediateSuperMembers().Any()) { consumer.AddHighlighting( new AvoidAsyncVoidHighlighting("'void' method overridden or implemented as 'async void'.", methodDeclaration)); return; } // find usages var psiServices = method.GetPsiServices(); Debug.Assert(SearchDomainFactory.Instance != null); var solutionSearchDomain = SearchDomainFactory.Instance.CreateSearchDomain(psiServices.Solution, false); var references = psiServices.Finder.FindReferences(method, solutionSearchDomain, NullProgressIndicator.Create()); if (IsPublicSurfaceArea(method)) { if (references.Length > 0) { consumer.AddHighlighting( new AvoidAsyncVoidHighlighting("'async void' public surface area method with detected usages.", methodDeclaration)); } else { var implicitUseAnnotationProvider = psiServices.GetCodeAnnotationsCache().GetProvider <ImplicitUseAnnotationProvider>(); var useKindFlags = implicitUseAnnotationProvider.IsImplicitlyUsed(method); if (useKindFlags == null) { // [UsedImplicitly] annotation not applied consumer.AddHighlighting( new AvoidAsyncVoidHighlighting("'async void' public surface area method without detected usages.", methodDeclaration)); } } } else { var count = references.Count(reference => !reference.AssertNotNull().IsEventTarget()); if (count > 0) { consumer.AddHighlighting( new AvoidAsyncVoidHighlighting( string.Format( "'async void' method used {0} time{1} not as a direct event handler.", count.ToString(), count == 1 ? "" : "s"), methodDeclaration)); } } }