public void SimpleSwitch_Scores_1() { var method = root.DescendantNodesAndSelf().OfType <MethodDeclarationSyntax>().First(method => method.Identifier.ValueText == "SimpleSwitch"); var score = CognitiveComplexityAnalyzer.AnalyzeMethod(method); Assert.Equal(1, score); }
public static NamespaceDeclarationSyntax GetNamespaceDeclaration( this CompilationUnitSyntax compilation) => compilation .DescendantNodesAndSelf() .OfType <NamespaceDeclarationSyntax>() .FirstOrDefault();
public override async Task <AnalyzerResult> Analyze() { foreach (SyntaxTree tree in this.Compilation.SyntaxTrees) { CompilationUnitSyntax root = (CompilationUnitSyntax)await tree.GetRootAsync(); List <TypeDeclarationSyntax> declarations = root.DescendantNodesAndSelf().Where( x => x.IsKind(SyntaxKind.InterfaceDeclaration) || x.IsKind(SyntaxKind.ClassDeclaration) || x.IsKind(SyntaxKind.StructDeclaration) ).Select(d => d as TypeDeclarationSyntax).ToList(); if (declarations.Count == 0) { continue; } //this.ScriptEnvironment.Info("Got {0} type declarations in compilation unit {1}: {2}", declarations.Count, tree.FilePath, declarations.Select(d => d.Identifier.ValueText).Where(i => !string.IsNullOrEmpty(i)).Aggregate((s1, s2) => s1 + " " + s2)); /* * foreach (TypeDeclarationSyntax d in declarations) * { * string identifier = d.Identifier.ValueText; * this.ScriptEnvironment.Debug(c.Identifier.ValueText); * }*/ } return(this.AnalyzerResult); }
public override SyntaxNode VisitCompilationUnit(CompilationUnitSyntax node) { var descendants = node.DescendantNodesAndSelf(); internals = new HashSet <string>(descendants .OfType <NamespaceDeclarationSyntax>() .Select(n => n.Name.ToString())); externals = new HashSet <string>(descendants .OfType <PropertyDeclarationSyntax>() .Select(p => p.Type) .OfType <QualifiedNameSyntax>() .Select(n => StripGlobalAlias(n.Left).ToString()) .Where(n => !internals.Contains(n))); var result = base.VisitCompilationUnit(node) as CompilationUnitSyntax; result = result.WithUsings(new SyntaxList <UsingDirectiveSyntax>(externals .Select(n => SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(n))))); externals = null; internals = null; return(result); }
protected static void CreateInitialTemplate(string name, out CompilationUnitSyntax root, out ClassDeclarationSyntax extensionDecl) { // create the initial template var initialText = EXTENSION_METHODS_CLASS_TEMPLATE.Replace(NAME_TEMPLATE_VAR, name); root = SyntaxFactory.ParseCompilationUnit(initialText); extensionDecl = root.DescendantNodesAndSelf().OfType <ClassDeclarationSyntax>().Single(); }
private CompilationUnitSyntax AddNamespaceIfMissing(CompilationUnitSyntax root, string namespaceIdentifyer) { var ns = root.DescendantNodesAndSelf() .OfType <UsingDirectiveSyntax>() .FirstOrDefault(elem => elem.Name.ToString() == namespaceIdentifyer); if (ns != null) { return(root); } var usingDirective = SyntaxFactory.UsingDirective(SyntaxFactory.IdentifierName(namespaceIdentifyer)) .WithTrailingTrivia(SyntaxFactory.EndOfLine("\r\n")); var lastUsing = root.DescendantNodesAndSelf().OfType <UsingDirectiveSyntax>().Last(); root = root.InsertNodesAfter(lastUsing, new[] { usingDirective }); return(root); }
public override void VisitCompilationUnit(CompilationUnitSyntax node) { var startNode = node.DescendantNodesAndSelf(n => region.Start <= n.SpanStart).FirstOrDefault(); if (startNode == node || startNode == null) { base.VisitCompilationUnit(node); } else { this.Visit(startNode); } }
public static CompilationUnitSyntax ExtractClass(this CompilationUnitSyntax root, TextSpan span) { var node = root.FindNode(span); var typeDecl = node as BaseTypeDeclarationSyntax; if (typeDecl == null) { return(null); } var member = node as MemberDeclarationSyntax; var namespaceDeclarations = typeDecl .Ancestors() .OfType <NamespaceDeclarationSyntax>() .Select(n => (member = n.WithMembers(SyntaxFactory.SingletonList(member)))); var namespaceDecl = namespaceDeclarations.LastOrDefault() as MemberDeclarationSyntax; if (namespaceDecl == null) { namespaceDecl = typeDecl; } var usings = root .DescendantNodesAndSelf(n => true) .OfType <UsingDirectiveSyntax>() .Select(u => u.WithAdditionalAnnotations(Simplifier.Annotation)); var extAlias = root .ChildNodes() .OfType <ExternAliasDirectiveSyntax>(); var ret = SyntaxFactory.CompilationUnit( SyntaxFactory.List(extAlias), SyntaxFactory.List(usings), SyntaxFactory.List <AttributeListSyntax>(), SyntaxFactory.SingletonList(namespaceDecl) ); return(ret); }
public ExpressionResolverGeneralTests() { _documentCSharpCode = @"using System; using System.Collections; using System.Linq; using System.Text; namespace HelloWorld { class Program { static void Main(string[] args) { var case1 = TestMethod(""unittest"", """"); var case2 = TestMethod(""unit""+""test"",""""); var case3 = TestMethod(""unit""+""test"",""""); var case4 = TestMethod(""u""+""n""+""i""+""t""+""t""+""e""+""s""+""t"",""""); var case5 = TestMethod(constString,""""); var case6 = TestMethod(constUnit+constTest,""""); var case7 = TestMethod($""{constUnit}test"",""""); var case8 = TestMethod($""unit{constTest}"",""""); var case9 = TestMethod($""{constUnit}{constTest}"",""""); var case10 = TestMethod($""{""unit""}{""test""}"",""""); var case11 = TestMethod(stringFromInterpolation,""""); var case12 = TestMethod(nameof(unittest),""""); var case13 = TestMethod(constantStringUnitTest,""""); var case14 = TestMethod(constantNameOfResult,""""); var case15 = TestMethod(string.Format(""{0}"", ""unittest""),""""); var case16 = TestMethod(string.Format(""{0}{1}"", ""unit"",""test""),""""); var case17 = TestMethod(string.Format(""{0}{1}"", ""unit"", constTest),""""); var case18 = TestMethod(string.Format(""{0}{1}"", constUnit, constTest),""""); var case19 = TestMethod(typeof(unittest).Name,""""); var case20 = TestMethod(constantTypeOfNameResult,""""); var case21 = TestMethod(PublicFieldStringUnitTest,""""); var case22 = TestMethod(PrivateFieldStringUnitTest,""""); var case23 = TestMethod(PublicFieldStringUnitTestFromLambda,""""); var case24 = TestMethod(PrivateFieldStringUnitTestFromLambda,""""); var case25 = TestMethod(PublicFieldStringUnitTestWithGetter,""""); var case26 = TestMethod(PrivateFieldStringUnitTestWithGetter,""""); var case27 = TestMethod(PublicFieldStringUnitTestWithGetterNonDirectReturn,""""); var case28 = TestMethod(PrivateFieldStringUnitTestWithGetterNonDirectReturn,""""); var case29 = TestMethod(constUnit.Replace(""unit"", ""unittest""),""""); var case30 = TestMethod(constUnit.Replace(constUnit, ""unittest""),""""); var case31 = TestMethod(constUnit.Replace(constUnit, constString),""""); var constString = ""unittest""; var constUnit = ""unit""; var constTest = ""test""; const string constantStringUnitTest = ""unittest""; const string constantNameOfResult = nameof(unittest); var stringFromInterpolation = $""{constUnit}{constTest}""; var stringFromStringFormat = string.Format(""{0}"", ""unittest""); var constantTypeOfNameResult = typeof(unittest).Name; } public static string TestMethod(string one, string two) { return one + two; } public string PublicFieldStringUnitTest = ""unittest""; private string PrivateFieldStringUnitTest = ""unittest""; public string PublicFieldStringUnitTestFromLambda => ""unittest""; private string PrivateFieldStringUnitTestFromLambda => ""unittest""; public string PublicFieldStringUnitTestWithGetter { get { return ""unittest""; } set { } } private string PrivateFieldStringUnitTestWithGetter { get { return ""unittest""; } set { } } public string PublicFieldStringUnitTestWithGetterNonDirectReturn { get { var returnValue =""unittest""; return returnValue; } set { } } private string PrivateFieldStringUnitTestWithGetterNonDirectReturn { get { var returnValue =""unittest""; return returnValue; } set { } } public void unittest(){} } }"; var projectId = ProjectId.CreateNewId(); var documentId = DocumentId.CreateNewId(projectId); var solution = new AdhocWorkspace().CurrentSolution .AddProject(projectId, "MyProject", "MyProject", LanguageNames.CSharp) .AddMetadataReference(projectId, MetadataReference.CreateFromFile(typeof(object).Assembly.Location)) .AddDocument(documentId, "MyFile.cs", _documentCSharpCode); _document = solution.GetDocument(documentId); SyntaxTree tree = CSharpSyntaxTree.ParseText(_documentCSharpCode); var compilation = CSharpCompilation.Create("HelloWorld") .AddReferences( MetadataReference.CreateFromFile( typeof(object).Assembly.Location)) .AddSyntaxTrees(tree); _semanticModel = compilation.GetSemanticModel(tree); _treeRoot = (CompilationUnitSyntax)tree.GetRoot(); _documentNodes = _treeRoot.DescendantNodesAndSelf(); _sourceText = _treeRoot.GetText(); }
public CompilationUnitSyntax Reduce() { CompileResult debug = Compiler.Compile(Original, Compiler.DebugOptions); CompileResult release = Compiler.Compile(Original, Compiler.ReleaseOptions); Func <CompilationUnitSyntax, bool> isInteresting; if (debug.RoslynException != null || release.RoslynException != null) { CSharpCompilationOptions opts = debug.RoslynException != null ? Compiler.DebugOptions : Compiler.ReleaseOptions; isInteresting = program => Compiler.Compile(program, opts).RoslynException != null; } else if (debug.CompileErrors.Length > 0 || release.CompileErrors.Length > 0) { CSharpCompilationOptions opts = debug.CompileErrors.Length > 0 ? Compiler.DebugOptions : Compiler.ReleaseOptions; isInteresting = program => { CompileResult recompiled = Compiler.Compile(program, opts); if (recompiled.CompileErrors.Length <= 0) { return(false); } return(recompiled.CompileErrors[0].Id == (debug.CompileErrors.Length > 0 ? debug.CompileErrors[0] : release.CompileErrors[0]).Id); }; } else { var origPair = new ProgramPair(debug.Assembly, release.Assembly); ProgramPairResults origResults = ProgramExecutor.RunPair(origPair); if (origResults.DebugResult.Checksum == origResults.ReleaseResult.Checksum && origResults.DebugResult.ExceptionType == origResults.ReleaseResult.ExceptionType) { throw new InvalidOperationException("Program has no errors"); } isInteresting = prog => { ProgramPairResults results = CompileAndRun(prog); if (results == null) { return(false); } // Do exceptions first because they will almost always change checksum if (origResults.DebugResult.ExceptionType != origResults.ReleaseResult.ExceptionType) { // Must throw same exceptions in debug and release to be bad. return(results.DebugResult.ExceptionType == origResults.DebugResult.ExceptionType && results.ReleaseResult.ExceptionType == origResults.ReleaseResult.ExceptionType); } else { if (results.DebugResult.ExceptionType != origResults.DebugResult.ExceptionType || results.ReleaseResult.ExceptionType != origResults.ReleaseResult.ExceptionType) { return(false); } } return(results.DebugResult.Checksum != results.ReleaseResult.Checksum); }; } // Save original comments as simplification may remove it by removing an unnecessary type. SyntaxTriviaList originalTrivia = Original.GetLeadingTrivia(); Reduced = Original.WithLeadingTrivia(); Reduced = CoarseSimplify(Reduced, isInteresting); List <SyntaxNode> simplifiedNodes = new List <SyntaxNode>(); bool first = true; bool any = true; while (any) { any = false; while (true) { if (!SimplifyOne("Statements", Reduced.DescendantNodes().Where(n => n is StatementSyntax).ToList())) { break; } any = true; } while (true) { if (!SimplifyOne("Expressions", Reduced.DescendantNodes().Where(n => n is ExpressionSyntax).ToList())) { break; } any = true; } while (true) { List <SyntaxNode> members = Reduced.DescendantNodesAndSelf().Where(n => n is MemberDeclarationSyntax || n is CompilationUnitSyntax).ToList(); if (!SimplifyOne("Members", members)) { break; } any = true; } first = false; bool SimplifyOne(string name, List <SyntaxNode> list) { for (int i = 0; i < 2000; i++) { Console.Title = $"Simplifying {name}. Iter: {i}"; SyntaxNode node = list[_rng.Next(list.Count)]; // Do not optimize checksum args and call itself. // We still want to remove these statements, however, so we focus on the expression only. InvocationExpressionSyntax invocParent = node.FirstAncestorOrSelf <InvocationExpressionSyntax>(); if (invocParent != null && IsChecksumCall(invocParent)) { continue; } // If we fail at creating a new bad example, then we want to be able to restore the state // so the reducer will not blow these up unnecessarily. int origVarCounter = _varCounter; simplifiedNodes.Clear(); SimplifyNode(node, !first, simplifiedNodes); foreach (SyntaxNode candidateNode in simplifiedNodes) { CompilationUnitSyntax candidate = Reduced.ReplaceNode(node, candidateNode); if (isInteresting(candidate)) { Reduced = candidate; return(true); } } _varCounter = origVarCounter; } return(false); } } List <SyntaxTrivia> outputComments = GetOutputComments(debug, release).Select(Comment).ToList(); SimplifyRuntime(); double oldSizeKiB = Original.NormalizeWhitespace().ToString().Length / 1024.0; double newSizeKiB = Reduced.NormalizeWhitespace().ToString().Length / 1024.0; SyntaxTriviaList newTrivia = originalTrivia.Add(Comment(FormattableString.Invariant($"// Reduced from {oldSizeKiB:F1} KiB to {newSizeKiB:F1} KiB"))) .AddRange(outputComments); Reduced = Reduced.WithLeadingTrivia(newTrivia); return(Reduced); }