Пример #1
0
        public void Test(string programText, string[] expected)
        {
            var tree  = CSharpSyntaxTree.ParseText(programText);
            var root  = (Syntax.CompilationUnitSyntax)tree.GetRoot();
            var first = root.DescendantNodes(descendIntoTrivia: true).First();

            List <Extraction.Pipeline.Code>?got;

            switch (first)
            {
            case Syntax.DocumentationCommentTriviaSyntax documentation:
                got = Extraction.Pipeline.CodesFromDocumentation(documentation);
                break;

            default:
                throw new InvalidOperationException($"Unexpected type of tree: {tree.GetType()}");
            }

            Assert.NotNull(got);
            Assert.AreEqual(expected.Length, got.Count);

            for (var i = 0; i < expected.Length; i++)
            {
                Assert.AreEqual(expected[i], got[i].Text);
            }
        }
Пример #2
0
        public void TestDoesntExist()
        {
            using var tmpdir = new TemporaryDirectory();
            string outputPath = Path.Join(tmpdir.Path, "DocTestSomeProgram.cs");

            string programText = @"
/// <code doctest=""true"">
///    var x = 1;
/// </code>
";

            var doctestsAndErrors = Extraction.Extract(
                CSharpSyntaxTree.ParseText(
                    programText));

            Assert.AreEqual(0, doctestsAndErrors.Errors.Count);
            var doctests = doctestsAndErrors.Doctests;

            // Test pre-condition
            Assert.IsFalse(File.Exists(outputPath));

            var got = Process.Check(doctests, "SomeProgram.cs", outputPath);

            Assert.IsInstanceOf <Report.DoesntExist>(got);
        }
Пример #3
0
        public void TestEmpty()
        {
            string programText = "";
            var    tree        = CSharpSyntaxTree.ParseText(programText);

            var records = Inspection.Inspect(tree, DefinedForTest.Rules).ToList();

            Assert.AreEqual(0, records.Count);
        }
Пример #4
0
        public void TestNotCode()
        {
            string programText = "This is no C# code, but it has a 'TODO (mristin, 2020-07-20): Do something'.";
            var    tree        = CSharpSyntaxTree.ParseText(programText);

            var records = Inspection.Inspect(tree, DefinedForTest.Rules).ToList();

            Assert.AreEqual(0, records.Count);
        }
Пример #5
0
        public void Test(string text, string[] expectedNamespaces)
        {
            var tree = CSharpSyntaxTree.ParseText(text);
            var doctestsAndErrors = Extraction.Extract(tree);

            Assert.That(doctestsAndErrors.Errors, Is.EquivalentTo(new List <Extraction.Error>()));

            var doctests = doctestsAndErrors.Doctests;

            var gotNamespaces = doctests.Select((doctest) => doctest.Namespace).ToList();

            Assert.That(gotNamespaces, Is.EquivalentTo(expectedNamespaces));
        }
Пример #6
0
        public void WriteTypes()
        {
            foreach (var type in this.Types)
            {
                if (type.Value is Enum)
                {
                    var code = Render.FileToString("Enum.cs.template", type.Value);
                    var path = Path.Combine(this.TargetDirectory, $"{type.Value.Name}.cs");

                    var tree = CSharpSyntaxTree.ParseText(code);
                    var root = SyntaxNodeExtensions.NormalizeWhitespace(tree.GetRoot());
                    code = root.ToFullString();
                    File.WriteAllText(path, code);
                }
            }
        }
Пример #7
0
        public void TestOkNoDoctest()
        {
            using var tmpdir = new TemporaryDirectory();
            string outputPath = Path.Join(tmpdir.Path, "Output.cs");

            var doctestsAndErrors = Extraction.Extract(
                CSharpSyntaxTree.ParseText(
                    "No doctest at all"));

            Assert.AreEqual(0, doctestsAndErrors.Errors.Count);
            var doctests = doctestsAndErrors.Doctests;

            Process.Report got = Process.Check(doctests, outputPath);

            Assert.AreEqual(Process.Report.Ok, got);
        }
