示例#1
0
        private void VisitMethodsCSharp(SyntaxNodeAnalysisContext ctx)
        {
            CSharpSyntax.ClassDeclarationSyntax node = ctx.Node as CSharpSyntax.ClassDeclarationSyntax;

            if (node == null)
            {
                return;
            }

            // Ensures that the analyzed class has a dependency to Controller
            if (node
                .DescendantNodesAndSelf()
                .OfType <CSharpSyntax.BaseListSyntax>()
                .Count(childrenNode => childrenNode.ToString().Contains("Controller"))
                .Equals(0))
            {
                return;
            }

            IEnumerable <CSharpSyntax.MethodDeclarationSyntax> methodsWithParameters = node.DescendantNodesAndSelf()
                                                                                       .OfType <CSharpSyntax.MethodDeclarationSyntax>()
                                                                                       .Where(method => !method.ParameterList.Parameters.Count.Equals(0))
                                                                                       .Where(method => method.Modifiers.ToString().Equals("public"))
                                                                                       .Where(method => method.ReturnType.ToString().Equals("string"));

            foreach (CSharpSyntax.MethodDeclarationSyntax method in methodsWithParameters)
            {
                SyntaxList <CSharpSyntax.StatementSyntax>             methodStatements  = method.Body.Statements;
                IEnumerable <CSharpSyntax.InvocationExpressionSyntax> methodInvocations = method.DescendantNodes().OfType <CSharpSyntax.InvocationExpressionSyntax>();

                if (!methodStatements.Count.Equals(0))
                {
                    DataFlowAnalysis flow = ctx.SemanticModel.AnalyzeDataFlow(methodStatements.First(), methodStatements.Last());

                    // Returns from the Data Flow Analysis of sensible data
                    // Sensible data is: Data passed as a parameter that is also returned as is by the method
                    IEnumerable <ISymbol> sensibleVariables = flow.DataFlowsIn.Union(flow.VariablesDeclared.Except(flow.AlwaysAssigned))
                                                              .Union(flow.WrittenInside)
                                                              .Intersect(flow.WrittenOutside);

                    if (!sensibleVariables.Count().Equals(0))
                    {
                        foreach (ISymbol sensibleVariable in sensibleVariables)
                        {
                            bool sensibleVariableIsEncoded = false;
                            foreach (CSharpSyntax.InvocationExpressionSyntax methodInvocation in methodInvocations)
                            {
                                SeparatedSyntaxList <CSharpSyntax.ArgumentSyntax> arguments = methodInvocation.ArgumentList.Arguments;
                                if (!arguments.Count.Equals(0))
                                {
                                    if (arguments.First().ToString().Contains(sensibleVariable.Name))
                                    {
                                        sensibleVariableIsEncoded = true;
                                    }
                                }
                            }

                            if (!sensibleVariableIsEncoded)
                            {
                                ctx.ReportDiagnostic(Diagnostic.Create(Rule, method.GetLocation()));
                            }
                        }
                    }
                }
            }
        }
    private static void AddCodeFixWithUpdatingNonPublicConstructor(CodeFixContext context, SyntaxNode root,
      Diagnostic diagnostic, ClassDeclarationSyntax classNode)
    {
      var publicModifier = SyntaxFactory.Token(SyntaxKind.PublicKeyword);
      var constructor = classNode.DescendantNodesAndSelf()
        .Where(_ => _.IsKind(SyntaxKind.ConstructorDeclaration))
        .Cast<ConstructorDeclarationSyntax>()
        .Single(c => c.ParameterList.Parameters.Count == 0 &&
          !c.Modifiers.Contains(SyntaxFactory.Token(SyntaxKind.PublicKeyword)));

      var newConstructor = constructor.WithModifiers(SyntaxFactory.TokenList(publicModifier));
      var newRoot = root.ReplaceNode(constructor, newConstructor);

      context.RegisterCodeFix(
        CodeAction.Create(
          CheckConstructorsAnalyzerPublicConstructorCodeFixConstants.UpdateNonPublicConstructorToPublicDescription,
          _ => Task.FromResult(context.Document.WithSyntaxRoot(newRoot)),
          CheckConstructorsAnalyzerPublicConstructorCodeFixConstants.UpdateNonPublicConstructorToPublicDescription), diagnostic);
    }
    private static void AddCodeFixWithUpdatingNonPublicConstructor(CodeFixContext context, SyntaxNode root,
      Diagnostic diagnostic, ClassDeclarationSyntax classNode, SemanticModel model)
    {
      var publicModifier = SyntaxFactory.Token(SyntaxKind.PublicKeyword);
      var classSymbol = model.GetDeclaredSymbol(classNode);

      if (classSymbol != null)
      {
        var constructor = classNode.DescendantNodesAndSelf()
          .Where(_ => _.IsKind(SyntaxKind.ConstructorDeclaration))
          .Cast<ConstructorDeclarationSyntax>()
          .Single(c => model.GetDeclaredSymbol(c).ContainingType == classSymbol &&
            c.ParameterList.Parameters.Count == 0 &&
            !c.Modifiers.Contains(publicModifier));

        var newConstructor = constructor.WithModifiers(SyntaxFactory.TokenList(publicModifier));

        if (constructor.HasLeadingTrivia)
        {
          newConstructor = newConstructor.WithLeadingTrivia(constructor.GetLeadingTrivia());
        }

        if (constructor.HasTrailingTrivia)
        {
          newConstructor = newConstructor.WithTrailingTrivia(constructor.GetTrailingTrivia());
        }

        var newRoot = root.ReplaceNode(constructor, newConstructor);

        context.RegisterCodeFix(
          CodeAction.Create(
            CheckConstructorsAnalyzerPublicConstructorCodeFixConstants.UpdateNonPublicConstructorToPublicDescription,
            _ => Task.FromResult(context.Document.WithSyntaxRoot(newRoot)),
            CheckConstructorsAnalyzerPublicConstructorCodeFixConstants.UpdateNonPublicConstructorToPublicDescription), diagnostic);
      }
    }