Skip to content

Commit

Permalink
feat: Add nullable annotation
Browse files Browse the repository at this point in the history
Add C# 8 nullable annotations

See pull request #15 from ap0llo/features/nullable-reference-types
  • Loading branch information
ap0llo authored Dec 30, 2019
2 parents 8aeb74f + 530acd5 commit c6c5f28
Show file tree
Hide file tree
Showing 53 changed files with 192 additions and 132 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ public static implicit operator MdSpan(string text);

The string value to wrap in a span.

## Remarks

Wraps a string in an instance of [MdTextSpan](../../MdTextSpan/index.md). Although the nullable annotations do not indicate it, passing in `null` will return `null`.

## Returns

[MdSpan](../index.md)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ public static implicit operator MdTextSpan(string text);

The string value to wrap in an instance of [MdTextSpan](../index.md)

## Remarks

Wraps a string in an instance of [MdTextSpan](../index.md). Although the nullable annotations do not indicate it, passing in `null` will return `null`.

## Returns

[MdTextSpan](../index.md)
Expand Down
3 changes: 2 additions & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@


<PropertyGroup>
<LangVersion>7.2</LangVersion>
<LangVersion>8.0</LangVersion>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ public sealed class CodeSample : IXunitSerializable
// parameterless constructor required for deserialization by xunit
public CodeSample()
{

RelativePath = null!; // Set by Deserialize();
SourceCode = null!; // Set by Deserialize();
}

public CodeSample(string relativePath, int line, string code)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -959,7 +959,7 @@ public void EmptyBlock_is_seralized_as_expected() =>
AssertToStringEquals("", new MdDocument(MdEmptyBlock.Instance));


private void AssertToStringEquals(string expected, MdDocument document, MdSerializationOptions options = null)
private void AssertToStringEquals(string expected, MdDocument document, MdSerializationOptions? options = null)
{
using (var writer = new StringWriter())
{
Expand Down
4 changes: 2 additions & 2 deletions src/MarkdownGenerator.Test/_Model/DocumentSetTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public void Indexer_returns_expected_document()
public void Indexer_throws_ArgumentNullException_if_path_is_null()
{
var set = new DocumentSet<TestDocument>();
Assert.Throws<ArgumentNullException>(() => set[(string)null]);
Assert.Throws<ArgumentNullException>(() => set[(string)null!]);
}

[Fact]
Expand All @@ -56,7 +56,7 @@ public void Indexer_returns_a_documents_path()
public void Indexer_throws_ArgumentNullException_if_document_is_null()
{
var set = new DocumentSet<TestDocument>();
Assert.Throws<ArgumentNullException>(() => set[(TestDocument)null]);
Assert.Throws<ArgumentNullException>(() => set[(TestDocument)null!]);
}

[Fact]
Expand Down
4 changes: 2 additions & 2 deletions src/MarkdownGenerator.Test/_Model/MdDocumentSetTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public void Indexer_returns_expected_document()
public void Indexer_throws_ArgumentNullException_if_path_is_null()
{
var set = new MdDocumentSet();
Assert.Throws<ArgumentNullException>(() => set[(string)null]);
Assert.Throws<ArgumentNullException>(() => set[(string)null!]);
}

[Fact]
Expand All @@ -49,7 +49,7 @@ public void Indexer_returns_a_documents_path()
public void Indexer_throws_ArgumentNullException_if_document_is_null()
{
var set = new MdDocumentSet();
Assert.Throws<ArgumentNullException>(() => set[(MdDocument)null]);
Assert.Throws<ArgumentNullException>(() => set[(MdDocument)null!]);
}

[Fact]
Expand Down
8 changes: 4 additions & 4 deletions src/MarkdownGenerator.Test/_Model/_Blocks/MdBlockQuoteTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ public void MdBlockQuote_can_be_initialized_with_string_content_02()
var compositeSpan = (MdCompositeSpan)paragraph.Text;

Assert.Equal(2, compositeSpan.Spans.Count);
Assert.IsType<MdTextSpan>(compositeSpan.Spans[0]);
Assert.IsType<MdTextSpan>(compositeSpan.Spans[1]);
var textSpan1 = Assert.IsType<MdTextSpan>(compositeSpan.Spans[0]);
var textSpan2 = Assert.IsType<MdTextSpan>(compositeSpan.Spans[1]);

Assert.Equal("Content1", (compositeSpan.Spans[0] as MdTextSpan).Text);
Assert.Equal("Content2", (compositeSpan.Spans[1] as MdTextSpan).Text);
Assert.Equal("Content1", textSpan1.Text);
Assert.Equal("Content2", textSpan2.Text);
}

[Fact]
Expand Down
8 changes: 4 additions & 4 deletions src/MarkdownGenerator.Test/_Model/_Blocks/MdListItemTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ public void MdListItem_can_be_initialized_with_string_content_02()
var compositeSpan = (MdCompositeSpan)paragraph.Text;

Assert.Equal(2, compositeSpan.Spans.Count);
Assert.IsType<MdTextSpan>(compositeSpan.Spans[0]);
Assert.IsType<MdTextSpan>(compositeSpan.Spans[1]);
var textSpan1 = Assert.IsType<MdTextSpan>(compositeSpan.Spans[0]);
var textSpan2 = Assert.IsType<MdTextSpan>(compositeSpan.Spans[1]);

Assert.Equal("Content1", (compositeSpan.Spans[0] as MdTextSpan).Text);
Assert.Equal("Content2", (compositeSpan.Spans[1] as MdTextSpan).Text);
Assert.Equal("Content1", textSpan1.Text);
Assert.Equal("Content2", textSpan2.Text);
}

