public async Task FindSource_WithInvalidCursorPosition_ReturnsNoValue()
        {
            var searcher = new ExpressionSearcher();

            var result = await searcher.FindSource(
                solution: DefaultSolution(),
                activeDocument: DefaultActiveDocument(),
                cursorPosition: InvalidCursorPosition());

            Assert.IsNull(result);
        }
        public async Task FindSource_LookingForExpression_ReturnsTheExpression()
        {
            var searcher = new ExpressionSearcher();

            var expression = "\"text\".ToString().ToString()";
            var file = @"
            public void Do() {
                var result = " + expression + @";
            }";
            var activeDocument = DefaultActiveDocument();
            var result = await searcher.FindSource(
                solution: SingleFileSolution(file),
                activeDocument: DefaultActiveDocument(),
                cursorPosition: file.IndexOf(expression));

            Assert.AreEqual(expression, result.GetText().ToString());
        }
        public async Task<string> GenerateViewAsync(string solutionPath, string activeDocument = null, int cursorPosition = -1)
        {
            var view = string.Empty;

            using (var tempDirectory = new TempDirectory())
            {
                try
                {
                    var workspace = MSBuildWorkspace.Create();
                    var solution = await workspace.OpenSolutionAsync(solutionPath);
                    var newSolution = solution.GetIsolatedSolution();

                    var expressionSearcher = new ExpressionSearcher();
                    var expressionBuilder = new ExpressionBuilder();
                    var source = await expressionSearcher.FindSource(newSolution, activeDocument, cursorPosition);
                    var target = await expressionSearcher.FindTarget(newSolution);
                    var instrumentation = await expressionBuilder.BuildWrapper(source);

                    var newCompilation = expressionSearcher.InsertNodeInCompilation(target.Compilation, target.Node, instrumentation);

                    var instrumentedDll = Path.Combine(tempDirectory.FullName, Path.GetRandomFileName() + ".dll");
                    var emitResult = newCompilation.Emit(instrumentedDll);
                    if (emitResult.Success)
                    {
                        using (var assemblyRunner = new AssemblyRunner())
                        {
                            var result = assemblyRunner.Run(instrumentedDll, "WrapperClass", "WrapperMethod");
                            view = result;
                        }
                    }
                    else
                    {
                        view = string.Join(Environment.NewLine, emitResult.Diagnostics);
                    }
                }
                catch (Exception exception)
                {
                    Console.WriteLine(exception.ToString());
                    view = exception.ToString();
                }
            }

            return view;
        }
        public async Task InsertNodeInCompilation_WithOldAndNewNodes_LeavesOldClassInPlace()
        {
            var searcher = new ExpressionSearcher();
            var oldClassName = "SimpleClass";
            var solution = SingleFileSolution(@"
            namespace " + oldClassName + @" {
                public class SimpleClass() {
                    public void Do() {
                    }
                }
            }");
            var target = await searcher.FindTarget(solution);
            SyntaxNode newNode = SyntaxFactory.ClassDeclaration("NewNode");

            var newCompilation = searcher.InsertNodeInCompilation(target.Compilation, target.Node, newNode);

            var classes = GetClassDeclarationSyntaxes(newCompilation);
            Assert.AreEqual(1, classes.Count(classSyntax => classSyntax.Identifier.Text == oldClassName));
        }
        public async Task InsertNodeInCompilation_WithOldAndNewNodes_ReturnsNewUpdatedCompilation()
        {
            var searcher = new ExpressionSearcher();
            var solution = SingleFileSolution(@"
            namespace SimpleNamespace {
                public class SimpleClass() {
                    public void Do() {
                    }
                }
            }");
            var target = await searcher.FindTarget(solution);
            SyntaxNode newNode = SyntaxFactory.ClassDeclaration("NewNode");

            var newCompilation = searcher.InsertNodeInCompilation(target.Compilation, target.Node, newNode);

            Assert.AreNotEqual(target.Compilation, newCompilation);
        }
        public async Task FindTarget_WithNamespaceInFileSolution_ReturnsTarget()
        {
            var searcher = new ExpressionSearcher();

            var solution = SingleFileSolution(@"
            namespace SimpleNamespace {
                public class SimpleClass() {
                    public void Do() {
                    }
                }
            }");
            var result = await searcher.FindTarget(solution);

            Assert.IsTrue(result.Node is ClassDeclarationSyntax);
            Assert.IsNotNull(result.Compilation);
        }
        public async Task FindTarget_WithEmptySolution_ReturnsNoValue()
        {
            var searcher = new ExpressionSearcher();

            var solution = EmptySolution();
            var result = await searcher.FindTarget(solution);

            Assert.IsNull(result.Node);
            Assert.IsNull(result.Compilation);
        }
        public async Task FindSource_MethodWithMultipleExpressions_ReturnsTheRequestedExpression()
        {
            var expressions = new[]
            {
                "\"text1\".ToString().ToString()",
                "\"text2\".ToString().ToString()",
                "\"text3\".ToString().ToString()"
            };
            var file = @"
            public string Do()
            {
                var result1 = " + expressions[0] + @";
                var result2 = " + expressions[1] + @";
                return " + expressions[2] + @";
            }";

            foreach (var expression in expressions)
            {
                var searcher = new ExpressionSearcher();

                var result = await searcher.FindSource(
                    solution: SingleFileSolution(file),
                    activeDocument: DefaultActiveDocument(),
                    cursorPosition: file.IndexOf(expression));

                Assert.AreEqual(expression, result.GetText().ToString());
            }
        }
        public async Task FindSource_WithBadCursorPosition_ReturnsNoValue()
        {
            var searcher = new ExpressionSearcher();

            var expression = "\"text\".ToString().ToString()";
            var file = @"
            public void Do() {
                var result = " + expression + @";
            }";
            var activeDocument = DefaultActiveDocument();
            var result = await searcher.FindSource(
                solution: SingleFileSolution(file),
                activeDocument: DefaultActiveDocument(),
                cursorPosition: file.IndexOf(expression) - 1);

            Assert.IsNull(result);
        }