Пример #8
0
        public void TestOkNoDoctest()
        {
            using var tmpdir = new TemporaryDirectory();
            string outputPath = Path.Join(tmpdir.Path, "DocTestSomeProgram.cs");

            var doctestsAndErrors = Extraction.Extract(
                CSharpSyntaxTree.ParseText(
                    "No doctest at all"));

            Assert.AreEqual(0, doctestsAndErrors.Errors.Count);
            var doctests = doctestsAndErrors.Doctests;

            var got = Process.Check(doctests, "SomeProgram.cs", outputPath);

            Assert.IsInstanceOf <Report.Ok>(got);
        }
Пример #9
0
        public void TestNoDoctest()
        {
            using var tmpdir = new TemporaryDirectory();
            string outputPath = Path.Join(tmpdir.Path, "DocTestSomeProgram.cs");

            var doctestsAndErrors = Extraction.Extract(
                CSharpSyntaxTree.ParseText(
                    "No doctest at all"));

            Assert.AreEqual(0, doctestsAndErrors.Errors.Count);
            var doctests = doctestsAndErrors.Doctests;

            bool got = Process.Generate(doctests, "SomeProgram.cs", outputPath);

            Assert.IsFalse(got);
            Assert.IsFalse(File.Exists(outputPath));
        }
Пример #10
0
        public void TestShouldntExist()
        {
            using var tmpdir = new TemporaryDirectory();
            string outputPath = Path.Join(tmpdir.Path, "DocTestSomeProgram.cs");

            var doctestsAndErrors = Extraction.Extract(
                CSharpSyntaxTree.ParseText(
                    "no doctest"));

            Assert.AreEqual(0, doctestsAndErrors.Errors.Count);
            var doctests = doctestsAndErrors.Doctests;

            File.WriteAllText(outputPath, "should not exist");

            var got = Process.Check(doctests, "SomeProgram.cs", outputPath);

            Assert.IsInstanceOf <Report.ShouldNotExist>(got);
        }