[Fact]
Expand Down
8 changes: 4 additions & 4 deletions src/MarkdownGenerator.Test/_Model/_Blocks/MdParagraphTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ public void MdParagraph_can_be_initialized_with_string_content_02()
var compositeSpan = (MdCompositeSpan)paragraph.Text;

Assert.Equal(2, compositeSpan.Spans.Count);
Assert.IsType<MdTextSpan>(compositeSpan.Spans[0]);
Assert.IsType<MdTextSpan>(compositeSpan.Spans[1]);
var textSpan1 = Assert.IsType<MdTextSpan>(compositeSpan.Spans[0]);
var textSpan2 = Assert.IsType<MdTextSpan>(compositeSpan.Spans[1]);

Assert.Equal("Content1", (compositeSpan.Spans[0] as MdTextSpan).Text);
Assert.Equal("Content2", (compositeSpan.Spans[1] as MdTextSpan).Text);
Assert.Equal("Content1", textSpan1.Text);
Assert.Equal("Content2", textSpan2.Text);
}


Expand Down
16 changes: 8 additions & 8 deletions src/MarkdownGenerator.Test/_Model/_Blocks/MdTableRowTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ public void MdTableRow_can_be_initialized_with_string_content_02()
var singleLineSpan1 = (MdSingleLineSpan)row[0];
var singleLineSpan2 = (MdSingleLineSpan)row[1];

Assert.IsType<MdTextSpan>(singleLineSpan1.Content);
Assert.IsType<MdTextSpan>(singleLineSpan2.Content);
var textSpan1 = Assert.IsType<MdTextSpan>(singleLineSpan1.Content);
var textSpan2 = Assert.IsType<MdTextSpan>(singleLineSpan2.Content);

Assert.Equal("Content1", (singleLineSpan1.Content as MdTextSpan).Text);
Assert.Equal("Content2", (singleLineSpan2.Content as MdTextSpan).Text);
Assert.Equal("Content1", textSpan1.Text);
Assert.Equal("Content2", textSpan2.Text);
}

[Fact]
Expand All @@ -88,11 +88,11 @@ public void MdTableRow_can_be_initialized_with_string_content_03()
var singleLineSpan1 = (MdSingleLineSpan)row[0];
var singleLineSpan2 = (MdSingleLineSpan)row[1];

Assert.IsType<MdTextSpan>(singleLineSpan1.Content);
Assert.IsType<MdTextSpan>(singleLineSpan2.Content);
var textSpan1 = Assert.IsType<MdTextSpan>(singleLineSpan1.Content);
var textSpan2 = Assert.IsType<MdTextSpan>(singleLineSpan2.Content);

Assert.Equal("Content1", (singleLineSpan1.Content as MdTextSpan).Text);
Assert.Equal("Content2", (singleLineSpan2.Content as MdTextSpan).Text);
Assert.Equal("Content1", textSpan1.Text);
Assert.Equal("Content2", textSpan2.Text);
}

[Fact]
Expand Down
2 changes: 1 addition & 1 deletion src/MarkdownGenerator.Test/_Model/_Blocks/MdTableTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public void Insert_throws_expected_exceptions()
var instance = new MdTable(new MdTableRow(MdEmptySpan.Instance));

