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); } }
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); }
public void TestEmpty() { string programText = ""; var tree = CSharpSyntaxTree.ParseText(programText); var records = Inspection.Inspect(tree, DefinedForTest.Rules).ToList(); Assert.AreEqual(0, records.Count); }
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); }
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)); }
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); } } }
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); }
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); }
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)); }
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); }
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); }
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); } }
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)); }
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); }
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); }
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); }
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); } }