Пример #11
0
        public void TestOkDoctest()
        {
            using var tmpdir = new TemporaryDirectory();
            string outputPath = Path.Join(tmpdir.Path, "DocTestSomeProgram.cs");

            string programText = @"
/// <code doctest=""true"">
///    var x = 1;
/// </code>
";

            var doctestsAndErrors = Extraction.Extract(
                CSharpSyntaxTree.ParseText(
                    programText));

            Assert.AreEqual(0, doctestsAndErrors.Errors.Count);
            var doctests = doctestsAndErrors.Doctests;

            File.WriteAllText(outputPath, @"// This file was automatically generated by doctest-csharp.
// !!! DO NOT EDIT OR APPEND !!!

using NUnit.Framework;

namespace Tests
{
    public class DocTest_SomeProgram_cs
    {
        [Test]
        public void AtLine1AndColumn4()
        {
            var x = 1;
        }
    }
}

// This file was automatically generated by doctest-csharp.
// !!! DO NOT EDIT OR APPEND !!!
");
            var got = Process.Check(doctests, "SomeProgram.cs", outputPath);

            Assert.IsInstanceOf <Report.Ok>(got);
        }
Пример #12
0
        public void TestValidCode()
        {
            string programText = @"
namespace SomeNamespace
{
    // TODO
    class SomeClass
    {
        // TODO: invalid

        // TODO (mristin, 2007-07-20): Do something

        // This is just a comment.
    }
}
";
            var    tree        = CSharpSyntaxTree.ParseText(programText);

            var records = Inspection.Inspect(tree, DefinedForTest.Rules).ToList();

            var expectedRecords = new List <Inspection.Record>
            {
                new Inspection.Record("TODO", "", 3, 4, Inspection.Status.NonMatchingSuffix),
                new Inspection.Record("TODO", ": invalid", 6, 8,
                                      Inspection.Status.NonMatchingSuffix),
                new Inspection.Record("TODO", " (mristin, 2007-07-20): Do something", 8, 8,
                                      Inspection.Status.Ok)
            };

            Assert.AreEqual(expectedRecords.Count, records.Count);

            for (var i = 0; i < expectedRecords.Count; i++)
            {
                string label = $"Record {i}";
                Assert.AreEqual(expectedRecords[i].Prefix, records[i].Prefix, label);
                Assert.AreEqual(expectedRecords[i].Suffix, records[i].Suffix, label);
                Assert.AreEqual(expectedRecords[i].Line, records[i].Line, label);
                Assert.AreEqual(expectedRecords[i].Column, records[i].Column, label);
                Assert.AreEqual(expectedRecords[i].Status, records[i].Status, label);
            }
        }
Пример #13
0
        public void TestDoctest()
        {
            using var tmpdir = new TemporaryDirectory();
            string outputPath = Path.Join(tmpdir.Path, "DocTestSomeProgram.cs");

            var doctestsAndErrors = Extraction.Extract(
                CSharpSyntaxTree.ParseText(
                    @"/// <code doctest=""true"">
/// var x = 1;
/// </code>"));

            Assert.AreEqual(0, doctestsAndErrors.Errors.Count);
            var doctests = doctestsAndErrors.Doctests;

            bool got = Process.Generate(doctests, "SomeProgram.cs", outputPath);

            Assert.IsTrue(got);
            Assert.IsTrue(File.Exists(outputPath));
            Assert.AreEqual(@"// This file was automatically generated by doctest-csharp.
// !!! DO NOT EDIT OR APPEND !!!

using NUnit.Framework;

namespace Tests
{
    public class DocTest_SomeProgram_cs
    {
        [Test]
        public void AtLine0AndColumn4()
        {
            var x = 1;
        }
    }
}

// This file was automatically generated by doctest-csharp.
// !!! DO NOT EDIT OR APPEND !!!
",
                            File.ReadAllText(outputPath));
        }
Пример #14
0
        public void TestDifferent()
        {
            using var tmpdir = new TemporaryDirectory();
            string outputPath = Path.Join(tmpdir.Path, "Output.cs");

            string programText       = @"
/// <code doctest=""true"">
///    var x = 1;
/// </code>
";
            var    doctestsAndErrors = Extraction.Extract(
                CSharpSyntaxTree.ParseText(
                    programText));

            Assert.AreEqual(0, doctestsAndErrors.Errors.Count);
            var doctests = doctestsAndErrors.Doctests;

            File.WriteAllText(outputPath, "different content");

            Process.Report got = Process.Check(doctests, outputPath);

            Assert.AreEqual(Process.Report.Different, got);
        }
Пример #15
0
        private static int Handle(DirectoryInfo input, DirectoryInfo output, string[]?excludes, bool check)
        {
            int exitCode = 0;

            IEnumerable <string> relativePaths = Input.MatchFiles(
                input.FullName,
                new List <string> {
                "**/*.cs"
            },
                new List <string>(excludes ?? new string[0]));

            foreach (string relativePath in relativePaths)
            {
                if (Path.IsPathRooted(relativePath))
                {
                    throw new InvalidOperationException(
                              $"Expected path to be relative, but got rooted path: {relativePath}");
                }

                string inputPath  = Process.InputPath(relativePath, input);
                string outputPath = Process.OutputPath(relativePath, output);

                var doctestsAndErrors = Extraction.Extract(
                    CSharpSyntaxTree.ParseText(
                        File.ReadAllText(inputPath)));

                if (doctestsAndErrors.Errors.Count > 0)
                {
                    Console.WriteLine($"Failed to extract doctest(s) from: {inputPath}");
                    foreach (var error in doctestsAndErrors.Errors)
                    {
                        Console.WriteLine($"* Line {error.Line + 1}, column {error.Column + 1}: {error.Message}");
                    }

                    exitCode = 1;

                    continue;
                }

                var doctests = doctestsAndErrors.Doctests;

                if (!check)
                {
                    bool generated = Process.Generate(doctests, outputPath);
                    Console.WriteLine(
                        generated
                        ? $"Generated doctest(s) for: {inputPath} -> {outputPath}"
                        : $"No doctests found in: {inputPath}; not generating {outputPath}");
                }
                else
                {
                    var report = Process.Check(doctests, outputPath);
                    switch (report)
                    {
                    case Process.Report.Ok:
                        Console.WriteLine($"OK: {inputPath} -> {outputPath}");
                        break;

                    case Process.Report.Different:
                        Console.WriteLine($"Expected different content: {inputPath} -> {outputPath}");
                        exitCode = 1;
                        break;

                    case Process.Report.DoesntExist:
                        Console.WriteLine($"Output file does not exist: {inputPath} -> {outputPath}");
                        exitCode = 1;
                        break;

                    case Process.Report.ShouldNotExist:
                        Console.WriteLine(
                            $"No doctests found in: {inputPath}; the output should not exist: {outputPath}");
                        exitCode = 1;
                        break;

                    default:
                        throw new NotImplementedException($"Uncovered report: {report}");
                    }
                }
            }

            return(exitCode);
        }
Пример #16
0
        private static int Handle(string[] inputOutput, string suffix, string[]?excludes, bool check, bool verbose)
        {
            int exitCode = 0;

            var inputOutputOrError = Input.ParseInputOutput(inputOutput, suffix);

            if (inputOutputOrError.Error != null)
            {
                Console.Error.WriteLine($"Failed to parse --input-output: {inputOutputOrError.Error}");
                return(1);
            }

            if (inputOutputOrError.InputOutput == null)
            {
                throw new InvalidOperationException(
                          "Invalid inputOutputOrError: both InputOutput and Error are null.");
            }

            string cwd = Directory.GetCurrentDirectory();

            foreach (var(input, output) in inputOutputOrError.InputOutput)
            {
                string rootedInput =
                    Path.IsPathRooted(input)
                        ? input
                        : Path.Join(cwd, input);

                string rootedOutput =
                    Path.IsPathRooted(output)
                        ? output
                        : Path.Join(cwd, output);

                IEnumerable <string> relativePaths = Input.MatchFiles(
                    rootedInput,
                    new List <string> {
                    "**/*.cs"
                },
                    new List <string>(excludes ?? new string[0]));

                foreach (string relativePath in relativePaths)
                {
                    if (Path.IsPathRooted(relativePath))
                    {
                        throw new InvalidOperationException(
                                  $"Expected path to be relative, but got rooted path: {relativePath}");
                    }

                    string inputPath  = Process.InputPath(relativePath, rootedInput);
                    string outputPath = Process.OutputPath(relativePath, rootedOutput);

                    var doctestsAndErrors = Extraction.Extract(
                        CSharpSyntaxTree.ParseText(
                            File.ReadAllText(inputPath)));

                    if (doctestsAndErrors.Errors.Count > 0)
                    {
                        Console.WriteLine($"Failed to extract doctest(s) from: {inputPath}");
                        foreach (var error in doctestsAndErrors.Errors)
                        {
                            Console.WriteLine($"* Line {error.Line + 1}, column {error.Column + 1}: {error.Message}");
                        }

                        exitCode = 1;

                        continue;
                    }

                    var doctests = doctestsAndErrors.Doctests;

                    if (!check)
                    {
                        bool generated = Process.Generate(doctests, relativePath, outputPath);

                        if (verbose)
                        {
                            Console.WriteLine(
                                generated
                                    ? $"Generated doctest(s) for: {inputPath} -> {outputPath}"
                                    : $"No doctests found in: {inputPath}");
                        }
                    }
                    else
                    {
                        var report = Process.Check(doctests, relativePath, outputPath);
                        switch (report)
                        {
                        case Report.Ok _:
                            if (verbose)
                            {
                                Console.WriteLine(
                                    (doctests.Count > 0)
                                            ? $"OK: {inputPath} -> {outputPath}"
                                            : $"OK, no doctests: {inputPath}");
                            }
                            break;

                        case Report.Different reportDifferent:
                            Console.WriteLine($"Expected different content: {inputPath} -> {outputPath}");
                            Console.WriteLine(
                                "Here is the diff between the expected content and the actual content:");

                            foreach (var line in reportDifferent.Diff.Lines)
                            {
                                switch (line.Type)
                                {
                                case DiffPlex.DiffBuilder.Model.ChangeType.Inserted:
                                    Console.Write("+ ");
                                    break;

                                case DiffPlex.DiffBuilder.Model.ChangeType.Deleted:
                                    Console.Write("- ");
                                    break;

                                default:
                                    Console.Write("  ");
                                    break;
                                }

                                Console.WriteLine(line.Text);
                            }

                            exitCode = 1;
                            break;

                        case Report.DoesntExist _:
                            Console.WriteLine($"Output file does not exist: {inputPath} -> {outputPath}");
                            exitCode = 1;
                            break;

                        case Report.ShouldNotExist _:
                            Console.WriteLine(
                                $"No doctests found in: {inputPath}; the output should not exist: {outputPath}");
                            exitCode = 1;
                            break;

                        default:
                            throw new NotImplementedException($"Uncovered report: {report}");
                        }
                    }
                }
            }

            return(exitCode);
        }
Пример #17
0
        public void TestMethodDoctest()
        {
            string text     = @"
namespace SomeNamespace
{
    public static class SomeClass
    {
        /// <summary>
        /// Does something.
        /// </summary>
        /// <code doctest=""true"">
        /// using Microsoft.CodeAnalysis.SyntaxTree;
        /// // ---
        /// var x = 1;
        /// </code>
        public void SomeMethod() 
        {
            // some implementation
            var y = 2;
        }

        /// <summary>
        /// Does something else.
        /// </summary>
        /// <code doctest=""true"">
        /// var y = 2;
        /// </code>
        public void AnotherMethod() 
        {
            // another implementation
            var z = 3;
        }
    } 
}
";
            var    expected = new List <Extraction.Doctest>
            {
                new Extraction.Doctest(
                    ns: "SomeNamespace",
                    usings: new List <Extraction.UsingDirective>
                {
                    new Extraction.UsingDirective("Microsoft.CodeAnalysis.SyntaxTree", null)
                },
                    body: "var x = 1;",
                    line: 8,
                    column: 12),
                new Extraction.Doctest(
                    ns: "SomeNamespace",
                    usings: new List <Extraction.UsingDirective>(),
                    body: "var y = 2;",
                    line: 22,
                    column: 12)
            };

            var tree = CSharpSyntaxTree.ParseText(text);
            var doctestsAndErrors = Extraction.Extract(tree);

            Assert.That(doctestsAndErrors.Errors, Is.EquivalentTo(new List <Extraction.Error>()));

            var doctests = doctestsAndErrors.Doctests;

            Assert.AreEqual(expected.Count, doctests.Count);
            for (var i = 0; i < doctests.Count; i++)
            {
                Assert.AreEqual(expected[i].Namespace, doctests[i].Namespace);
                Assert.That(doctests[i].Usings, Is.EquivalentTo(expected[i].Usings));
                Assert.AreEqual(expected[i].Body, doctests[i].Body);
                Assert.AreEqual(expected[i].Line, doctests[i].Line);
                Assert.AreEqual(expected[i].Column, doctests[i].Column);
            }
        }