private void Analyze(SyntaxNodeAnalysisContext context)
        {
            if (AllocationRules.IsIgnoredFile(context.Node.SyntaxTree.FilePath))
            {
                return;
            }

            if (HasIgnoreAttribute(context))
            {
                return;
            }

            var          ids   = SupportedDiagnostics.Select(x => x.Id).ToArray();
            EnabledRules rules = AllocationRules.GetEnabledRules(ids);

            if (!rules.AnyEnabled)
            {
                return;
            }

            rules = HotPathAnalysis.GetEnabledRules(rules.All(), context);
            if (!rules.AnyEnabled)
            {
                return;
            }

            AnalyzeNode(context, rules);
        }
Esempio n. 2
0
        protected virtual void Analyze(SyntaxNodeAnalysisContext context, AttributeSyntax attributeSyntax)
        {
            var attributeLocation = attributeSyntax.GetLocation();

            context.ReportDiagnostic(Diagnostic.Create(
                                         SupportedDiagnostics.First(), attributeLocation, attributeSyntax.Name.ToString()));
        }
Esempio n. 3
0
        private void AnalyzeInvocation(SyntaxNodeAnalysisContext context)
        {
            var invocation = (InvocationExpressionSyntax)context.Node;

            if (!(invocation.Expression is MemberAccessExpressionSyntax member))
            {
                return;
            }

            var symbol = context.SemanticModel.GetSymbolInfo(member);

            if (symbol.Symbol == null)
            {
                return;
            }

            if (!(symbol.Symbol is IMethodSymbol method))
            {
                return;
            }

            if (!IsReportable(method))
            {
                return;
            }

            context.ReportDiagnostic(Diagnostic.Create(SupportedDiagnostics.First(), member.Name.GetLocation(), method.Name));
        }
Esempio n. 4
0
        private void VerifyDiagnostics(
            IEnumerable <Diagnostic> actualDiagnostics,
            IEnumerable <Diagnostic> expectedDiagnostics,
            bool checkAdditionalLocations,
            CancellationToken cancellationToken = default)
        {
            int expectedCount = 0;
            int actualCount   = 0;

            using (IEnumerator <Diagnostic> expectedEnumerator = expectedDiagnostics.OrderBy(f => f, DiagnosticComparer.SpanStart).GetEnumerator())
                using (IEnumerator <Diagnostic> actualEnumerator = actualDiagnostics.OrderBy(f => f, DiagnosticComparer.SpanStart).GetEnumerator())
                {
                    if (!expectedEnumerator.MoveNext())
                    {
                        throw new InvalidOperationException($"'{nameof(expectedDiagnostics)}' contains no elements.");
                    }

                    do
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        expectedCount++;

                        Diagnostic expectedDiagnostic = expectedEnumerator.Current;

                        if (SupportedDiagnostics.IndexOf(expectedDiagnostic.Descriptor, DiagnosticDescriptorComparer.Id) == -1)
                        {
                            Assert.True(false, $"Diagnostic \"{expectedDiagnostic.Id}\" is not supported by analyzer(s) {string.Join(", ", Analyzers.Select(f => f.GetType().Name))}.");
                        }

                        if (actualEnumerator.MoveNext())
                        {
                            actualCount++;

                            VerifyDiagnostic(actualEnumerator.Current, expectedDiagnostic, checkAdditionalLocations: checkAdditionalLocations);
                        }
                        else
                        {
                            while (expectedEnumerator.MoveNext())
                            {
                                expectedCount++;
                            }

                            Assert.True(false, $"Mismatch between number of diagnostics returned, expected: {expectedCount} actual: {actualCount}{actualDiagnostics.ToDebugString()}");
                        }
                    } while (expectedEnumerator.MoveNext());

                    if (actualEnumerator.MoveNext())
                    {
                        actualCount++;

                        while (actualEnumerator.MoveNext())
                        {
                            actualCount++;
                        }

                        Assert.True(false, $"Mismatch between number of diagnostics returned, expected: {expectedCount} actual: {actualCount}{actualDiagnostics.ToDebugString()}");
                    }
                }
        }
        public override void Initialize(AnalysisContext analysisContext)
        {
            analysisContext.RegisterCompilationStartAction(compilationStartAnalysisContext =>
            {
                if (compilationStartAnalysisContext.CancellationToken.IsCancellationRequested)
                {
                    return;
                }

                var taskType    = compilationStartAnalysisContext.Compilation.GetTypeByMetadataName("System.Threading.Tasks.Task");
                var taskOfTType = compilationStartAnalysisContext.Compilation.GetTypeByMetadataName("System.Threading.Tasks.Task`1");

                compilationStartAnalysisContext.RegisterCodeBlockStartAction <SyntaxKind>(codeBlockStartAnalysisContext =>
                {
                    if (codeBlockStartAnalysisContext.CancellationToken.IsCancellationRequested)
                    {
                        return;
                    }

                    if (codeBlockStartAnalysisContext.CodeBlock.SyntaxTree.IsGeneratedCode())
                    {
                        return;
                    }

                    codeBlockStartAnalysisContext.RegisterSyntaxNodeAction(syntaxNodeAnalysisContext =>
                    {
                        if (syntaxNodeAnalysisContext.CancellationToken.IsCancellationRequested)
                        {
                            return;
                        }

                        var identifierNameNode = (IdentifierNameSyntax)syntaxNodeAnalysisContext.Node;

                        if (identifierNameNode.Identifier.Text != TaskMemberToDiagnose.Name)
                        {
                            return;
                        }

                        var symbolInfo = syntaxNodeAnalysisContext.SemanticModel.GetSymbolInfo(identifierNameNode, syntaxNodeAnalysisContext.CancellationToken);

                        if (symbolInfo.Symbol == null || symbolInfo.Symbol.Kind != TaskMemberToDiagnose.SymbolKind)
                        {
                            return;
                        }

                        if (symbolInfo.Symbol.ContainingType.OriginalDefinition != taskType &&
                            symbolInfo.Symbol.ContainingType.OriginalDefinition != taskOfTType)
                        {
                            return;
                        }

                        syntaxNodeAnalysisContext.ReportDiagnostic(Diagnostic.Create(SupportedDiagnostics.First(), syntaxNodeAnalysisContext.Node.GetLocation()));
                    }, SyntaxKind.IdentifierName);
                });
            });
        }
        protected bool IsEnabled(AnalyzerOptions options)
        {
            if (analysisConfiguration.EnabledRules == null)
            {
                analysisConfiguration.Read(options);
            }

            if (analysisConfiguration.EnabledRules == null)
            {
                return(false);
            }

            return(SupportedDiagnostics.Any(d => analysisConfiguration.IsEnabled(d.Id)));
        }
