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)); 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); }
private void VisitMethods(SyntaxNodeAnalysisContext ctx) { ClassDeclarationSyntax node = ctx.Node as ClassDeclarationSyntax; if (node == null) { return; } // Ensures that the analyzed class has a dependency to Controller if (node .DescendantNodesAndSelf() .OfType <BaseListSyntax>() .Count(childrenNode => childrenNode.ToString().Contains("Controller")) .Equals(0)) { return; } IEnumerable <MethodDeclarationSyntax> methodsWithParameters = node.DescendantNodesAndSelf() .OfType <MethodDeclarationSyntax>() .Where(method => !method.ParameterList.Parameters.Count.Equals(0)) .Where(method => method.Modifiers.ToString().Equals("public")) .Where(method => method.ReturnType.ToString().Equals("string")); foreach (MethodDeclarationSyntax method in methodsWithParameters) { SyntaxList <StatementSyntax> methodStatements = method.Body.Statements; IEnumerable <InvocationExpressionSyntax> methodInvocations = method.DescendantNodes().OfType <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 (InvocationExpressionSyntax methodInvocation in methodInvocations) { SeparatedSyntaxList <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())); } } } } } }
static void HandleSinglePlaceholderTemplateMethod(ref ClassDeclarationSyntax updatedDecl, MethodDeclarationSyntax mtd, EnumerableDetails builtIn, string outTypeStr) { var expanded = ExpandMethodFromPlaceholders(mtd, new[] { builtIn }, BUILTIN_ENUMERABLE_NAME, BUILTIN_ENUMERATOR_NAME, false); var constrainedExpansions = new List <MethodDeclarationSyntax>(); foreach (var expandedMtd in expanded) { var updated = ExpandConstrainedBuiltIns(expandedMtd, builtIn, outTypeStr); constrainedExpansions.Add(updated); } foreach (var expandedMtd in constrainedExpansions) { // slap the type on so we can find it when rewritting later var withOutTypeAnnotation = expandedMtd.WithAdditionalAnnotations(new SyntaxAnnotation(OUT_TYPE_ANNOTATION, outTypeStr)); updatedDecl = updatedDecl.AddMembers(new[] { withOutTypeAnnotation }); } // change methods to be extension methods, and replace placeholders var replaces = new Dictionary <SyntaxNode, SyntaxNode>(); foreach (var workingMtd in updatedDecl.DescendantNodesAndSelf().OfType <MethodDeclarationSyntax>().Where(m => !m.HasAnnotation(METHOD_REWRITTEN))) { // grab the type we need for the enumerable and enumerator var outTypeAnnotation = workingMtd.GetAnnotations(OUT_TYPE_ANNOTATION).SingleOrDefault(); // did we already handle this elsewhere? if (outTypeAnnotation == null) { var skipped = workingMtd.WithAdditionalAnnotations(METHOD_REWRITTEN); replaces[workingMtd] = skipped.WithTriviaFrom(workingMtd); continue; } var workingOutTypeStr = outTypeAnnotation.Data; var outType = SyntaxFactory.ParseTypeName(workingOutTypeStr); TypeSyntax enumerable, enumerator; BindEnumerableAndEnumerator(builtIn, outType, out enumerable, out enumerator); // make the method an extension method var extension = MakeExtensionMethod(workingMtd); // make the dynamic bridge calls call CommonImplementation.Bridge var bridged = ReplaceBridgeCalls(extension); // slap the appropriate enumerable and enumerator into the various CommonImplementation calls MethodDeclarationSyntax parameterized; if (!bridged.HasAnnotation(DO_NOT_PARAMETERIZE)) { parameterized = InjectIdentityAndEnumerator(bridged, enumerable, enumerator); } else { parameterized = bridged; } parameterized = parameterized.WithAdditionalAnnotations(METHOD_REWRITTEN); replaces[workingMtd] = parameterized.WithTriviaFrom(workingMtd); } updatedDecl = updatedDecl.ReplaceNodes(replaces.Keys, (old, _) => replaces[old]); // change methods to be extension methods, and replace placeholders //while (true) //{ // var workingMtd = updatedDecl.DescendantNodesAndSelf().OfType<MethodDeclarationSyntax>().Where(m => !m.HasAnnotation(METHOD_REWRITTEN)).FirstOrDefault(); // if (workingMtd == null) break; // // grab the type we need for the enumerable and enumerator // var outTypeAnnotation = workingMtd.GetAnnotations(OUT_TYPE_ANNOTATION).SingleOrDefault(); // // did we already handle this elsewhere? // if (outTypeAnnotation == null) // { // var skipped = workingMtd.WithAdditionalAnnotations(METHOD_REWRITTEN); // updatedDecl = updatedDecl.ReplaceNode(workingMtd, skipped.WithTriviaFrom(workingMtd)); // continue; // } // var workingOutTypeStr = outTypeAnnotation.Data; // var outType = SyntaxFactory.ParseTypeName(workingOutTypeStr); // TypeSyntax enumerable, enumerator; // BindEnumerableAndEnumerator(builtIn, outType, out enumerable, out enumerator); // // make the method an extension method // var extension = MakeExtensionMethod(workingMtd); // // make the dynamic bridge calls call CommonImplementation.Bridge // var bridged = ReplaceBridgeCalls(extension); // // slap the appropriate enumerable and enumerator into the various CommonImplementation calls // MethodDeclarationSyntax parameterized; // if (!bridged.HasAnnotation(DO_NOT_PARAMETERIZE)) // { // parameterized = InjectIdentityAndEnumerator(bridged, enumerable, enumerator); // } // else // { // parameterized = bridged; // } // parameterized = parameterized.WithAdditionalAnnotations(METHOD_REWRITTEN); // updatedDecl = updatedDecl.ReplaceNode(workingMtd, parameterized.WithTriviaFrom(workingMtd)); //} }