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);
        }
Example #2
0
 public static NamespaceDeclarationSyntax GetNamespaceDeclaration(
     this CompilationUnitSyntax compilation)
 =>
 compilation
 .DescendantNodesAndSelf()
 .OfType <NamespaceDeclarationSyntax>()
 .FirstOrDefault();
Example #3
0
        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);
        }
Example #4
0
        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();
        }
Example #6
0
        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);
            }
        }
Example #8
0
        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();
        }
Example #10
0
        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);
        }