// ACT / ASSERT
Assert.Throws<ArgumentNullException>(() => instance.Insert(0, null));
Assert.Throws<ArgumentNullException>(() => instance.Insert(0, null!));
Assert.Throws<ArgumentOutOfRangeException>(() => instance.Insert(-1, new MdTableRow(MdEmptySpan.Instance)));
Assert.Throws<ArgumentOutOfRangeException>(() => instance.Insert(2, new MdTableRow(MdEmptySpan.Instance)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Grynwald.MarkdownGenerator.Test
{
public class MdSerializationOptionsTest
{
private object GetTestValue(Type type)
private object? GetTestValue(Type type)
{
if (!type.IsValueType)
{
Expand Down Expand Up @@ -37,7 +37,7 @@ public static IEnumerable<object[]> DefaultInstancesAndProperties()
yield return new object[] { MdSerializationOptions.Default, property.Name };
foreach(var presetField in typeof(MdSerializationOptions.Presets).GetFields(BindingFlags.Static | BindingFlags.Public))
{
yield return new object[] { presetField.GetValue(null), property.Name };
yield return new object[] { presetField.GetValue(null)!, property.Name };
}
}
}
Expand All @@ -47,16 +47,17 @@ public static IEnumerable<object[]> DefaultInstancesAndProperties()
public void Properties_of_the_default_instances_cannot_be_modified(MdSerializationOptions instance, string propertyName)
{
// ARRANGE
var property = typeof(MdSerializationOptions).GetProperty(propertyName);
var property = typeof(MdSerializationOptions).GetProperty(propertyName)!;

var testValue = GetTestValue(property.PropertyType);

// ACT / ASSERT
var exception = Assert.Throws<TargetInvocationException>(() => property.SetMethod.Invoke(instance, new[] { testValue }));
Assert.IsType<InvalidOperationException>(exception.InnerException);
var exception = Assert.Throws<TargetInvocationException>(() => property.SetMethod!.Invoke(instance, new[] { testValue }));
Assert.NotNull(exception.InnerException);
var innerException = Assert.IsType<InvalidOperationException>(exception.InnerException);

// exception message should indicate which property cannot be set
Assert.Contains(propertyName, exception.InnerException.Message);
Assert.Contains(propertyName, innerException.Message);
}

public static IEnumerable<object[]> Properties()
Expand All @@ -76,11 +77,11 @@ public void Properties_of_non_default_instance_can_be_modified(string propertyNa

var property = typeof(MdSerializationOptions).GetProperty(propertyName);

var newValue = GetTestValue(property.PropertyType);
var newValue = GetTestValue(property!.PropertyType);

// ACT / ASSERT
property.SetMethod.Invoke(instance, new[] { newValue });
var actualValue = property.GetMethod.Invoke(instance, Array.Empty<object>());
property.SetMethod!.Invoke(instance, new[] { newValue });
var actualValue = property.GetMethod!.Invoke(instance, Array.Empty<object>());
Assert.Equal(newValue, actualValue);
}

Expand Down Expand Up @@ -111,7 +112,7 @@ public static IEnumerable<object[]> PresetInstancesAndNames()
{
foreach (var presetField in typeof(MdSerializationOptions.Presets).GetFields(BindingFlags.Static | BindingFlags.Public))
{
yield return new object[] { presetField.GetValue(null), presetField.Name };
yield return new object[] { presetField.GetValue(null)!, presetField.Name };
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/MarkdownGenerator.Test/_Model/_Spans/MdSpanTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ public void String_can_be_implicitly_converted_to_MdSpan(string str)
}
else
{
Assert.IsType<MdTextSpan>(span);
Assert.Equal(str, (span as MdTextSpan).Text);
var textSpan = Assert.IsType<MdTextSpan>(span);
Assert.Equal(str, textSpan.Text);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ public MdAdmonition(string type, MdSpan title, IEnumerable<MdBlock> content) : b


/// <inheritdoc />
public override bool DeepEquals(MdBlock other) => other is MdAdmonition containerBlock ? DeepEquals(containerBlock) : false;
public override bool DeepEquals(MdBlock? other) => other is MdAdmonition containerBlock ? DeepEquals(containerBlock) : false;

/// <inheritdoc />
internal override void Accept(IBlockVisitor visitor) => visitor.Visit(this);
Expand Down
8 changes: 4 additions & 4 deletions src/MarkdownGenerator/FactoryMethods.Blocks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public static partial class FactoryMethods
/// Creates a new instance of <see cref="MdParagraph"/> with the specified content.
/// </summary>
/// <param name="text">The paragraph's content</param>
public static MdParagraph Paragraph(MdSpan text) => new MdParagraph(text);
public static MdParagraph Paragraph(MdSpan text) => new MdParagraph(text!);

/// <summary>
/// Creates a new instance of <see cref="MdParagraph"/> with the specified content.
Expand All @@ -68,7 +68,7 @@ public static partial class FactoryMethods
/// the compiler does not seem to match the method in all situations,
/// e.g. <c>new [] { "foo", "bar" }).Select(Paragraph)</c> so this overload is still necessary.
/// </remarks>
public static MdParagraph Paragraph(string text) => new MdParagraph(text);
public static MdParagraph Paragraph(string text) => new MdParagraph(text!);

/// <summary>
/// Creates a new instance of <see cref="MdParagraph"/> with the specified content.
Expand Down Expand Up @@ -170,7 +170,7 @@ public static partial class FactoryMethods
/// the compiler does not seem to match the method in all situations,
/// e.g. <c>new [] { "foo", "bar" }).Select(ListItem)</c> so this overload is still necessary.
/// </remarks>
public static MdListItem ListItem(string content) => new MdListItem(content);
public static MdListItem ListItem(string content) => new MdListItem(content!);

/// <summary>
/// Creates a new instance of <see cref="MdListItem"/> containing the specified spans
Expand Down Expand Up @@ -233,7 +233,7 @@ public static partial class FactoryMethods
/// the compiler does not seem to match the method in all situations,
/// e.g. <c>new [] { "foo", "bar" }).Select(BlockQuote)</c> so this overload is still necessary.
/// </remarks>
public static MdBlockQuote BlockQuote(string content) => new MdBlockQuote(content);
public static MdBlockQuote BlockQuote(string content) => new MdBlockQuote(content!);

/// <summary>
/// Creates a new instance of <see cref="MdBlockQuote"/> with the specified content
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ internal partial class DocumentSerializer : IBlockVisitor
public DocumentSerializer(TextWriter writer) : this(writer, null)
{ }

public DocumentSerializer(TextWriter writer, MdSerializationOptions options)
public DocumentSerializer(TextWriter writer, MdSerializationOptions? options)
{
m_Writer = new PrefixTextWriter(writer ?? throw new ArgumentNullException(nameof(writer)));
m_Options = options ?? MdSerializationOptions.Default;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ namespace Grynwald.MarkdownGenerator.Internal
internal abstract class ListPrefixHandler : IPrefixHandler
{
protected readonly MdSerializationOptions m_SerializationOptions;
protected string m_ListPrefix; // the prefix for lines other than the first line
protected string? m_ListPrefix; // the prefix for lines other than the first line
protected bool m_LineWritten = false; // indicates if any lines have been written in the current list item
protected string m_ListMarker; // the prefix for list items
protected string? m_ListMarker; // the prefix for list items


public ListPrefixHandler(MdSerializationOptions serializationOptions)
Expand All @@ -16,12 +16,12 @@ public ListPrefixHandler(MdSerializationOptions serializationOptions)
}


public int PrefixLength => m_LineWritten ? m_ListPrefix.Length : m_ListMarker.Length;
public int PrefixLength => m_LineWritten ? m_ListPrefix!.Length : m_ListMarker!.Length;


public string GetBlankLinePrefix() => m_ListPrefix;
public string? GetBlankLinePrefix() => m_ListPrefix;

public string GetLinePrefix()
public string? GetLinePrefix()
{
// prefix the first line in the list item with the list marker,
// other lines are just indented by the width of the list marker
Expand Down
4 changes: 2 additions & 2 deletions src/MarkdownGenerator/Internal/_TextWriter/IPrefixHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ internal interface IPrefixHandler
int PrefixLength { get; }


string GetLinePrefix();
string? GetLinePrefix();

string GetBlankLinePrefix();
string? GetBlankLinePrefix();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ internal sealed class PrefixTextWriter
private readonly LinkedList<IPrefixHandler> m_PrefixHandlers = new LinkedList<IPrefixHandler>();


public event EventHandler<EventArgs> LineWritten;
public event EventHandler<EventArgs>? LineWritten;

public event EventHandler<EventArgs> BlankLineRequested;
public event EventHandler<EventArgs>? BlankLineRequested;


public int PrefixLength => m_PrefixHandlers.Sum(x => x.PrefixLength);
Expand Down
14 changes: 10 additions & 4 deletions src/MarkdownGenerator/SyntaxVisualizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ private class GraphBuildingVisitor : IBlockVisitor, ISpanVisitor

private AsciiTreeNode CurrentNode => m_Nodes.Peek();

public AsciiTreeNode RootNode { get; private set; }
public AsciiTreeNode? RootNode { get; private set; }


public void Visit(MdHeading heading)
Expand Down Expand Up @@ -188,7 +188,10 @@ public static string GetSyntaxTree(MdDocument document)
document.Root.Accept(visitor);

var rootNode = new AsciiTreeNode(document.GetType().Name);
rootNode.Children.Add(visitor.RootNode);
if(visitor.RootNode != null)
{
rootNode.Children.Add(visitor.RootNode);
}

// generate ascii tree
var treeWriter = new AsciiTreeWriter();
Expand All @@ -210,11 +213,14 @@ public static string GetSyntaxTree(MdBlock block)

// convert the block into a graph
var visitor = new GraphBuildingVisitor();
block.Accept(visitor);
block!.Accept(visitor);

// generate ascii tree
var treeWriter = new AsciiTreeWriter();
treeWriter.WriteNode(visitor.RootNode);
if (visitor.RootNode != null)
{
treeWriter.WriteNode(visitor.RootNode);
}

// return ascii tree
return treeWriter.ToString();
Expand Down
Loading

0 comments on commit c6c5f28

Please sign in to comment.