Esempio n. 7
0
        public async Task VerifyNoDiagnosticAsync(
            string source,
            string[] additionalSources          = null,
            CodeVerificationOptions options     = null,
            CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            if (SupportedDiagnostics.IndexOf(Descriptor, DiagnosticDescriptorComparer.Id) == -1)
            {
                Assert.True(false, $"Diagnostic \"{Descriptor.Id}\" is not supported by analyzer \"{Analyzer.GetType().Name}\".");
            }

            using (Workspace workspace = new AdhocWorkspace())
            {
                Project project = WorkspaceFactory.AddProject(workspace.CurrentSolution, options);

                Document document = WorkspaceFactory.AddDocument(project, source, additionalSources ?? Array.Empty <string>());

                Compilation compilation = await document.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

                ImmutableArray <Diagnostic> compilerDiagnostics = compilation.GetDiagnostics(cancellationToken);

                if (options == null)
                {
                    options = Options;
                }

                VerifyCompilerDiagnostics(compilerDiagnostics, options);

                if (options.EnableDiagnosticsDisabledByDefault)
                {
                    compilation = compilation.EnsureEnabled(Descriptor);
                }

                ImmutableArray <Diagnostic> analyzerDiagnostics = await compilation.GetAnalyzerDiagnosticsAsync(Analyzer, DiagnosticComparer.SpanStart, cancellationToken).ConfigureAwait(false);

                foreach (Diagnostic diagnostic in analyzerDiagnostics)
                {
                    if (string.Equals(diagnostic.Id, Descriptor.Id, StringComparison.Ordinal))
                    {
                        Assert.True(false, $"No diagnostic expected{analyzerDiagnostics.Where(f => string.Equals(f.Id, Descriptor.Id, StringComparison.Ordinal)).ToDebugString()}");
                    }
                }
            }
        }
        private void CheckStructShouldImplementIEquatable(SyntaxNodeAnalysisContext context)
        {
            var declSyntax = (StructDeclarationSyntax)context.Node;
            var declSymbol = context.SemanticModel.GetDeclaredSymbol(declSyntax) as INamedTypeSymbol;

            bool foundIEquatableOfStruct = false;

            if (declSyntax.BaseList != null)
            {
                var baseList        = declSyntax.BaseList.Types;
                var baseTypesSyntax = baseList.OfType <SimpleBaseTypeSyntax>();


                foreach (var oneBaseTypeSyntax in baseTypesSyntax)
                {
                    var baseTypeName = oneBaseTypeSyntax.ChildNodes();
                    foreach (var oneName in baseTypeName)
                    {
                        if (oneName is GenericNameSyntax)
                        {
                            var genericSymbolInfo = context.SemanticModel.GetSymbolInfo(oneName);
                            var genericSymbol     = genericSymbolInfo.Symbol as INamedTypeSymbol;
                            if (genericSymbol != null && genericSymbol.ContainingNamespace.Name == "System" &&
                                genericSymbol.Name == "IEquatable")
                            {
                                foreach (var oneParameterType in genericSymbol.TypeArguments)
                                {
                                    if (oneParameterType == declSymbol)
                                    {
                                        foundIEquatableOfStruct = true;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (!foundIEquatableOfStruct)
            {
                var diagnostic = Diagnostic.Create(SupportedDiagnostics.First(), declSyntax.Identifier.GetLocation(),
                                                   declSyntax.Identifier.ToString());

                context.ReportDiagnostic(diagnostic);
            }
        }
Esempio n. 9
0
        protected void CheckComplexity <TSyntax>(SyntaxNodeAnalysisContext context, Func <TSyntax, SyntaxNode> nodeSelector, Func <TSyntax, Location> location,
                                                 string declarationType)
            where TSyntax : SyntaxNode
        {
            var syntax        = (TSyntax)context.Node;
            var nodeToAnalyze = nodeSelector(syntax);

            if (nodeToAnalyze == null)
            {
                return;
            }

            var complexity = GetComplexity(nodeToAnalyze);

            if (complexity > Maximum)
            {
                context.ReportDiagnostic(Diagnostic.Create(SupportedDiagnostics.First(), location(syntax), Maximum, complexity, declarationType));
            }
        }
 protected sealed override void Initialize(ParameterLoadingAnalysisContext context)
 {
     context.RegisterSyntaxNodeActionInNonGenerated(
         c =>
     {
         var fieldDeclaration = (FieldDeclarationSyntax)c.Node;
         foreach (var name in fieldDeclaration.Declarators.SelectMany(v => v.Names).Where(n => n != null))
         {
             var symbol = c.SemanticModel.GetDeclaredSymbol(name) as IFieldSymbol;
             if (symbol != null &&
                 IsCandidateSymbol(symbol) &&
                 !IsRegexMatch(symbol.Name, Pattern))
             {
                 c.ReportDiagnostic(Diagnostic.Create(SupportedDiagnostics.First(), name.GetLocation(), symbol.Name, Pattern));
             }
         }
     },
         SyntaxKind.FieldDeclaration);
 }
        private void AnalyzeClassSyntax(SyntaxNodeAnalysisContext context)
        {
            var classDeclaration = (ClassDeclarationSyntax)context.Node;

            if (classDeclaration.IsDerived() && !classDeclaration.IsSealed())
            {
                var methods = classDeclaration.Members.OfType <MethodDeclarationSyntax>();

                foreach (var method in methods)
                {
                    if (method.IsOverriden() && !method.IsSealed())
                    {
                        var diagnostic = Diagnostic.Create(SupportedDiagnostics.First(), method.Identifier.GetLocation(),
                                                           method.Identifier.ToString(), classDeclaration.Identifier.ToString());

                        context.ReportDiagnostic(diagnostic);
                    }
                }
            }
        }
Esempio n. 12
0
        private void AnalyzeInvocation(SyntaxNodeAnalysisContext context)
        {
            var invocation = context.Node as InvocationExpressionSyntax;

            if (invocation == null)
            {
                return;
            }

            var methodName = invocation.MethodName();

            if (InvokeMethods.Contains(methodName))
            {
                // check if the method is the one from UnityEngine
                var symbolInfo   = context.SemanticModel.GetSymbolInfo(invocation);
                var methodSymbol = symbolInfo.Symbol as IMethodSymbol;

                var fullTypeName = methodSymbol?.ContainingType.ToString();

                if (fullTypeName == InvokeMethodTypeName && invocation.ArgumentList.Arguments.Count > 0)
                {
                    var firstArgumentExpression = invocation.ArgumentList.Arguments[0];

                    var invokedMethodName = firstArgumentExpression.GetArgumentValue <string>();

                    var containingClassDeclaration = invocation.Ancestors().FirstOrDefault(a => a is ClassDeclarationSyntax) as ClassDeclarationSyntax;

                    var allMethods = containingClassDeclaration?.Members.OfType <MethodDeclarationSyntax>();

                    var invokeEndPoint = allMethods.FirstOrDefault(m => m.Identifier.ValueText == invokedMethodName);

                    if (invokeEndPoint == null)
                    {
                        var diagnostic = Diagnostic.Create(SupportedDiagnostics.First(), firstArgumentExpression.GetLocation(),
                                                           methodName, invokedMethodName);

                        context.ReportDiagnostic(diagnostic);
                    }
                }
            }
        }
Esempio n. 13
0
        public async Task VerifyNoDiagnosticAsync(
            string source,
            IEnumerable <string> additionalSources = null,
            CodeVerificationOptions options        = null,
            CancellationToken cancellationToken    = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            options ??= Options;

            if (SupportedDiagnostics.IndexOf(Descriptor, DiagnosticDescriptorComparer.Id) == -1)
            {
                Assert.True(false, $"Diagnostic \"{Descriptor.Id}\" is not supported by analyzer(s) {string.Join(", ", Analyzers.Select(f => f.GetType().Name))}.");
            }

            using (Workspace workspace = new AdhocWorkspace())
            {
                Project project = WorkspaceFactory.AddProject(workspace.CurrentSolution, options);

                Document document = WorkspaceFactory.AddDocument(project, source, additionalSources);

                Compilation compilation = await document.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

                ImmutableArray <Diagnostic> compilerDiagnostics = compilation.GetDiagnostics(cancellationToken);

                VerifyCompilerDiagnostics(compilerDiagnostics, options);

                compilation = UpdateCompilation(compilation);

                ImmutableArray <Diagnostic> analyzerDiagnostics = await compilation.GetAnalyzerDiagnosticsAsync(Analyzers, DiagnosticComparer.SpanStart, cancellationToken).ConfigureAwait(false);

                foreach (Diagnostic diagnostic in analyzerDiagnostics)
                {
                    if (string.Equals(diagnostic.Id, Descriptor.Id, StringComparison.Ordinal))
                    {
                        Assert.True(false, $"No diagnostic expected{analyzerDiagnostics.Where(f => string.Equals(f.Id, Descriptor.Id, StringComparison.Ordinal)).ToDebugString()}");
                    }
                }
            }
        }
        protected void CheckComplexity <TSyntax>(SyntaxNodeAnalysisContext context,
                                                 Func <TSyntax, Location> getLocationToReport, string declarationType, int threshold)
            where TSyntax : SyntaxNode
        {
            var syntax = (TSyntax)context.Node;

            var cognitiveWalker = new CognitiveComplexityWalker();

            cognitiveWalker.Visit(syntax);
            if (cognitiveWalker.NestingLevel != 0)
            {
                throw new Exception($"There is a problem with the cognitive complexity walker. Expecting ending nesting to be '0' got '{cognitiveWalker.NestingLevel}'");
            }

            if (cognitiveWalker.Complexity > Threshold)
            {
                context.ReportDiagnostic(Diagnostic.Create(SupportedDiagnostics.First(), getLocationToReport(syntax),
                                                           cognitiveWalker.Flow.Select(x => x.Location),
                                                           CreatePropertiesFromCognitiveTrace(cognitiveWalker.Flow),
                                                           new object[] { declarationType, cognitiveWalker.Complexity, threshold }));
            }
        }
Esempio n. 15
0
        protected bool IsEnabled(AnalyzerOptions options)
        {
            analyzerConfiguration.Initialize(options);

            return(SupportedDiagnostics.Any(d => analyzerConfiguration.IsEnabled(d.Id)));
        }
Esempio n. 16
0
 public DeprecatedAnalyzer()
 {
     SupportedDiagnostics = GetDescriptors();
     DescriptorById       = SupportedDiagnostics.ToImmutableDictionary(d => d.Id);
 }
Esempio n. 17
0
 private ImmutableDictionary <string, ImmutableArray <DiagnosticDescriptor> > LoadSupportedDiagnosticsByPrefix()
 {
     return(SupportedDiagnostics
            .GroupBy(f => f, DiagnosticDescriptorComparer.IdPrefix)
            .ToImmutableDictionary(f => DiagnosticIdPrefix.GetPrefix(f.Key.Id), f => f.ToImmutableArray()));
 }