private void AnalyzeExpression(SyntaxNodeAnalysisContext context, ConcurrentDictionary <int, Diagnostic> reports) { var parentKind = context.Node.Parent.Kind(); // will be handled at higher level if (parentKind == SyntaxKind.SimpleMemberAccessExpression || parentKind == SyntaxKind.QualifiedName) { return; } var target = GetTargetOfNode(context.Node, context.SemanticModel); if (target == null) { return; } var platform = Analyzer.GetPlatformForSymbol(target); // Some quick escapes if (platform.Kind == PlatformKind.Unchecked) { return; } if (platform.Kind == PlatformKind.Uwp && platform.Version == Analyzer.N2SDKVersion) { return; } // Is this expression inside a method/constructor/property that claims to be specific? DeclarationStatementSyntax containingMember = context.Node.FirstAncestorOrSelf <MethodBlockBaseSyntax>(); if (containingMember is AccessorBlockSyntax) { containingMember = containingMember.FirstAncestorOrSelf <PropertyBlockSyntax>(); } // Is this invocation properly guarded? See readme.md for explanations. if (IsProperlyGuarded(context.Node, context.SemanticModel)) { return; } if (containingMember != null) { foreach (var ret in containingMember.DescendantNodes().OfType <ReturnStatementSyntax>()) { if (IsProperlyGuarded(ret, context.SemanticModel)) { return; } } } // We'll report only a single diagnostic per line, the first. var loc = context.Node.GetLocation(); if (!loc.IsInSource) { return; } var line = loc.GetLineSpan().StartLinePosition.Line; if (reports.TryGetValue(line, out var diagnostic) && diagnostic.Location.SourceSpan.Start <= loc.SourceSpan.Start) { return; } diagnostic = Diagnostic.Create(platform.Kind == PlatformKind.Uwp ? Analyzer.VersionRule : Analyzer.PlatformRule, loc); reports[line] = diagnostic; context.ReportDiagnostic(diagnostic); }