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); } }