diff --git a/.appveyor.yml b/.appveyor.yml
index 1dbceb116..c180aecce 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -6,6 +6,10 @@ image: Visual Studio 2017
#---------------------------------#
# Build Script #
#---------------------------------#
+install:
+ # Update to latest NuGet version since we require 5.3.0 for embedded icon
+ - ps: nuget update -self
+
build_script:
- ps: .\build.ps1 -Target AppVeyor
@@ -27,4 +31,4 @@ branches:
# Build Cache #
#---------------------------------#
cache:
-- tools -> setup.cake
+- tools -> recipe.cake
diff --git a/3rd-Party-License.md b/3rd-Party-License.md
new file mode 100644
index 000000000..9487ddc3d
--- /dev/null
+++ b/3rd-Party-License.md
@@ -0,0 +1,10 @@
+# License overview of included 3rd party code
+
+Cake.Issues is licensed under the terms of the [MIT License](LICENSE).
+
+Cake.Issues includes third-party code which is licensed under its own respective license.
+
+## LitJSON
+
+License: Unlicense
+https://github.com/LitJSON/litjson/blob/develop/COPYING
diff --git a/README.md b/README.md
index 8417d5d26..a8574d888 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
This addin for the Cake build automation system allows you to read issues from any code analyzer or linter.
For more information about this addin see the [Cake.Issues website](https://cakeissues.net)
-and for general information about the Cake build automation system see the [Cake website](http://cakebuild.net)
+and for general information about the Cake build automation system see the [Cake website](http://cakebuild.net).
[![License](http://img.shields.io/:license-mit-blue.svg)](https://github.com/cake-contrib/Cake.Issues/blob/develop/LICENSE)
@@ -31,7 +31,7 @@ and for general information about the Cake build automation system see the [Cake
## Chat Room
-Come join in the conversation about this addin in our Gitter Chat Room
+Come join in the conversation about this addin in our Gitter Chat Room.
[![Join the chat at https://gitter.im/cake-contrib/Lobby](https://badges.gitter.im/cake-contrib/Lobby.svg)](https://gitter.im/cake-contrib/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 8f395df29..d7198be65 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -6,6 +6,8 @@ trigger:
pr:
- develop
+- release/*
+- hotfix/*
jobs:
- job: Windows
diff --git a/build.ps1 b/build.ps1
index bdfb32b4f..a6d30c4e8 100644
--- a/build.ps1
+++ b/build.ps1
@@ -35,7 +35,7 @@ http://cakebuild.net
[CmdletBinding()]
Param(
- [string]$Script = "setup.cake",
+ [string]$Script = "recipe.cake",
[string]$Target = "Default",
[ValidateSet("Release", "Debug")]
[string]$Configuration = "Release",
@@ -181,4 +181,4 @@ if (!(Test-Path $CAKE_EXE)) {
# Start Cake
Write-Host "Running build script..."
Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -target=`"$Target`" -configuration=`"$Configuration`" -verbosity=`"$Verbosity`" $UseMono $UseDryRun $UseExperimental $ScriptArgs"
-exit $LASTEXITCODE
\ No newline at end of file
+exit $LASTEXITCODE
diff --git a/build.sh b/build.sh
old mode 100644
new mode 100755
index a541ec165..d35bcf4ef
--- a/build.sh
+++ b/build.sh
@@ -11,7 +11,7 @@ NUGET_EXE=$TOOLS_DIR/nuget.exe
CAKE_EXE=$TOOLS_DIR/Cake/Cake.exe
# Define default arguments.
-SCRIPT="setup.cake"
+SCRIPT="recipe.cake"
TARGET="Default"
CONFIGURATION="Release"
VERBOSITY="verbose"
diff --git a/nuspec/nuget/Cake.Issues.Testing.nuspec b/nuspec/nuget/Cake.Issues.Testing.nuspec
index 2b702c31f..c536efe0e 100644
--- a/nuspec/nuget/Cake.Issues.Testing.nuspec
+++ b/nuspec/nuget/Cake.Issues.Testing.nuspec
@@ -12,14 +12,15 @@ Common helpers for testing add-ins based on Cake.Issues
MIT
https://cakeissues.net
- https://cdn.jsdelivr.net/gh/cake-contrib/graphics@a5cf0f881c390650144b2243ae551d5b9f836196/png/cake-contrib-medium.png
+ icon.png
false
Copyright © BBT Software AG and contributors
Cake Script Cake-Issues Issues Testing
- https://github.com/cake-contrib/Cake.Issues/releases/tag/0.7.1
+ https://github.com/cake-contrib/Cake.Issues/releases/tag/0.8.0
+
diff --git a/nuspec/nuget/Cake.Issues.nuspec b/nuspec/nuget/Cake.Issues.nuspec
index 1a698374e..a8e8c08e6 100644
--- a/nuspec/nuget/Cake.Issues.nuspec
+++ b/nuspec/nuget/Cake.Issues.nuspec
@@ -19,14 +19,15 @@ See the Project Site for an overview of the whole ecosystem of addins for workin
MIT
https://cakeissues.net
- https://cdn.jsdelivr.net/gh/cake-contrib/graphics@a5cf0f881c390650144b2243ae551d5b9f836196/png/cake-contrib-medium.png
+ icon.png
false
Copyright © BBT Software AG and contributors
Cake Script Cake-Issues CodeAnalysis Linting Issues
- https://github.com/cake-contrib/Cake.Issues/releases/tag/0.7.1
+ https://github.com/cake-contrib/Cake.Issues/releases/tag/0.8.0
+
diff --git a/nuspec/nuget/icon.png b/nuspec/nuget/icon.png
new file mode 100644
index 000000000..9881edc4e
Binary files /dev/null and b/nuspec/nuget/icon.png differ
diff --git a/setup.cake b/recipe.cake
similarity index 58%
rename from setup.cake
rename to recipe.cake
index c22d5dd85..5836671e3 100644
--- a/setup.cake
+++ b/recipe.cake
@@ -3,21 +3,27 @@
Environment.SetVariableNames();
BuildParameters.SetParameters(
- context: Context,
+ context: Context,
buildSystem: BuildSystem,
sourceDirectoryPath: "./src",
title: "Cake.Issues",
repositoryOwner: "cake-contrib",
repositoryName: "Cake.Issues",
appVeyorAccountName: "cakecontrib",
- shouldRunCodecov: false);
+ shouldRunCodecov: false,
+ shouldRunGitVersion: true);
BuildParameters.PrintParameters(Context);
ToolSettings.SetToolSettings(
context: Context,
- dupFinderExcludePattern: new string[] { BuildParameters.RootDirectoryPath + "/src/Cake.Issues.Tests/*.cs", BuildParameters.RootDirectoryPath + "/src/Cake.Issues*/**/*.AssemblyInfo.cs" },
- testCoverageFilter: "+[*]* -[xunit.*]* -[Cake.Core]* -[Cake.Testing]* -[*.Tests]* -[Shouldly]*",
+ dupFinderExcludePattern: new string[]
+ {
+ BuildParameters.RootDirectoryPath + "/src/Cake.Issues*/**/*.AssemblyInfo.cs",
+ BuildParameters.RootDirectoryPath + "/src/Cake.Issues*/Serialization/LitJson/*.cs",
+ BuildParameters.RootDirectoryPath + "/src/Cake.Issues.Tests/**/*.cs"
+ },
+ testCoverageFilter: "+[*]* -[xunit.*]* -[Cake.Core]* -[Cake.Testing]* -[*.Tests]* -[Cake.Issues]LitJson.* -[Shouldly]*",
testCoverageExcludeByAttribute: "*.ExcludeFromCodeCoverage*",
testCoverageExcludeByFile: "*/*Designer.cs;*/*.g.cs;*/*.g.i.cs");
diff --git a/src/Cake.Issues.Testing/BaseIssueProviderFixture.cs b/src/Cake.Issues.Testing/BaseIssueProviderFixture.cs
index 8016a45d2..c71f7f198 100644
--- a/src/Cake.Issues.Testing/BaseIssueProviderFixture.cs
+++ b/src/Cake.Issues.Testing/BaseIssueProviderFixture.cs
@@ -33,13 +33,13 @@ protected BaseIssueProviderFixture()
public RepositorySettings RepositorySettings { get; set; }
///
- /// Calls .
+ /// Calls .
///
/// Issues returned from issue provider.
public IEnumerable ReadIssues()
{
var issueProvider = this.CreateIssueProvider();
- return issueProvider.ReadIssues(IssueCommentFormat.PlainText);
+ return issueProvider.ReadIssues();
}
///
diff --git a/src/Cake.Issues.Testing/Cake.Issues.Testing.csproj b/src/Cake.Issues.Testing/Cake.Issues.Testing.csproj
index d628f20db..e91a7e15a 100644
--- a/src/Cake.Issues.Testing/Cake.Issues.Testing.csproj
+++ b/src/Cake.Issues.Testing/Cake.Issues.Testing.csproj
@@ -26,7 +26,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/Cake.Issues.Testing/FakeConfigurableIssueProvider.cs b/src/Cake.Issues.Testing/FakeConfigurableIssueProvider.cs
index 3bff27240..5a7c9f061 100644
--- a/src/Cake.Issues.Testing/FakeConfigurableIssueProvider.cs
+++ b/src/Cake.Issues.Testing/FakeConfigurableIssueProvider.cs
@@ -55,18 +55,12 @@ public FakeConfigurableIssueProvider(
///
public new IssueProviderSettings IssueProviderSettings => base.IssueProviderSettings;
- ///
- /// Gets the format in which issues should be returned.
- ///
- public IssueCommentFormat Format { get; private set; }
-
///
public override string ProviderName => "Fake Issue Provider";
///
- protected override IEnumerable InternalReadIssues(IssueCommentFormat format)
+ protected override IEnumerable InternalReadIssues()
{
- this.Format = format;
return this.issues;
}
}
diff --git a/src/Cake.Issues.Testing/FakeIssueProvider.cs b/src/Cake.Issues.Testing/FakeIssueProvider.cs
index 7d84a558f..8dcef5169 100644
--- a/src/Cake.Issues.Testing/FakeIssueProvider.cs
+++ b/src/Cake.Issues.Testing/FakeIssueProvider.cs
@@ -44,18 +44,12 @@ public FakeIssueProvider(ICakeLog log, IEnumerable issues)
///
public new RepositorySettings Settings => base.Settings;
- ///
- /// Gets the format in which issues should be returned.
- ///
- public IssueCommentFormat Format { get; private set; }
-
///
public override string ProviderName => "Fake Issue Provider";
///
- protected override IEnumerable InternalReadIssues(IssueCommentFormat format)
+ protected override IEnumerable InternalReadIssues()
{
- this.Format = format;
return this.issues;
}
}
diff --git a/src/Cake.Issues.Testing/FakeLogFileFormat.cs b/src/Cake.Issues.Testing/FakeLogFileFormat.cs
index 4245b5c1e..8e39bfd73 100644
--- a/src/Cake.Issues.Testing/FakeLogFileFormat.cs
+++ b/src/Cake.Issues.Testing/FakeLogFileFormat.cs
@@ -42,7 +42,6 @@ public FakeLogFileFormat(ICakeLog log, IEnumerable issues)
///
public override IEnumerable ReadIssues(
FakeMultiFormatIssueProvider issueProvider,
- IssueCommentFormat format,
RepositorySettings repositorySettings,
FakeMultiFormatIssueProviderSettings issueProviderSettings)
{
diff --git a/src/Cake.Issues.Testing/IssueChecker.cs b/src/Cake.Issues.Testing/IssueChecker.cs
index a784d8970..d68a51799 100644
--- a/src/Cake.Issues.Testing/IssueChecker.cs
+++ b/src/Cake.Issues.Testing/IssueChecker.cs
@@ -45,7 +45,9 @@ public static void Check(
expectedIssue.ProjectName,
expectedIssue.AffectedFileRelativePath?.ToString(),
expectedIssue.Line,
- expectedIssue.Message,
+ expectedIssue.MessageText,
+ expectedIssue.MessageHtml,
+ expectedIssue.MessageMarkdown,
expectedIssue.Priority,
expectedIssue.PriorityName,
expectedIssue.Rule,
@@ -66,7 +68,9 @@ public static void Check(
/// null if the issue is not expected to be related to a change in a file.
/// Expected line number.
/// null if the issue is not expected to be related to a file or specific line.
- /// Expected message.
+ /// Expected message in plain text format.
+ /// Expected message in HTML format.
+ /// Expected message in Markdown format.
/// Expected priority.
/// null if no priority is expected.
/// Expected priority name.
@@ -83,7 +87,9 @@ public static void Check(
string projectName,
string affectedFileRelativePath,
int? line,
- string message,
+ string messageText,
+ string messageHtml,
+ string messageMarkdown,
int? priority,
string priorityName,
string rule,
@@ -161,10 +167,22 @@ public static void Check(
$"Expected issue.Line to be '{line}' but was '{issue.Line}'.");
}
- if (issue.Message != message)
+ if (issue.MessageText != messageText)
{
throw new Exception(
- $"Expected issue.Message to be '{message}' but was '{issue.Message}'.");
+ $"Expected issue.MessageText to be '{messageText}' but was '{issue.MessageText}'.");
+ }
+
+ if (issue.MessageHtml != messageHtml)
+ {
+ throw new Exception(
+ $"Expected issue.MessageHtml to be '{messageHtml}' but was '{issue.MessageHtml}'.");
+ }
+
+ if (issue.MessageMarkdown != messageMarkdown)
+ {
+ throw new Exception(
+ $"Expected issue.MessageMarkdown to be '{messageMarkdown}' but was '{issue.MessageMarkdown}'.");
}
if (issue.Priority != priority)
diff --git a/src/Cake.Issues.Tests/BaseIssueProviderTests.cs b/src/Cake.Issues.Tests/BaseIssueProviderTests.cs
index 05e9d0735..f943a5aa0 100644
--- a/src/Cake.Issues.Tests/BaseIssueProviderTests.cs
+++ b/src/Cake.Issues.Tests/BaseIssueProviderTests.cs
@@ -42,7 +42,7 @@ public void Should_Throw_If_Settings_Is_Null()
var provider = new FakeIssueProvider(new FakeLog());
// When
- var result = Record.Exception(() => provider.ReadIssues(IssueCommentFormat.PlainText));
+ var result = Record.Exception(() => provider.ReadIssues());
// Then
result.IsInvalidOperationException("Initialize needs to be called first.");
diff --git a/src/Cake.Issues.Tests/BaseMultiFormatIssueProviderTests.cs b/src/Cake.Issues.Tests/BaseMultiFormatIssueProviderTests.cs
index 114c6fec0..f446e83d8 100644
--- a/src/Cake.Issues.Tests/BaseMultiFormatIssueProviderTests.cs
+++ b/src/Cake.Issues.Tests/BaseMultiFormatIssueProviderTests.cs
@@ -113,7 +113,7 @@ public void Should_Read_Issues_From_Format()
provider.Initialize(new RepositorySettings(@"c:\repo"));
// When
- var result = provider.ReadIssues(IssueCommentFormat.PlainText);
+ var result = provider.ReadIssues();
// Then
result.Count().ShouldBe(2);
diff --git a/src/Cake.Issues.Tests/Cake.Issues.Tests.csproj b/src/Cake.Issues.Tests/Cake.Issues.Tests.csproj
index e373cbaa5..63f8064b5 100644
--- a/src/Cake.Issues.Tests/Cake.Issues.Tests.csproj
+++ b/src/Cake.Issues.Tests/Cake.Issues.Tests.csproj
@@ -1,7 +1,7 @@
- netcoreapp2.0
+ netcoreapp2.1
false
Cake.Issues
Copyright © BBT Software AG and contributors
@@ -25,7 +25,7 @@
-
+
@@ -43,6 +43,12 @@
+
+ Always
+
+
+ Always
+
Always
diff --git a/src/Cake.Issues.Tests/IIssueComparerTests.cs b/src/Cake.Issues.Tests/IIssueComparerTests.cs
new file mode 100644
index 000000000..169003a5a
--- /dev/null
+++ b/src/Cake.Issues.Tests/IIssueComparerTests.cs
@@ -0,0 +1,1425 @@
+namespace Cake.Issues.Tests
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using Shouldly;
+ using Xunit;
+
+ public sealed class IIssueComparerTests
+ {
+ public sealed class TheCtorWithCompareOnlyPersistentPropertiesSetToFalse
+ {
+ [Fact]
+ public void Should_Return_False_If_First_Issue_Is_Null()
+ {
+ // Given
+ IIssue issue1 = null;
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Fact]
+ public void Should_Return_False_If_Second_Issue_Is_Null()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .Create();
+ IIssue issue2 = null;
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Theory]
+ [InlineData("foo", "bar")]
+ [InlineData("foo", "Foo")]
+ [InlineData("foo", null)]
+ [InlineData(null, "foo")]
+ public void Should_Return_False_If_ProjectFileRelativePath_Is_Different(string path1, string path2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InProjectFile(path1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InProjectFile(path2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Theory]
+ [InlineData("foo", "bar")]
+ [InlineData("foo", "Foo")]
+ [InlineData("foo", null)]
+ [InlineData(null, "foo")]
+ public void Should_Return_False_If_ProjectName_Is_Different(string projectName1, string projectName2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InProjectOfName(projectName1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InProjectOfName(projectName2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Theory]
+ [InlineData("foo", "bar")]
+ [InlineData("foo", "Foo")]
+ [InlineData("foo", null)]
+ [InlineData(null, "foo")]
+ public void Should_Return_False_If_AffectedFileRelativePath_Is_Different(string path1, string path2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile(path1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile(path2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Theory]
+ [InlineData(1, 2)]
+ [InlineData(1, null)]
+ [InlineData(null, 1)]
+ [InlineData(int.MaxValue, 1)]
+ [InlineData(1, int.MaxValue)]
+ public void Should_Return_False_If_Line_Is_Different(int? line1, int? line2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile("foo", line1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile("foo", line2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Fact]
+ public void Should_Return_False_If_MessageText_Is_Different()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message1", "providerType", "providerName")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message2", "providerType", "providerName")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Theory]
+ [InlineData("foo", "bar")]
+ [InlineData("foo", "Foo")]
+ [InlineData("foo", null)]
+ [InlineData(null, "foo")]
+ public void Should_Return_False_If_MessageHtml_Is_Different(string message1, string message2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithMessageInHtmlFormat(message1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithMessageInHtmlFormat(message2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Theory]
+ [InlineData("foo", "bar")]
+ [InlineData("foo", "Foo")]
+ [InlineData("foo", null)]
+ [InlineData(null, "foo")]
+ public void Should_Return_False_If_MessageMarkdown_Is_Different(string message1, string message2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithMessageInMarkdownFormat(message1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithMessageInMarkdownFormat(message2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Theory]
+ [InlineData(1, 2)]
+ [InlineData(1, null)]
+ [InlineData(null, 1)]
+ [InlineData(int.MinValue, 0)]
+ [InlineData(int.MaxValue, 0)]
+ public void Should_Return_False_If_Priority_Is_Different(int? priority1, int? priority2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithPriority(priority1, "Foo")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithPriority(priority2, "Foo")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Theory]
+ [InlineData("foo", "bar")]
+ [InlineData("foo", "Foo")]
+ [InlineData("foo", null)]
+ [InlineData(null, "foo")]
+ public void Should_Return_False_If_PriorityName_Is_Different(string priorityName1, string priorityName2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithPriority(42, priorityName1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithPriority(42, priorityName2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Theory]
+ [InlineData("foo", "bar")]
+ [InlineData("foo", "Foo")]
+ [InlineData("foo", null)]
+ [InlineData(null, "foo")]
+ public void Should_Return_False_If_Rule_Is_Different(string rule1, string rule2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .OfRule(rule1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .OfRule(rule2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Theory]
+ [InlineData("http://foo", "http://bar")]
+ [InlineData("http://foo", null)]
+ [InlineData(null, "http://foo")]
+ public void Should_Return_False_If_RuleUlr_Is_Different(string ruleUrl1, string ruleUrl2)
+ {
+ // Given
+ var issueBuilder =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName");
+ if (!string.IsNullOrEmpty(ruleUrl1))
+ {
+ issueBuilder =
+ issueBuilder
+ .OfRule("foo", new Uri(ruleUrl1));
+ }
+
+ var issue1 = issueBuilder.Create();
+
+ issueBuilder =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName");
+ if (!string.IsNullOrEmpty(ruleUrl2))
+ {
+ issueBuilder =
+ issueBuilder
+ .OfRule("foo", new Uri(ruleUrl2));
+ }
+
+ var issue2 = issueBuilder.Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Fact]
+ public void Should_Return_False_If_ProviderType_Is_Different()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType1", "providerName")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType2", "providerName")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Fact]
+ public void Should_Return_False_If_ProviderName_Is_Different()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName1")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName2")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Fact]
+ public void Should_Return_True_If_Same_Reference()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .Create();
+ var issue2 = issue1;
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Fact]
+ public void Should_Return_True_If_Both_Are_Null()
+ {
+ // Given
+ IIssue issue1 = null;
+ IIssue issue2 = null;
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Fact]
+ public void Should_Return_True_If_Properties_Are_The_Same()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData("foo", "foo")]
+ [InlineData("foo", "foo/")]
+ [InlineData("foo/", "foo")]
+ [InlineData("", "")]
+ [InlineData(null, null)]
+ public void Should_Return_True_If_ProjectFileRelativePath_Is_Same(string path1, string path2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InProjectFile(path1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InProjectFile(path2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData("foo", "foo")]
+ [InlineData("", "")]
+ [InlineData(null, null)]
+ public void Should_Return_True_If_ProjectName_Is_Same(string projectName1, string projectName2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InProjectOfName(projectName1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InProjectOfName(projectName2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData("foo", "foo")]
+ [InlineData("foo", "foo/")]
+ [InlineData("foo/", "foo")]
+ [InlineData("", "")]
+ [InlineData(null, null)]
+ public void Should_Return_True_If_AffectedFileRelativePath_Is_Same(string path1, string path2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile(path1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile(path2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData(1, 1)]
+ [InlineData(null, null)]
+ [InlineData(int.MaxValue, int.MaxValue)]
+ public void Should_Return_True_If_Line_Is_Same(int? line1, int? line2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile("foo", line1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile("foo", line2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Fact]
+ public void Should_Return_True_If_MessageText_Is_Same()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("messageText", "providerType", "providerName")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("messageText", "providerType", "providerName")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData("foo", "foo")]
+ [InlineData("", "")]
+ [InlineData(null, null)]
+ public void Should_Return_True_If_MessageHtml_Is_Same(string message1, string message2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithMessageInHtmlFormat(message1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithMessageInHtmlFormat(message2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData("foo", "foo")]
+ [InlineData("", "")]
+ [InlineData(null, null)]
+ public void Should_Return_True_If_MessageMarkdown_Is_Same(string message1, string message2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithMessageInMarkdownFormat(message1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithMessageInMarkdownFormat(message2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData(1, 1)]
+ [InlineData(null, null)]
+ [InlineData(0, 0)]
+ [InlineData(int.MinValue, int.MinValue)]
+ [InlineData(int.MaxValue, int.MaxValue)]
+ public void Should_Return_True_If_Priority_Is_Same(int? priority1, int? priority2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithPriority(priority1, "Foo")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithPriority(priority2, "Foo")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData("foo", "foo")]
+ [InlineData("", "")]
+ [InlineData(null, null)]
+ public void Should_Return_True_If_PriorityName_Is_Same(string priorityName1, string priorityName2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithPriority(42, priorityName1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithPriority(42, priorityName2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData("foo", "foo")]
+ [InlineData("", "")]
+ [InlineData(null, null)]
+ public void Should_Return_True_If_Rule_Is_Same(string rule1, string rule2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .OfRule(rule1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .OfRule(rule2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData("http://foo", "http://foo")]
+ [InlineData("http://foo", "http://Foo")]
+ [InlineData(null, null)]
+ public void Should_Return_True_If_RuleUlr_Is_Same(string ruleUrl1, string ruleUrl2)
+ {
+ // Given
+ var issueBuilder =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName");
+ if (!string.IsNullOrEmpty(ruleUrl1))
+ {
+ issueBuilder =
+ issueBuilder
+ .OfRule("foo", new Uri(ruleUrl1));
+ }
+
+ var issue1 = issueBuilder.Create();
+
+ issueBuilder =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName");
+ if (!string.IsNullOrEmpty(ruleUrl2))
+ {
+ issueBuilder =
+ issueBuilder
+ .OfRule("foo", new Uri(ruleUrl2));
+ }
+
+ var issue2 = issueBuilder.Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Fact]
+ public void Should_Return_True_If_ProviderType_Is_Same()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Fact]
+ public void Should_Return_True_If_ProviderName_Is_Same()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Fact]
+ public void Should_Remove_Identical_Issues_From_List_Of_Issues()
+ {
+ // Given
+ var issue1_1 =
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .Create();
+ var issue1_2 =
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .Create();
+ var issue3 =
+ IssueBuilder
+ .NewIssue("message3", "providerType3", "providerName3")
+ .Create();
+ var issues1 = new List { issue1_1, issue2 };
+ var issues2 = new List { issue1_2, issue3 };
+ var comparer = new IIssueComparer();
+
+ // When
+ var result = issues1.Except(issues2, comparer);
+
+ // Then
+ result.Count().ShouldBe(1);
+ result.ShouldContain(issue2);
+ }
+
+ private static void CompareIssues(IIssue issue1, IIssue issue2, bool expectedToBeEqual)
+ {
+ var comparer = new IIssueComparer(false);
+
+ comparer.Equals(issue1, issue2).ShouldBe(expectedToBeEqual);
+
+ if (expectedToBeEqual)
+ {
+ comparer.GetHashCode(issue1).ShouldBe(comparer.GetHashCode(issue2));
+ }
+ else
+ {
+ comparer.GetHashCode(issue1).ShouldNotBe(comparer.GetHashCode(issue2));
+ }
+ }
+ }
+
+ public sealed class TheCtorWithCompareOnlyPersistentPropertiesSetToTrue
+ {
+ [Fact]
+ public void Should_Return_False_If_First_Issue_Is_Null()
+ {
+ // Given
+ IIssue issue1 = null;
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Fact]
+ public void Should_Return_False_If_Second_Issue_Is_Null()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .Create();
+ IIssue issue2 = null;
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Theory]
+ [InlineData("foo", "bar")]
+ [InlineData("foo", "Foo")]
+ [InlineData("foo", null)]
+ [InlineData(null, "foo")]
+ public void Should_Return_False_If_ProjectName_Is_Different(string projectName1, string projectName2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InProjectOfName(projectName1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InProjectOfName(projectName2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Fact]
+ public void Should_Return_False_If_MessageText_Is_Different()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message1", "providerType", "providerName")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message2", "providerType", "providerName")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Theory]
+ [InlineData("foo", "bar")]
+ [InlineData("foo", "Foo")]
+ [InlineData("foo", null)]
+ [InlineData(null, "foo")]
+ public void Should_Return_False_If_MessageHtml_Is_Different(string message1, string message2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithMessageInHtmlFormat(message1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithMessageInHtmlFormat(message2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Theory]
+ [InlineData("foo", "bar")]
+ [InlineData("foo", "Foo")]
+ [InlineData("foo", null)]
+ [InlineData(null, "foo")]
+ public void Should_Return_False_If_MessageMarkdown_Is_Different(string message1, string message2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithMessageInMarkdownFormat(message1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithMessageInMarkdownFormat(message2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Theory]
+ [InlineData(1, 2)]
+ [InlineData(1, null)]
+ [InlineData(null, 1)]
+ [InlineData(int.MinValue, 0)]
+ [InlineData(int.MaxValue, 0)]
+ public void Should_Return_False_If_Priority_Is_Different(int? priority1, int? priority2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithPriority(priority1, "Foo")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithPriority(priority2, "Foo")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Theory]
+ [InlineData("foo", "bar")]
+ [InlineData("foo", "Foo")]
+ [InlineData("foo", null)]
+ [InlineData(null, "foo")]
+ public void Should_Return_False_If_PriorityName_Is_Different(string priorityName1, string priorityName2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithPriority(42, priorityName1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithPriority(42, priorityName2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Theory]
+ [InlineData("foo", "bar")]
+ [InlineData("foo", "Foo")]
+ [InlineData("foo", null)]
+ [InlineData(null, "foo")]
+ public void Should_Return_False_If_Rule_Is_Different(string rule1, string rule2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .OfRule(rule1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .OfRule(rule2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Theory]
+ [InlineData("http://foo", "http://bar")]
+ [InlineData("http://foo", null)]
+ [InlineData(null, "http://foo")]
+ public void Should_Return_False_If_RuleUlr_Is_Different(string ruleUrl1, string ruleUrl2)
+ {
+ // Given
+ var issueBuilder =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName");
+ if (!string.IsNullOrEmpty(ruleUrl1))
+ {
+ issueBuilder =
+ issueBuilder
+ .OfRule("foo", new Uri(ruleUrl1));
+ }
+
+ var issue1 = issueBuilder.Create();
+
+ issueBuilder =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName");
+ if (!string.IsNullOrEmpty(ruleUrl2))
+ {
+ issueBuilder =
+ issueBuilder
+ .OfRule("foo", new Uri(ruleUrl2));
+ }
+
+ var issue2 = issueBuilder.Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Fact]
+ public void Should_Return_False_If_ProviderType_Is_Different()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType1", "providerName")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType2", "providerName")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Fact]
+ public void Should_Return_False_If_ProviderName_Is_Different()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName1")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName2")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Fact]
+ public void Should_Return_True_If_Same_Reference()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .Create();
+ var issue2 = issue1;
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Fact]
+ public void Should_Return_True_If_Both_Are_Null()
+ {
+ // Given
+ IIssue issue1 = null;
+ IIssue issue2 = null;
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Fact]
+ public void Should_Return_True_If_Properties_Are_The_Same()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData("foo", "bar")]
+ [InlineData("foo", "Foo")]
+ [InlineData("foo", null)]
+ [InlineData(null, "foo")]
+ public void Should_Return_True_If_ProjectFileRelativePath_Is_Different(string path1, string path2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InProjectFile(path1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InProjectFile(path2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData("foo", "foo")]
+ [InlineData("foo", "foo/")]
+ [InlineData("foo/", "foo")]
+ [InlineData("", "")]
+ [InlineData(null, null)]
+ public void Should_Return_True_If_ProjectFileRelativePath_Is_Same(string path1, string path2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InProjectFile(path1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InProjectFile(path2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData("foo", "foo")]
+ [InlineData("", "")]
+ [InlineData(null, null)]
+ public void Should_Return_True_If_ProjectName_Is_Same(string projectName1, string projectName2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InProjectOfName(projectName1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InProjectOfName(projectName2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData("foo", "bar")]
+ [InlineData("foo", "Foo")]
+ [InlineData("foo", null)]
+ [InlineData(null, "foo")]
+ public void Should_Return_True_If_AffectedFileRelativePath_Is_Different(string path1, string path2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile(path1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile(path2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData("foo", "foo")]
+ [InlineData("foo", "foo/")]
+ [InlineData("foo/", "foo")]
+ [InlineData("", "")]
+ [InlineData(null, null)]
+ public void Should_Return_True_If_AffectedFileRelativePath_Is_Same(string path1, string path2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile(path1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile(path2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData(1, 2)]
+ [InlineData(1, null)]
+ [InlineData(null, 1)]
+ [InlineData(int.MaxValue, 1)]
+ [InlineData(1, int.MaxValue)]
+ public void Should_Return_True_If_Line_Is_Different(int? line1, int? line2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile("foo", line1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile("foo", line2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData(1, 1)]
+ [InlineData(null, null)]
+ [InlineData(int.MaxValue, int.MaxValue)]
+ public void Should_Return_True_If_Line_Is_Same(int? line1, int? line2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile("foo", line1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile("foo", line2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Fact]
+ public void Should_Return_True_If_MessageText_Is_Same()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("messageText", "providerType", "providerName")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("messageText", "providerType", "providerName")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData("foo", "foo")]
+ [InlineData("", "")]
+ [InlineData(null, null)]
+ public void Should_Return_True_If_MessageHtml_Is_Same(string message1, string message2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithMessageInHtmlFormat(message1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithMessageInHtmlFormat(message2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData("foo", "foo")]
+ [InlineData("", "")]
+ [InlineData(null, null)]
+ public void Should_Return_True_If_MessageMarkdown_Is_Same(string message1, string message2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithMessageInMarkdownFormat(message1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithMessageInMarkdownFormat(message2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData(1, 1)]
+ [InlineData(null, null)]
+ [InlineData(0, 0)]
+ [InlineData(int.MinValue, int.MinValue)]
+ [InlineData(int.MaxValue, int.MaxValue)]
+ public void Should_Return_True_If_Priority_Is_Same(int? priority1, int? priority2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithPriority(priority1, "Foo")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithPriority(priority2, "Foo")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData("foo", "foo")]
+ [InlineData("", "")]
+ [InlineData(null, null)]
+ public void Should_Return_True_If_PriorityName_Is_Same(string priorityName1, string priorityName2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithPriority(42, priorityName1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithPriority(42, priorityName2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData("foo", "foo")]
+ [InlineData("", "")]
+ [InlineData(null, null)]
+ public void Should_Return_True_If_Rule_Is_Same(string rule1, string rule2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .OfRule(rule1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .OfRule(rule2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData("http://foo", "http://foo")]
+ [InlineData("http://foo", "http://Foo")]
+ [InlineData(null, null)]
+ public void Should_Return_True_If_RuleUlr_Is_Same(string ruleUrl1, string ruleUrl2)
+ {
+ // Given
+ var issueBuilder =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName");
+ if (!string.IsNullOrEmpty(ruleUrl1))
+ {
+ issueBuilder =
+ issueBuilder
+ .OfRule("foo", new Uri(ruleUrl1));
+ }
+
+ var issue1 = issueBuilder.Create();
+
+ issueBuilder =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName");
+ if (!string.IsNullOrEmpty(ruleUrl2))
+ {
+ issueBuilder =
+ issueBuilder
+ .OfRule("foo", new Uri(ruleUrl2));
+ }
+
+ var issue2 = issueBuilder.Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Fact]
+ public void Should_Return_True_If_ProviderType_Is_Same()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Fact]
+ public void Should_Return_True_If_ProviderName_Is_Same()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Fact]
+ public void Should_Remove_Identical_Issues_From_List_Of_Issues()
+ {
+ // Given
+ var issue1_1 =
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .InFile("foo.cs", 10)
+ .Create();
+ var issue1_2 =
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .InFile("foo.cs", 20)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .Create();
+ var issue3 =
+ IssueBuilder
+ .NewIssue("message3", "providerType3", "providerName3")
+ .Create();
+ var issues1 = new List { issue1_1, issue2 };
+ var issues2 = new List { issue1_2, issue3 };
+ var comparer = new IIssueComparer(true);
+
+ // When
+ var result = issues1.Except(issues2, comparer);
+
+ // Then
+ result.Count().ShouldBe(1);
+ result.ShouldContain(issue2);
+ }
+
+ private static void CompareIssues(IIssue issue1, IIssue issue2, bool expectedToBeEqual)
+ {
+ var comparer = new IIssueComparer(true);
+
+ comparer.Equals(issue1, issue2).ShouldBe(expectedToBeEqual);
+
+ if (expectedToBeEqual)
+ {
+ comparer.GetHashCode(issue1).ShouldBe(comparer.GetHashCode(issue2));
+ }
+ else
+ {
+ comparer.GetHashCode(issue1).ShouldNotBe(comparer.GetHashCode(issue2));
+ }
+ }
+ }
+ }
+}
diff --git a/src/Cake.Issues.Tests/IIssueExtensionsTests.cs b/src/Cake.Issues.Tests/IIssueExtensionsTests.cs
index 500e9bb95..c444ac375 100644
--- a/src/Cake.Issues.Tests/IIssueExtensionsTests.cs
+++ b/src/Cake.Issues.Tests/IIssueExtensionsTests.cs
@@ -308,13 +308,17 @@ public void Should_Throw_If_Issue_Is_Null()
[InlineData("foo {Line} bar", "foo 42 bar")]
[InlineData("foo {Rule} bar", "foo Rule Foo bar")]
[InlineData("foo {RuleUrl} bar", "foo https://google.com/ bar")]
- [InlineData("foo {Message} bar", "foo Message Foo bar")]
+ [InlineData("foo {MessageText} bar", "foo MessageText Foo bar")]
+ [InlineData("foo {MessageHtml} bar", "foo MessageHtml Foo bar")]
+ [InlineData("foo {MessageMarkdown} bar", "foo MessageMarkdown Foo bar")]
public void Should_Replace_Tokens(string pattern, string expectedResult)
{
// Given
var issue =
IssueBuilder
- .NewIssue("Message Foo", "ProviderType Foo", "ProviderName Foo")
+ .NewIssue("MessageText Foo", "ProviderType Foo", "ProviderName Foo")
+ .WithMessageInHtmlFormat("MessageHtml Foo")
+ .WithMessageInMarkdownFormat("MessageMarkdown Foo")
.InFile(@"src/Cake.Issues/foo.cs", 42)
.InProject(@"src/Cake.Issues/Cake.Issues.csproj", "Cake.Issues")
.OfRule("Rule Foo", new Uri("https://google.com"))
diff --git a/src/Cake.Issues.Tests/IssueBuilderFixture.cs b/src/Cake.Issues.Tests/IssueBuilderFixture.cs
index d734d2da9..7b5e1cbc0 100644
--- a/src/Cake.Issues.Tests/IssueBuilderFixture.cs
+++ b/src/Cake.Issues.Tests/IssueBuilderFixture.cs
@@ -7,10 +7,10 @@ public IssueBuilderFixture()
{
}
- public IssueBuilderFixture(string message, string providerType, string providerName)
+ public IssueBuilderFixture(string messageText, string providerType, string providerName)
{
this.IssueBuilder =
- IssueBuilder.NewIssue(message, providerType, providerName);
+ IssueBuilder.NewIssue(messageText, providerType, providerName);
}
public IssueBuilder IssueBuilder { get; private set; }
diff --git a/src/Cake.Issues.Tests/IssueReaderTests.cs b/src/Cake.Issues.Tests/IssueReaderTests.cs
index 61efe99b5..6a6696d62 100644
--- a/src/Cake.Issues.Tests/IssueReaderTests.cs
+++ b/src/Cake.Issues.Tests/IssueReaderTests.cs
@@ -20,7 +20,7 @@ public void Should_Throw_If_Log_Is_Null()
};
// When
- var result = Record.Exception(() => fixture.ReadIssues(IssueCommentFormat.Undefined));
+ var result = Record.Exception(() => fixture.ReadIssues());
// Then
result.IsArgumentNullException("log");
@@ -36,7 +36,7 @@ public void Should_Throw_If_Issue_Provider_List_Is_Null()
};
// When
- var result = Record.Exception(() => fixture.ReadIssues(IssueCommentFormat.Undefined));
+ var result = Record.Exception(() => fixture.ReadIssues());
// Then
result.IsArgumentNullException("issueProviders");
@@ -50,7 +50,7 @@ public void Should_Throw_If_Issue_Provider_List_Is_Empty()
fixture.IssueProviders.Clear();
// When
- var result = Record.Exception(() => fixture.ReadIssues(IssueCommentFormat.Undefined));
+ var result = Record.Exception(() => fixture.ReadIssues());
// Then
result.IsArgumentException("issueProviders");
@@ -65,7 +65,7 @@ public void Should_Throw_If_Issue_Provider_Is_Null()
fixture.IssueProviders.Add(null);
// When
- var result = Record.Exception(() => fixture.ReadIssues(IssueCommentFormat.Undefined));
+ var result = Record.Exception(() => fixture.ReadIssues());
// Then
result.IsArgumentOutOfRangeException("issueProviders");
@@ -81,7 +81,7 @@ public void Should_Throw_If_Settings_Are_Null()
};
// When
- var result = Record.Exception(() => fixture.ReadIssues(IssueCommentFormat.Undefined));
+ var result = Record.Exception(() => fixture.ReadIssues());
// Then
result.IsArgumentNullException("settings");
@@ -97,7 +97,7 @@ public void Should_Initialize_Issue_Provider()
var fixture = new IssuesFixture();
// When
- fixture.ReadIssues(IssueCommentFormat.Undefined);
+ fixture.ReadIssues();
// Then
fixture.IssueProviders.ShouldAllBe(x => x.Settings == fixture.Settings);
@@ -147,7 +147,7 @@ public void Should_Initialize_All_Issue_Provider()
}));
// When
- fixture.ReadIssues(IssueCommentFormat.Undefined);
+ fixture.ReadIssues();
// Then
fixture.IssueProviders.ShouldAllBe(x => x.Settings == fixture.Settings);
@@ -183,7 +183,7 @@ public void Should_Read_Correct_Number_Of_Issues()
}));
// When
- var issues = fixture.ReadIssues(IssueCommentFormat.Undefined).ToList();
+ var issues = fixture.ReadIssues().ToList();
// Then
issues.Count.ShouldBe(2);
@@ -219,7 +219,7 @@ public void Should_Read_Correct_Number_Of_Issues_Not_Related_To_A_File()
}));
// When
- var issues = fixture.ReadIssues(IssueCommentFormat.Undefined).ToList();
+ var issues = fixture.ReadIssues().ToList();
// Then
issues.Count.ShouldBe(2);
@@ -279,7 +279,7 @@ public void Should_Read_Correct_Number_Of_Issues_From_Multiple_Providers()
}));
// When
- var issues = fixture.ReadIssues(IssueCommentFormat.Undefined).ToList();
+ var issues = fixture.ReadIssues().ToList();
// Then
issues.Count.ShouldBe(4);
diff --git a/src/Cake.Issues.Tests/IssueSerializationExtensionsTests.cs b/src/Cake.Issues.Tests/IssueSerializationExtensionsTests.cs
deleted file mode 100644
index dd18d166d..000000000
--- a/src/Cake.Issues.Tests/IssueSerializationExtensionsTests.cs
+++ /dev/null
@@ -1,827 +0,0 @@
-namespace Cake.Issues.Tests
-{
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using Cake.Core.IO;
- using Cake.Issues.Testing;
- using Shouldly;
- using Xunit;
-
- public sealed class IssueSerializationExtensionsTests
- {
- public sealed class TheSerializeToJsonStringExtensionForASingleIssue
- {
- [Fact]
- public void Should_Throw_If_Issue_Is_Null()
- {
- // Given
- IIssue issue = null;
-
- // When
- var result = Record.Exception(() => issue.SerializeToJsonString());
-
- // Then
- result.IsArgumentNullException("issue");
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_Message_After_Roundtrip()
- {
- // Given
- var message = "message";
- var issue =
- IssueBuilder
- .NewIssue(message, "providerType", "providerName")
- .Create();
-
- // When
- var result = issue.SerializeToJsonString().DeserializeToIssue();
-
- // Then
- result.Message.ShouldBe(message);
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_ProviderType_After_Roundtrip()
- {
- // Given
- var providerType = "providerType";
- var issue =
- IssueBuilder
- .NewIssue("message", providerType, "providerName")
- .Create();
-
- // When
- var result = issue.SerializeToJsonString().DeserializeToIssue();
-
- // Then
- result.ProviderType.ShouldBe(providerType);
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_ProviderName_After_Roundtrip()
- {
- // Given
- var providerName = "providerName";
- var issue =
- IssueBuilder
- .NewIssue("message", "providerType", providerName)
- .Create();
-
- // When
- var result = issue.SerializeToJsonString().DeserializeToIssue();
-
- // Then
- result.ProviderName.ShouldBe(providerName);
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_ProjectFileRelativePath_After_Roundtrip()
- {
- // Given
- var projectFileRelativePath = @"src/myproj.file";
- var issue =
- IssueBuilder
- .NewIssue("message", "providerType", "providerName")
- .InProjectFile(projectFileRelativePath)
- .Create();
-
- // When
- var result = issue.SerializeToJsonString().DeserializeToIssue();
-
- // Then
- result.ProjectFileRelativePath.FullPath.ShouldBe(projectFileRelativePath);
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_ProjectName_After_Roundtrip()
- {
- // Given
- var projectName = "projectName";
- var issue =
- IssueBuilder
- .NewIssue("message", "providerType", "providerName")
- .InProjectOfName(projectName)
- .Create();
-
- // When
- var result = issue.SerializeToJsonString().DeserializeToIssue();
-
- // Then
- result.ProjectName.ShouldBe(projectName);
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_AffectedFileRelativePath_After_Roundtrip()
- {
- // Given
- var affectedFileRelativePath = @"src/foo.bar";
- var issue =
- IssueBuilder
- .NewIssue("message", "providerType", "providerName")
- .InFile(affectedFileRelativePath)
- .Create();
-
- // When
- var result = issue.SerializeToJsonString().DeserializeToIssue();
-
- // Then
- result.AffectedFileRelativePath.FullPath.ShouldBe(affectedFileRelativePath);
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_Line_After_Roundtrip()
- {
- // Given
- var line = 42;
- var issue =
- IssueBuilder
- .NewIssue("message", "providerType", "providerName")
- .InFile(@"src/foo.bar", line)
- .Create();
-
- // When
- var result = issue.SerializeToJsonString().DeserializeToIssue();
-
- // Then
- result.Line.ShouldBe(line);
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_Priority_After_Roundtrip()
- {
- // Given
- var priority = 42;
- var issue =
- IssueBuilder
- .NewIssue("message", "providerType", "providerName")
- .WithPriority(priority, "priorityName")
- .Create();
-
- // When
- var result = issue.SerializeToJsonString().DeserializeToIssue();
-
- // Then
- result.Priority.ShouldBe(priority);
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_PriorityName_After_Roundtrip()
- {
- // Given
- var priorityName = "priorityName";
- var issue =
- IssueBuilder
- .NewIssue("message", "providerType", "providerName")
- .WithPriority(42, priorityName)
- .Create();
-
- // When
- var result = issue.SerializeToJsonString().DeserializeToIssue();
-
- // Then
- result.PriorityName.ShouldBe(priorityName);
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_Rule_After_Roundtrip()
- {
- // Given
- var rule = "rule";
- var issue =
- IssueBuilder
- .NewIssue("message", "providerType", "providerName")
- .OfRule(rule)
- .Create();
-
- // When
- var result = issue.SerializeToJsonString().DeserializeToIssue();
-
- // Then
- result.Rule.ShouldBe(rule);
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_RuleUrl_After_Roundtrip()
- {
- // Given
- var ruleUrl = new Uri("https://rule.url");
- var issue =
- IssueBuilder
- .NewIssue("message", "providerType", "providerName")
- .OfRule("rule", ruleUrl)
- .Create();
-
- // When
- var result = issue.SerializeToJsonString().DeserializeToIssue();
-
- // Then
- result.RuleUrl.ToString().ShouldBe(ruleUrl.ToString());
- }
- }
-
- public sealed class TheSerializeToJsonStringExtensionForAnEnumerableOfIssues
- {
- [Fact]
- public void Should_Throw_If_Issue_Is_Null()
- {
- // Given
- IEnumerable issues = null;
-
- // When
- var result = Record.Exception(() => issues.SerializeToJsonString());
-
- // Then
- result.IsArgumentNullException("issues");
- }
-
- [Fact]
- public void Should_Serialize_Issues()
- {
- // Given
- var issues =
- new List
- {
- IssueBuilder
- .NewIssue("message1", "providerType1", "providerName1")
- .Create(),
- IssueBuilder
- .NewIssue("message2", "providerType2", "providerName2")
- .Create(),
- };
-
- // When
- var result = issues.SerializeToJsonString();
-
- // Then
- result.ShouldNotBeNull();
- }
- }
-
- public sealed class TheSerializeToJsonFileExtensionForASingleIssue
- {
- [Fact]
- public void Should_Throw_If_Issue_Is_Null()
- {
- // Given
- IIssue issue = null;
- var filePath = @"c:\issue.json";
-
- // When
- var result = Record.Exception(() => issue.SerializeToJsonFile(filePath));
-
- // Then
- result.IsArgumentNullException("issue");
- }
-
- [Fact]
- public void Should_Throw_If_FilePath_Is_Null()
- {
- // Given
- var issue =
- IssueBuilder
- .NewIssue("message", "providerType", "providerName")
- .Create();
- FilePath filePath = null;
-
- // When
- var result = Record.Exception(() => issue.SerializeToJsonFile(filePath));
-
- // Then
- result.IsArgumentNullException("filePath");
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_Message_After_Roundtrip()
- {
- // Given
- var message = "message";
- var issue =
- IssueBuilder
- .NewIssue(message, "providerType", "providerName")
- .Create();
- var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
-
- try
- {
- // When
- issue.SerializeToJsonFile(filePath);
- var result = filePath.DeserializeToIssue();
-
- // Then
- result.Message.ShouldBe(message);
- }
- finally
- {
- System.IO.File.Delete(filePath.FullPath);
- }
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_ProviderType_After_Roundtrip()
- {
- // Given
- var providerType = "providerType";
- var issue =
- IssueBuilder
- .NewIssue("message", providerType, "providerName")
- .Create();
- var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
-
- try
- {
- // When
- issue.SerializeToJsonFile(filePath);
- var result = filePath.DeserializeToIssue();
-
- // Then
- result.ProviderType.ShouldBe(providerType);
- }
- finally
- {
- System.IO.File.Delete(filePath.FullPath);
- }
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_ProviderName_After_Roundtrip()
- {
- // Given
- var providerName = "providerName";
- var issue =
- IssueBuilder
- .NewIssue("message", "providerType", providerName)
- .Create();
- var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
-
- try
- {
- // When
- issue.SerializeToJsonFile(filePath);
- var result = filePath.DeserializeToIssue();
-
- // Then
- result.ProviderName.ShouldBe(providerName);
- }
- finally
- {
- System.IO.File.Delete(filePath.FullPath);
- }
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_ProjectFileRelativePath_After_Roundtrip()
- {
- // Given
- var projectFileRelativePath = @"src/myproj.file";
- var issue =
- IssueBuilder
- .NewIssue("message", "providerType", "providerName")
- .InProjectFile(projectFileRelativePath)
- .Create();
- var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
-
- try
- {
- // When
- issue.SerializeToJsonFile(filePath);
- var result = filePath.DeserializeToIssue();
-
- // Then
- result.ProjectFileRelativePath.FullPath.ShouldBe(projectFileRelativePath);
- }
- finally
- {
- System.IO.File.Delete(filePath.FullPath);
- }
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_ProjectName_After_Roundtrip()
- {
- // Given
- var projectName = "projectName";
- var issue =
- IssueBuilder
- .NewIssue("message", "providerType", "providerName")
- .InProjectOfName(projectName)
- .Create();
- var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
-
- try
- {
- // When
- issue.SerializeToJsonFile(filePath);
- var result = filePath.DeserializeToIssue();
-
- // Then
- result.ProjectName.ShouldBe(projectName);
- }
- finally
- {
- System.IO.File.Delete(filePath.FullPath);
- }
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_AffectedFileRelativePath_After_Roundtrip()
- {
- // Given
- var affectedFileRelativePath = @"src/foo.bar";
- var issue =
- IssueBuilder
- .NewIssue("message", "providerType", "providerName")
- .InFile(affectedFileRelativePath)
- .Create();
- var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
-
- try
- {
- // When
- issue.SerializeToJsonFile(filePath);
- var result = filePath.DeserializeToIssue();
-
- // Then
- result.AffectedFileRelativePath.FullPath.ShouldBe(affectedFileRelativePath);
- }
- finally
- {
- System.IO.File.Delete(filePath.FullPath);
- }
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_Line_After_Roundtrip()
- {
- // Given
- var line = 42;
- var issue =
- IssueBuilder
- .NewIssue("message", "providerType", "providerName")
- .InFile(@"src/foo.bar", line)
- .Create();
- var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
-
- try
- {
- // When
- issue.SerializeToJsonFile(filePath);
- var result = filePath.DeserializeToIssue();
-
- // Then
- result.Line.ShouldBe(line);
- }
- finally
- {
- System.IO.File.Delete(filePath.FullPath);
- }
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_Priority_After_Roundtrip()
- {
- // Given
- var priority = 42;
- var issue =
- IssueBuilder
- .NewIssue("message", "providerType", "providerName")
- .WithPriority(priority, "priorityName")
- .Create();
- var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
-
- try
- {
- // When
- issue.SerializeToJsonFile(filePath);
- var result = filePath.DeserializeToIssue();
-
- // Then
- result.Priority.ShouldBe(priority);
- }
- finally
- {
- System.IO.File.Delete(filePath.FullPath);
- }
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_PriorityName_After_Roundtrip()
- {
- // Given
- var priorityName = "priorityName";
- var issue =
- IssueBuilder
- .NewIssue("message", "providerType", "providerName")
- .WithPriority(42, priorityName)
- .Create();
- var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
-
- try
- {
- // When
- issue.SerializeToJsonFile(filePath);
- var result = filePath.DeserializeToIssue();
-
- // Then
- result.PriorityName.ShouldBe(priorityName);
- }
- finally
- {
- System.IO.File.Delete(filePath.FullPath);
- }
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_Rule_After_Roundtrip()
- {
- // Given
- var rule = "rule";
- var issue =
- IssueBuilder
- .NewIssue("message", "providerType", "providerName")
- .OfRule(rule)
- .Create();
- var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
-
- try
- {
- // When
- issue.SerializeToJsonFile(filePath);
- var result = filePath.DeserializeToIssue();
-
- // Then
- result.Rule.ShouldBe(rule);
- }
- finally
- {
- System.IO.File.Delete(filePath.FullPath);
- }
- }
-
- [Fact]
- public void Should_Give_Correct_Result_For_RuleUrl_After_Roundtrip()
- {
- // Given
- var ruleUrl = new Uri("https://rule.url");
- var issue =
- IssueBuilder
- .NewIssue("message", "providerType", "providerName")
- .OfRule("rule", ruleUrl)
- .Create();
- var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
-
- try
- {
- // When
- issue.SerializeToJsonFile(filePath);
- var result = filePath.DeserializeToIssue();
-
- // Then
- result.RuleUrl.ToString().ShouldBe(ruleUrl.ToString());
- }
- finally
- {
- System.IO.File.Delete(filePath.FullPath);
- }
- }
- }
-
- public sealed class TheSerializeToJsonFileExtensionForAnEnumerableOfIssues
- {
- [Fact]
- public void Should_Throw_If_Issue_Is_Null()
- {
- // Given
- IEnumerable issues = null;
- var filePath = @"c:\issues.json";
-
- // When
- var result = Record.Exception(() => issues.SerializeToJsonFile(filePath));
-
- // Then
- result.IsArgumentNullException("issues");
- }
-
- [Fact]
- public void Should_Throw_If_FilePath_Is_Null()
- {
- // Given
- var issues = new List();
- FilePath filePath = null;
-
- // When
- var result = Record.Exception(() => issues.SerializeToJsonFile(filePath));
-
- // Then
- result.IsArgumentNullException("filePath");
- }
-
- [Fact]
- public void Should_Serialize_Issues()
- {
- // Given
- var issues =
- new List
- {
- IssueBuilder
- .NewIssue("message1", "providerType1", "providerName1")
- .Create(),
- IssueBuilder
- .NewIssue("message2", "providerType2", "providerName2")
- .Create(),
- };
- var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
-
- try
- {
- // When
- issues.SerializeToJsonFile(filePath);
-
- // Then
- System.IO.File.Exists(filePath.FullPath).ShouldBeTrue();
- }
- finally
- {
- System.IO.File.Delete(filePath.FullPath);
- }
- }
- }
-
- public sealed class TheDeserializeToIssueExtensionForAJsonString
- {
- [Fact]
- public void Should_Throw_If_JsonString_Is_Null()
- {
- // Given
- string jsonString = null;
-
- // When
- var result = Record.Exception(() => jsonString.DeserializeToIssue());
-
- // Then
- result.IsArgumentNullException("jsonString");
- }
- }
-
- public sealed class TheDeserializeToIssuesExtensionForAJsonString
- {
- [Fact]
- public void Should_Throw_If_JsonString_Is_Null()
- {
- // Given
- string jsonString = null;
-
- // When
- var result = Record.Exception(() => jsonString.DeserializeToIssues());
-
- // Then
- result.IsArgumentNullException("jsonString");
- }
-
- [Fact]
- public void Should_Return_An_Empty_List_For_An_Empty_Array()
- {
- // Given
- string jsonString = "[]";
-
- // When
- var result = jsonString.DeserializeToIssues();
-
- // Then
- result.ShouldBeEmpty();
- }
- }
-
- public sealed class TheDeserializeToIssueExtensionForAJsonFile
- {
- [Fact]
- public void Should_Throw_If_FilePath_Is_Null()
- {
- // Given
- FilePath filePath = null;
-
- // When
- var result = Record.Exception(() => filePath.DeserializeToIssue());
-
- // Then
- result.IsArgumentNullException("filePath");
- }
-
- [Fact]
- public void Should_Return_Issue()
- {
- // Given
- var filePath = new FilePath("Testfiles/issue.json");
-
- // When
- var result = filePath.DeserializeToIssue();
-
- // Then
- IssueChecker.Check(
- result,
- IssueBuilder.NewIssue(
- "Something went wrong.",
- "TestProvider",
- "Test Provider")
- .InProject(@"src\Foo\Bar.csproj", "Bar")
- .InFile(@"src\Foo\Bar.cs", 42)
- .OfRule("Rule", new Uri("https://google.com"))
- .WithPriority(IssuePriority.Warning));
- }
- }
-
- public sealed class TheDeserializeToIssuesExtensionForAJsonFile
- {
- [Fact]
- public void Should_Throw_If_FilePath_Is_Null()
- {
- // Given
- FilePath filePath = null;
-
- // When
- var result = Record.Exception(() => filePath.DeserializeToIssues());
-
- // Then
- result.IsArgumentNullException("filePath");
- }
-
- [Fact]
- public void Should_Return_An_Empty_List_For_An_Empty_Array()
- {
- // Given
- var filePath = new FilePath("Testfiles/empty-array.json");
-
- // When
- var result = filePath.DeserializeToIssues();
-
- // Then
- result.ShouldBeEmpty();
- }
-
- [Fact]
- public void Should_Return_List_Of_Issues()
- {
- // Given
- var filePath = new FilePath("Testfiles/issues.json");
-
- // When
- var result = filePath.DeserializeToIssues().ToList();
-
- // Then
- result.Count.ShouldBe(2);
- IssueChecker.Check(
- result[0],
- IssueBuilder.NewIssue(
- "Something went wrong.",
- "TestProvider",
- "Test Provider")
- .InProject(@"src\Foo\Bar.csproj", "Bar")
- .InFile(@"src\Foo\Bar.cs", 42)
- .OfRule("Rule", new Uri("https://google.com"))
- .WithPriority(IssuePriority.Warning));
- IssueChecker.Check(
- result[1],
- IssueBuilder.NewIssue(
- "Something went wrong again.",
- "TestProvider",
- "Test Provider")
- .InProject(@"src\Foo\Bar.csproj", "Bar")
- .InFile(@"src\Foo\Bar2.cs")
- .WithPriority(IssuePriority.Warning));
- }
- }
-
- public sealed class TheToSerializableIssueExtension
- {
- [Fact]
- public void Should_Throw_If_Issue_Is_Null()
- {
- // Given
- IIssue issue = null;
-
- // When
- var result = Record.Exception(() => issue.ToSerializableIssue());
-
- // Then
- result.IsArgumentNullException("issue");
- }
- }
-
- public sealed class TheToIssueExtension
- {
- [Fact]
- public void Should_Throw_If_SerializableIssue_Is_Null()
- {
- // Given
- SerializableIssue serializableIssue = null;
-
- // When
- var result = Record.Exception(() => serializableIssue.ToIssue());
-
- // Then
- result.IsArgumentNullException("serializableIssue");
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/Cake.Issues.Tests/IssueTests.cs b/src/Cake.Issues.Tests/IssueTests.cs
index 3df1205d5..5a5d9b7ea 100644
--- a/src/Cake.Issues.Tests/IssueTests.cs
+++ b/src/Cake.Issues.Tests/IssueTests.cs
@@ -19,7 +19,9 @@ public void Should_Throw_If_Project_Path_Is_Invalid(string projectPath)
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 100;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -34,7 +36,9 @@ public void Should_Throw_If_Project_Path_Is_Invalid(string projectPath)
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -56,7 +60,9 @@ public void Should_Throw_If_File_Path_Is_Absolute(string projectPath)
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 100;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -71,7 +77,9 @@ public void Should_Throw_If_File_Path_Is_Absolute(string projectPath)
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -91,7 +99,9 @@ public void Should_Handle_Project_Paths_Which_Are_Null()
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -106,7 +116,9 @@ public void Should_Handle_Project_Paths_Which_Are_Null()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -126,7 +138,9 @@ public void Should_Handle_Project_Paths_Which_Are_Empty()
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -141,7 +155,9 @@ public void Should_Handle_Project_Paths_Which_Are_Empty()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -161,7 +177,9 @@ public void Should_Handle_Project_Paths_Which_Are_WhiteSpace()
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -176,7 +194,9 @@ public void Should_Handle_Project_Paths_Which_Are_WhiteSpace()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -196,7 +216,9 @@ public void Should_Set_ProjectFileRelativePath(string projectPath)
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -211,7 +233,9 @@ public void Should_Set_ProjectFileRelativePath(string projectPath)
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -234,7 +258,9 @@ public void Should_Handle_Projects_Which_Are_Null()
string projectName = null;
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -249,7 +275,9 @@ public void Should_Handle_Projects_Which_Are_Null()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -269,7 +297,9 @@ public void Should_Handle_Projects_Which_Are_Empty()
var projectName = string.Empty;
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -284,7 +314,9 @@ public void Should_Handle_Projects_Which_Are_Empty()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -304,7 +336,9 @@ public void Should_Handle_Projects_Which_Are_WhiteSpace()
var projectName = " ";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -319,7 +353,9 @@ public void Should_Handle_Projects_Which_Are_WhiteSpace()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -339,7 +375,9 @@ public void Should_Set_ProjectName(string projectName)
var projectPath = @"src\foo.csproj";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -354,7 +392,9 @@ public void Should_Set_ProjectName(string projectName)
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -377,7 +417,9 @@ public void Should_Throw_If_File_Path_Is_Invalid(string filePath)
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var line = 100;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -392,7 +434,9 @@ public void Should_Throw_If_File_Path_Is_Invalid(string filePath)
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -414,7 +458,9 @@ public void Should_Throw_If_File_Path_Is_Absolute(string filePath)
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var line = 100;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -429,7 +475,9 @@ public void Should_Throw_If_File_Path_Is_Absolute(string filePath)
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -449,7 +497,9 @@ public void Should_Handle_File_Paths_Which_Are_Null()
var projectName = "foo";
string filePath = null;
int? line = null;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -464,7 +514,9 @@ public void Should_Handle_File_Paths_Which_Are_Null()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -484,7 +536,9 @@ public void Should_Handle_File_Paths_Which_Are_Empty()
var projectName = "foo";
var filePath = string.Empty;
int? line = null;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -499,7 +553,9 @@ public void Should_Handle_File_Paths_Which_Are_Empty()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -519,7 +575,9 @@ public void Should_Handle_File_Paths_Which_Are_WhiteSpace()
var projectName = "foo";
var filePath = " ";
int? line = null;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -534,7 +592,9 @@ public void Should_Handle_File_Paths_Which_Are_WhiteSpace()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -562,7 +622,9 @@ public void Should_Set_File_Path(string filePath, string expectedFilePath)
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -577,7 +639,9 @@ public void Should_Set_File_Path(string filePath, string expectedFilePath)
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -601,7 +665,9 @@ public void Should_Throw_If_Line_Is_Negative()
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = -1;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -616,7 +682,9 @@ public void Should_Throw_If_Line_Is_Negative()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -636,7 +704,9 @@ public void Should_Throw_If_Line_Is_Zero()
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 0;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -651,7 +721,9 @@ public void Should_Throw_If_Line_Is_Zero()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -671,7 +743,9 @@ public void Should_Throw_If_Line_Is_Set_But_No_File()
var projectName = "foo";
string filePath = null;
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -686,7 +760,9 @@ public void Should_Throw_If_Line_Is_Set_But_No_File()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -708,7 +784,9 @@ public void Should_Set_Line(int? line)
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -723,7 +801,9 @@ public void Should_Set_Line(int? line)
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -736,17 +816,19 @@ public void Should_Set_Line(int? line)
}
}
- public sealed class TheMessageArgument
+ public sealed class TheMessageTextArgument
{
[Fact]
- public void Should_Throw_If_Message_Is_Null()
+ public void Should_Throw_If_MessageText_Is_Null()
{
// Given
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- string message = null;
+ string messageText = null;
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -761,7 +843,9 @@ public void Should_Throw_If_Message_Is_Null()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -770,18 +854,20 @@ public void Should_Throw_If_Message_Is_Null()
providerName));
// Then
- result.IsArgumentNullException("message");
+ result.IsArgumentNullException("messageText");
}
[Fact]
- public void Should_Throw_If_Message_Is_Empty()
+ public void Should_Throw_If_MessageText_Is_Empty()
{
// Given
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = string.Empty;
+ var messageText = string.Empty;
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -796,7 +882,9 @@ public void Should_Throw_If_Message_Is_Empty()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -805,18 +893,20 @@ public void Should_Throw_If_Message_Is_Empty()
providerName));
// Then
- result.IsArgumentOutOfRangeException("message");
+ result.IsArgumentOutOfRangeException("messageText");
}
[Fact]
- public void Should_Throw_If_Message_Is_WhiteSpace()
+ public void Should_Throw_If_MessageText_Is_WhiteSpace()
{
// Given
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = " ";
+ var messageText = " ";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -831,7 +921,9 @@ public void Should_Throw_If_Message_Is_WhiteSpace()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -840,18 +932,20 @@ public void Should_Throw_If_Message_Is_WhiteSpace()
providerName));
// Then
- result.IsArgumentOutOfRangeException("message");
+ result.IsArgumentOutOfRangeException("messageText");
}
[Theory]
- [InlineData("message")]
- public void Should_Set_Message(string message)
+ [InlineData("messageText")]
+ public void Should_Set_MessageText(string messageText)
{
// Given
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -866,7 +960,9 @@ public void Should_Set_Message(string message)
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -875,7 +971,97 @@ public void Should_Set_Message(string message)
providerName);
// Then
- issue.Message.ShouldBe(message);
+ issue.MessageText.ShouldBe(messageText);
+ }
+ }
+
+ public sealed class TheMessageHtmlArgument
+ {
+ [Theory]
+ [InlineData(null)]
+ [InlineData("")]
+ [InlineData(" ")]
+ [InlineData("messageHtml")]
+ public void Should_Set_MessageHtml(string messageHtml)
+ {
+ // Given
+ var projectPath = @"src\foo.csproj";
+ var projectName = "foo";
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var messageText = "MessageText";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+
+ // When
+ var issue =
+ new Issue(
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ providerType,
+ providerName);
+
+ // Then
+ issue.MessageHtml.ShouldBe(messageHtml);
+ }
+ }
+
+ public sealed class TheMessageMarkdownArgument
+ {
+ [Theory]
+ [InlineData(null)]
+ [InlineData("")]
+ [InlineData(" ")]
+ [InlineData("messageMarkdown")]
+ public void Should_Set_MessageHtml(string messageMarkdown)
+ {
+ // Given
+ var projectPath = @"src\foo.csproj";
+ var projectName = "foo";
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+
+ // When
+ var issue =
+ new Issue(
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ providerType,
+ providerName);
+
+ // Then
+ issue.MessageMarkdown.ShouldBe(messageMarkdown);
}
}
@@ -895,7 +1081,9 @@ public void Should_Set_Priority(int? priority)
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priorityName = "Warning";
var rule = "Rule";
var ruleUri = new Uri("https://google.com");
@@ -909,7 +1097,9 @@ public void Should_Set_Priority(int? priority)
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -932,7 +1122,9 @@ public void Should_Handle_PriorityNames_Which_Are_Null()
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
string priorityName = null;
var rule = "Rule";
@@ -947,7 +1139,9 @@ public void Should_Handle_PriorityNames_Which_Are_Null()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -967,7 +1161,9 @@ public void Should_Handle_PriorityNames_Which_Are_Empty()
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = string.Empty;
var rule = "Rule";
@@ -982,7 +1178,9 @@ public void Should_Handle_PriorityNames_Which_Are_Empty()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -1002,7 +1200,9 @@ public void Should_Handle_PriorityNames_Which_Are_WhiteSpace()
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = " ";
var rule = "Rule";
@@ -1017,7 +1217,9 @@ public void Should_Handle_PriorityNames_Which_Are_WhiteSpace()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -1038,7 +1240,9 @@ public void Should_Set_Priority_Name(string priorityName)
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var rule = "Rule";
var ruleUri = new Uri("https://google.com");
@@ -1052,7 +1256,9 @@ public void Should_Set_Priority_Name(string priorityName)
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -1078,7 +1284,9 @@ public void Should_Set_Rule(string rule)
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var ruleUri = new Uri("https://google.com");
@@ -1092,7 +1300,9 @@ public void Should_Set_Rule(string rule)
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -1115,7 +1325,9 @@ public void Should_Set_Rule_Url()
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -1130,7 +1342,9 @@ public void Should_Set_Rule_Url()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -1150,7 +1364,9 @@ public void Should_Set_Rule_Url_If_Null()
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -1165,7 +1381,9 @@ public void Should_Set_Rule_Url_If_Null()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -1188,7 +1406,9 @@ public void Should_Throw_If_Provider_Type_Is_Null()
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -1203,7 +1423,9 @@ public void Should_Throw_If_Provider_Type_Is_Null()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -1223,7 +1445,9 @@ public void Should_Throw_If_Provider_Type_Is_Empty()
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -1238,7 +1462,9 @@ public void Should_Throw_If_Provider_Type_Is_Empty()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -1258,7 +1484,9 @@ public void Should_Throw_If_Provider_Type_Is_WhiteSpace()
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -1273,7 +1501,9 @@ public void Should_Throw_If_Provider_Type_Is_WhiteSpace()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -1294,7 +1524,9 @@ public void Should_Set_ProviderType(string providerType)
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -1308,7 +1540,9 @@ public void Should_Set_ProviderType(string providerType)
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -1331,7 +1565,9 @@ public void Should_Throw_If_Provider_Name_Is_Null()
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -1346,7 +1582,9 @@ public void Should_Throw_If_Provider_Name_Is_Null()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -1366,7 +1604,9 @@ public void Should_Throw_If_Provider_Name_Is_Empty()
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -1381,7 +1621,9 @@ public void Should_Throw_If_Provider_Name_Is_Empty()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -1401,7 +1643,9 @@ public void Should_Throw_If_Provider_Name_Is_WhiteSpace()
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -1416,7 +1660,9 @@ public void Should_Throw_If_Provider_Name_Is_WhiteSpace()
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
@@ -1437,7 +1683,9 @@ public void Should_Set_ProviderName(string providerName)
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
- var message = "Message";
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
var priority = 1;
var priorityName = "Warning";
var rule = "Rule";
@@ -1451,7 +1699,9 @@ public void Should_Set_ProviderName(string providerName)
projectName,
filePath,
line,
- message,
+ messageText,
+ messageHtml,
+ messageMarkdown,
priority,
priorityName,
rule,
diff --git a/src/Cake.Issues.Tests/IssuesFixture.cs b/src/Cake.Issues.Tests/IssuesFixture.cs
index 9c6baf706..eecba2799 100644
--- a/src/Cake.Issues.Tests/IssuesFixture.cs
+++ b/src/Cake.Issues.Tests/IssuesFixture.cs
@@ -22,10 +22,10 @@ public IssuesFixture()
public RepositorySettings Settings { get; set; }
- public IEnumerable ReadIssues(IssueCommentFormat format)
+ public IEnumerable ReadIssues()
{
var issueReader = new IssuesReader(this.Log, this.IssueProviders, this.Settings);
- return issueReader.ReadIssues(format);
+ return issueReader.ReadIssues();
}
}
}
diff --git a/src/Cake.Issues.Tests/Serialization/IssueDeserializationExtensionsTests.cs b/src/Cake.Issues.Tests/Serialization/IssueDeserializationExtensionsTests.cs
new file mode 100644
index 000000000..f2ad8facb
--- /dev/null
+++ b/src/Cake.Issues.Tests/Serialization/IssueDeserializationExtensionsTests.cs
@@ -0,0 +1,230 @@
+namespace Cake.Issues.Tests.Serialization
+{
+ using System;
+ using System.Linq;
+ using Cake.Core.IO;
+ using Cake.Issues.Serialization;
+ using Cake.Issues.Testing;
+ using Shouldly;
+ using Xunit;
+
+ public sealed class IssueDeserializationExtensionsTests
+ {
+ public sealed class TheDeserializeToIssueExtensionForAJsonString
+ {
+ [Fact]
+ public void Should_Throw_If_JsonString_Is_Null()
+ {
+ // Given
+ string jsonString = null;
+
+ // When
+ var result = Record.Exception(() => jsonString.DeserializeToIssue());
+
+ // Then
+ result.IsArgumentNullException("jsonString");
+ }
+
+ [Fact]
+ public void Should_Throw_If_JsonString_Has_Unknown_Version()
+ {
+ // Given
+ var jsonString = "{\"Version\": -1}";
+
+ // When
+ var result = Record.Exception(() => jsonString.DeserializeToIssue());
+
+ // Then
+ result.Message.ShouldBe("Not supported issue serialization format -1");
+ }
+ }
+
+ public sealed class TheDeserializeToIssuesExtensionForAJsonString
+ {
+ [Fact]
+ public void Should_Throw_If_JsonString_Is_Null()
+ {
+ // Given
+ string jsonString = null;
+
+ // When
+ var result = Record.Exception(() => jsonString.DeserializeToIssues());
+
+ // Then
+ result.IsArgumentNullException("jsonString");
+ }
+
+ [Fact]
+ public void Should_Return_An_Empty_List_For_An_Empty_Array()
+ {
+ // Given
+ string jsonString = "[]";
+
+ // When
+ var result = jsonString.DeserializeToIssues();
+
+ // Then
+ result.ShouldBeEmpty();
+ }
+ }
+
+ public sealed class TheDeserializeToIssueExtensionForAJsonFile
+ {
+ [Fact]
+ public void Should_Throw_If_FilePath_Is_Null()
+ {
+ // Given
+ FilePath filePath = null;
+
+ // When
+ var result = Record.Exception(() => filePath.DeserializeToIssue());
+
+ // Then
+ result.IsArgumentNullException("filePath");
+ }
+
+ [Fact]
+ public void Should_Return_Issue()
+ {
+ // Given
+ var filePath = new FilePath("Testfiles/issue.json");
+
+ // When
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ IssueChecker.Check(
+ result,
+ IssueBuilder.NewIssue(
+ "Something went wrong.",
+ "TestProvider",
+ "Test Provider")
+ .InProject(@"src\Foo\Bar.csproj", "Bar")
+ .InFile(@"src\Foo\Bar.cs", 42)
+ .OfRule("Rule", new Uri("https://google.com"))
+ .WithPriority(IssuePriority.Warning));
+ }
+
+ [Fact]
+ public void Should_Return_IssueV2()
+ {
+ // Given
+ var filePath = new FilePath("Testfiles/issueV2.json");
+
+ // When
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ IssueChecker.Check(
+ result,
+ IssueBuilder.NewIssue(
+ "Something went wrong.",
+ "TestProvider",
+ "Test Provider")
+ .WithMessageInHtmlFormat("Something went wrong.")
+ .WithMessageInMarkdownFormat("Something went **wrong**.")
+ .InProject(@"src\Foo\Bar.csproj", "Bar")
+ .InFile(@"src\Foo\Bar.cs", 42)
+ .OfRule("Rule", new Uri("https://google.com"))
+ .WithPriority(IssuePriority.Warning));
+ }
+ }
+
+ public sealed class TheDeserializeToIssuesExtensionForAJsonFile
+ {
+ [Fact]
+ public void Should_Throw_If_FilePath_Is_Null()
+ {
+ // Given
+ FilePath filePath = null;
+
+ // When
+ var result = Record.Exception(() => filePath.DeserializeToIssues());
+
+ // Then
+ result.IsArgumentNullException("filePath");
+ }
+
+ [Fact]
+ public void Should_Return_An_Empty_List_For_An_Empty_Array()
+ {
+ // Given
+ var filePath = new FilePath("Testfiles/empty-array.json");
+
+ // When
+ var result = filePath.DeserializeToIssues();
+
+ // Then
+ result.ShouldBeEmpty();
+ }
+
+ [Fact]
+ public void Should_Return_List_Of_Issues()
+ {
+ // Given
+ var filePath = new FilePath("Testfiles/issues.json");
+
+ // When
+ var result = filePath.DeserializeToIssues().ToList();
+
+ // Then
+ result.Count.ShouldBe(2);
+ IssueChecker.Check(
+ result[0],
+ IssueBuilder.NewIssue(
+ "Something went wrong.",
+ "TestProvider",
+ "Test Provider")
+ .InProject(@"src\Foo\Bar.csproj", "Bar")
+ .InFile(@"src\Foo\Bar.cs", 42)
+ .OfRule("Rule", new Uri("https://google.com"))
+ .WithPriority(IssuePriority.Warning));
+ IssueChecker.Check(
+ result[1],
+ IssueBuilder.NewIssue(
+ "Something went wrong again.",
+ "TestProvider",
+ "Test Provider")
+ .InProject(@"src\Foo\Bar.csproj", "Bar")
+ .InFile(@"src\Foo\Bar2.cs")
+ .WithPriority(IssuePriority.Warning));
+ }
+
+ [Fact]
+ public void Should_Return_List_Of_IssuesV2()
+ {
+ // Given
+ var filePath = new FilePath("Testfiles/issuesV2.json");
+
+ // When
+ var result = filePath.DeserializeToIssues().ToList();
+
+ // Then
+ result.Count.ShouldBe(2);
+ IssueChecker.Check(
+ result[0],
+ IssueBuilder.NewIssue(
+ "Something went wrong.",
+ "TestProvider",
+ "Test Provider")
+ .WithMessageInHtmlFormat("Something went wrong.")
+ .WithMessageInMarkdownFormat("Something went **wrong**.")
+ .InProject(@"src\Foo\Bar.csproj", "Bar")
+ .InFile(@"src\Foo\Bar.cs", 42)
+ .OfRule("Rule", new Uri("https://google.com"))
+ .WithPriority(IssuePriority.Warning));
+ IssueChecker.Check(
+ result[1],
+ IssueBuilder.NewIssue(
+ "Something went wrong again.",
+ "TestProvider",
+ "Test Provider")
+ .WithMessageInHtmlFormat("Something went wrong again.")
+ .WithMessageInMarkdownFormat("Something went **wrong** again.")
+ .InProject(@"src\Foo\Bar.csproj", "Bar")
+ .InFile(@"src\Foo\Bar2.cs")
+ .WithPriority(IssuePriority.Warning));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Cake.Issues.Tests/Serialization/IssueSerializationExtensionsTests.cs b/src/Cake.Issues.Tests/Serialization/IssueSerializationExtensionsTests.cs
new file mode 100644
index 000000000..a280ff2af
--- /dev/null
+++ b/src/Cake.Issues.Tests/Serialization/IssueSerializationExtensionsTests.cs
@@ -0,0 +1,1617 @@
+namespace Cake.Issues.Tests.Serialization
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using Cake.Core.IO;
+ using Cake.Issues.Serialization;
+ using Cake.Issues.Testing;
+ using Shouldly;
+ using Xunit;
+
+ public sealed class IssueSerializationExtensionsTests
+ {
+ public sealed class TheSerializeToJsonStringExtensionForASingleIssue
+ {
+ [Fact]
+ public void Should_Throw_If_Issue_Is_Null()
+ {
+ // Given
+ IIssue issue = null;
+
+ // When
+ var result = Record.Exception(() => issue.SerializeToJsonString());
+
+ // Then
+ result.IsArgumentNullException("issue");
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_MessageText_After_Roundtrip()
+ {
+ // Given
+ var message = "message";
+ var issue =
+ IssueBuilder
+ .NewIssue(message, "providerType", "providerName")
+ .Create();
+
+ // When
+ var result = issue.SerializeToJsonString().DeserializeToIssue();
+
+ // Then
+ result.MessageText.ShouldBe(message);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_MessageMarkdown_After_Roundtrip()
+ {
+ // Given
+ var messageMarkdown = "messageMarkdown";
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithMessageInMarkdownFormat(messageMarkdown)
+ .Create();
+
+ // When
+ var result = issue.SerializeToJsonString().DeserializeToIssue();
+
+ // Then
+ result.MessageMarkdown.ShouldBe(messageMarkdown);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_MessageHtml_After_Roundtrip()
+ {
+ // Given
+ var messageHtml = "messageHtml";
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithMessageInHtmlFormat(messageHtml)
+ .Create();
+
+ // When
+ var result = issue.SerializeToJsonString().DeserializeToIssue();
+
+ // Then
+ result.MessageHtml.ShouldBe(messageHtml);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_ProviderType_After_Roundtrip()
+ {
+ // Given
+ var providerType = "providerType";
+ var issue =
+ IssueBuilder
+ .NewIssue("message", providerType, "providerName")
+ .Create();
+
+ // When
+ var result = issue.SerializeToJsonString().DeserializeToIssue();
+
+ // Then
+ result.ProviderType.ShouldBe(providerType);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_ProviderName_After_Roundtrip()
+ {
+ // Given
+ var providerName = "providerName";
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", providerName)
+ .Create();
+
+ // When
+ var result = issue.SerializeToJsonString().DeserializeToIssue();
+
+ // Then
+ result.ProviderName.ShouldBe(providerName);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_ProjectFileRelativePath_After_Roundtrip()
+ {
+ // Given
+ var projectFileRelativePath = @"src/myproj.file";
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InProjectFile(projectFileRelativePath)
+ .Create();
+
+ // When
+ var result = issue.SerializeToJsonString().DeserializeToIssue();
+
+ // Then
+ result.ProjectFileRelativePath.FullPath.ShouldBe(projectFileRelativePath);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_ProjectName_After_Roundtrip()
+ {
+ // Given
+ var projectName = "projectName";
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InProjectOfName(projectName)
+ .Create();
+
+ // When
+ var result = issue.SerializeToJsonString().DeserializeToIssue();
+
+ // Then
+ result.ProjectName.ShouldBe(projectName);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_AffectedFileRelativePath_After_Roundtrip()
+ {
+ // Given
+ var affectedFileRelativePath = @"src/foo.bar";
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile(affectedFileRelativePath)
+ .Create();
+
+ // When
+ var result = issue.SerializeToJsonString().DeserializeToIssue();
+
+ // Then
+ result.AffectedFileRelativePath.FullPath.ShouldBe(affectedFileRelativePath);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_Line_After_Roundtrip()
+ {
+ // Given
+ var line = 42;
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile(@"src/foo.bar", line)
+ .Create();
+
+ // When
+ var result = issue.SerializeToJsonString().DeserializeToIssue();
+
+ // Then
+ result.Line.ShouldBe(line);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_Priority_After_Roundtrip()
+ {
+ // Given
+ var priority = 42;
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithPriority(priority, "priorityName")
+ .Create();
+
+ // When
+ var result = issue.SerializeToJsonString().DeserializeToIssue();
+
+ // Then
+ result.Priority.ShouldBe(priority);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_PriorityName_After_Roundtrip()
+ {
+ // Given
+ var priorityName = "priorityName";
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithPriority(42, priorityName)
+ .Create();
+
+ // When
+ var result = issue.SerializeToJsonString().DeserializeToIssue();
+
+ // Then
+ result.PriorityName.ShouldBe(priorityName);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_Rule_After_Roundtrip()
+ {
+ // Given
+ var rule = "rule";
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .OfRule(rule)
+ .Create();
+
+ // When
+ var result = issue.SerializeToJsonString().DeserializeToIssue();
+
+ // Then
+ result.Rule.ShouldBe(rule);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_RuleUrl_After_Roundtrip()
+ {
+ // Given
+ var ruleUrl = new Uri("https://rule.url");
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .OfRule("rule", ruleUrl)
+ .Create();
+
+ // When
+ var result = issue.SerializeToJsonString().DeserializeToIssue();
+
+ // Then
+ result.RuleUrl.ToString().ShouldBe(ruleUrl.ToString());
+ }
+ }
+
+ public sealed class TheSerializeToJsonStringExtensionForAnEnumerableOfIssues
+ {
+ [Fact]
+ public void Should_Throw_If_Issue_Is_Null()
+ {
+ // Given
+ IEnumerable issues = null;
+
+ // When
+ var result = Record.Exception(() => issues.SerializeToJsonString());
+
+ // Then
+ result.IsArgumentNullException("issues");
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_MessageText_After_Roundtrip()
+ {
+ // Given
+ var messageText1 = "messageText1";
+ var messageText2 = "messageText2";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue(messageText1, "providerType1", "providerName1")
+ .Create(),
+ IssueBuilder
+ .NewIssue(messageText2, "providerType2", "providerName2")
+ .Create(),
+ };
+
+ // When
+ var result = issues.SerializeToJsonString().DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().MessageText.ShouldBe(messageText1);
+ result.Last().MessageText.ShouldBe(messageText2);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_MessageMarkdown_After_Roundtrip()
+ {
+ // Given
+ var messageMarkdown1 = "messageMarkdown1";
+ var messageMarkdown2 = "messageMarkdown2";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("messageText1", "providerType1", "providerName1")
+ .WithMessageInMarkdownFormat(messageMarkdown1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("messageText2", "providerType2", "providerName2")
+ .WithMessageInMarkdownFormat(messageMarkdown2)
+ .Create(),
+ };
+
+ // When
+ var result = issues.SerializeToJsonString().DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().MessageMarkdown.ShouldBe(messageMarkdown1);
+ result.Last().MessageMarkdown.ShouldBe(messageMarkdown2);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_MessageHtml_After_Roundtrip()
+ {
+ // Given
+ var messageHtml1 = "messageHtml1";
+ var messageHtml2 = "messageHtml2";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("messageText1", "providerType1", "providerName1")
+ .WithMessageInHtmlFormat(messageHtml1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("messageText2", "providerType2", "providerName2")
+ .WithMessageInHtmlFormat(messageHtml2)
+ .Create(),
+ };
+
+ // When
+ var result = issues.SerializeToJsonString().DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().MessageHtml.ShouldBe(messageHtml1);
+ result.Last().MessageHtml.ShouldBe(messageHtml2);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_ProviderType_After_Roundtrip()
+ {
+ // Given
+ var providerType1 = "providerType1";
+ var providerType2 = "providerType2";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", providerType1, "providerName1")
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", providerType2, "providerName2")
+ .Create(),
+ };
+
+ // When
+ var result = issues.SerializeToJsonString().DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().ProviderType.ShouldBe(providerType1);
+ result.Last().ProviderType.ShouldBe(providerType2);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_ProviderName_After_Roundtrip()
+ {
+ // Given
+ var providerName1 = "providerName1";
+ var providerName2 = "providerName2";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", providerName1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", providerName2)
+ .Create(),
+ };
+
+ // When
+ var result = issues.SerializeToJsonString().DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().ProviderName.ShouldBe(providerName1);
+ result.Last().ProviderName.ShouldBe(providerName2);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_ProjectFileRelativePath_After_Roundtrip()
+ {
+ // Given
+ var projectFileRelativePath1 = @"src/myproj1.file";
+ var projectFileRelativePath2 = @"src/myproj2.file";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .InProjectFile(projectFileRelativePath1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .InProjectFile(projectFileRelativePath2)
+ .Create(),
+ };
+
+ // When
+ var result = issues.SerializeToJsonString().DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().ProjectFileRelativePath.FullPath.ShouldBe(projectFileRelativePath1);
+ result.Last().ProjectFileRelativePath.FullPath.ShouldBe(projectFileRelativePath2);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_ProjectName_After_Roundtrip()
+ {
+ // Given
+ var projectName1 = "projectName1";
+ var projectName2 = "projectName2";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .InProjectOfName(projectName1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .InProjectOfName(projectName2)
+ .Create(),
+ };
+
+ // When
+ var result = issues.SerializeToJsonString().DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().ProjectName.ShouldBe(projectName1);
+ result.Last().ProjectName.ShouldBe(projectName2);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_AffectedFileRelativePath_After_Roundtrip()
+ {
+ // Given
+ var affectedFileRelativePath1 = @"src/foo1.bar";
+ var affectedFileRelativePath2 = @"src/foo2.bar";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .InFile(affectedFileRelativePath1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .InFile(affectedFileRelativePath2)
+ .Create(),
+ };
+
+ // When
+ var result = issues.SerializeToJsonString().DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().AffectedFileRelativePath.FullPath.ShouldBe(affectedFileRelativePath1);
+ result.Last().AffectedFileRelativePath.FullPath.ShouldBe(affectedFileRelativePath2);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_Line_After_Roundtrip()
+ {
+ // Given
+ var line1 = 23;
+ var line2 = 42;
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .InFile(@"src/foo.bar", line1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .InFile(@"src/foo.bar", line2)
+ .Create(),
+ };
+
+ // When
+ var result = issues.SerializeToJsonString().DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().Line.ShouldBe(line1);
+ result.Last().Line.ShouldBe(line2);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_Priority_After_Roundtrip()
+ {
+ // Given
+ var priority1 = 23;
+ var priority2 = 42;
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .WithPriority(priority1, "priorityName")
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .WithPriority(priority2, "priorityName")
+ .Create(),
+ };
+
+ // When
+ var result = issues.SerializeToJsonString().DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().Priority.ShouldBe(priority1);
+ result.Last().Priority.ShouldBe(priority2);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_PriorityName_After_Roundtrip()
+ {
+ // Given
+ var priorityName1 = "priorityName1";
+ var priorityName2 = "priorityName2";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .WithPriority(42, priorityName1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .WithPriority(42, priorityName2)
+ .Create(),
+ };
+
+ // When
+ var result = issues.SerializeToJsonString().DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().PriorityName.ShouldBe(priorityName1);
+ result.Last().PriorityName.ShouldBe(priorityName2);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_Rule_After_Roundtrip()
+ {
+ // Given
+ var rule1 = "rule1";
+ var rule2 = "rule2";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .OfRule(rule1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .OfRule(rule2)
+ .Create(),
+ };
+
+ // When
+ var result = issues.SerializeToJsonString().DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().Rule.ShouldBe(rule1);
+ result.Last().Rule.ShouldBe(rule2);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_RuleUrl_After_Roundtrip()
+ {
+ // Given
+ var ruleUrl1 = new Uri("https://rule1.url");
+ var ruleUrl2 = new Uri("https://rule2.url");
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .OfRule("rule", ruleUrl1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .OfRule("rule", ruleUrl2)
+ .Create(),
+ };
+
+ // When
+ var result = issues.SerializeToJsonString().DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().RuleUrl.ToString().ShouldBe(ruleUrl1.ToString());
+ result.Last().RuleUrl.ToString().ShouldBe(ruleUrl2.ToString());
+ }
+ }
+
+ public sealed class TheSerializeToJsonFileExtensionForASingleIssue
+ {
+ [Fact]
+ public void Should_Throw_If_Issue_Is_Null()
+ {
+ // Given
+ IIssue issue = null;
+ var filePath = @"c:\issue.json";
+
+ // When
+ var result = Record.Exception(() => issue.SerializeToJsonFile(filePath));
+
+ // Then
+ result.IsArgumentNullException("issue");
+ }
+
+ [Fact]
+ public void Should_Throw_If_FilePath_Is_Null()
+ {
+ // Given
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .Create();
+ FilePath filePath = null;
+
+ // When
+ var result = Record.Exception(() => issue.SerializeToJsonFile(filePath));
+
+ // Then
+ result.IsArgumentNullException("filePath");
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_MessageText_After_Roundtrip()
+ {
+ // Given
+ var messageText = "messageText";
+ var issue =
+ IssueBuilder
+ .NewIssue(messageText, "providerType", "providerName")
+ .Create();
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issue.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ result.MessageText.ShouldBe(messageText);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_MessageMarkdown_After_Roundtrip()
+ {
+ // Given
+ var messageMarkdown = "messageMarkdown";
+ var issue =
+ IssueBuilder
+ .NewIssue("messageText", "providerType", "providerName")
+ .WithMessageInMarkdownFormat(messageMarkdown)
+ .Create();
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issue.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ result.MessageMarkdown.ShouldBe(messageMarkdown);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_MessageHtml_After_Roundtrip()
+ {
+ // Given
+ var messageHtml = "messageHtml";
+ var issue =
+ IssueBuilder
+ .NewIssue("messageText", "providerType", "providerName")
+ .WithMessageInHtmlFormat(messageHtml)
+ .Create();
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issue.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ result.MessageHtml.ShouldBe(messageHtml);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_ProviderType_After_Roundtrip()
+ {
+ // Given
+ var providerType = "providerType";
+ var issue =
+ IssueBuilder
+ .NewIssue("message", providerType, "providerName")
+ .Create();
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issue.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ result.ProviderType.ShouldBe(providerType);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_ProviderName_After_Roundtrip()
+ {
+ // Given
+ var providerName = "providerName";
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", providerName)
+ .Create();
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issue.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ result.ProviderName.ShouldBe(providerName);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_ProjectFileRelativePath_After_Roundtrip()
+ {
+ // Given
+ var projectFileRelativePath = @"src/myproj.file";
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InProjectFile(projectFileRelativePath)
+ .Create();
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issue.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ result.ProjectFileRelativePath.FullPath.ShouldBe(projectFileRelativePath);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_ProjectName_After_Roundtrip()
+ {
+ // Given
+ var projectName = "projectName";
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InProjectOfName(projectName)
+ .Create();
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issue.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ result.ProjectName.ShouldBe(projectName);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_AffectedFileRelativePath_After_Roundtrip()
+ {
+ // Given
+ var affectedFileRelativePath = @"src/foo.bar";
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile(affectedFileRelativePath)
+ .Create();
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issue.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ result.AffectedFileRelativePath.FullPath.ShouldBe(affectedFileRelativePath);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_Line_After_Roundtrip()
+ {
+ // Given
+ var line = 42;
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile(@"src/foo.bar", line)
+ .Create();
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issue.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ result.Line.ShouldBe(line);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_Priority_After_Roundtrip()
+ {
+ // Given
+ var priority = 42;
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithPriority(priority, "priorityName")
+ .Create();
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issue.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ result.Priority.ShouldBe(priority);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_PriorityName_After_Roundtrip()
+ {
+ // Given
+ var priorityName = "priorityName";
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithPriority(42, priorityName)
+ .Create();
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issue.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ result.PriorityName.ShouldBe(priorityName);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_Rule_After_Roundtrip()
+ {
+ // Given
+ var rule = "rule";
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .OfRule(rule)
+ .Create();
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issue.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ result.Rule.ShouldBe(rule);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_RuleUrl_After_Roundtrip()
+ {
+ // Given
+ var ruleUrl = new Uri("https://rule.url");
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .OfRule("rule", ruleUrl)
+ .Create();
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issue.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ result.RuleUrl.ToString().ShouldBe(ruleUrl.ToString());
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+ }
+
+ public sealed class TheSerializeToJsonFileExtensionForAnEnumerableOfIssues
+ {
+ [Fact]
+ public void Should_Throw_If_Issue_Is_Null()
+ {
+ // Given
+ IEnumerable issues = null;
+ var filePath = @"c:\issues.json";
+
+ // When
+ var result = Record.Exception(() => issues.SerializeToJsonFile(filePath));
+
+ // Then
+ result.IsArgumentNullException("issues");
+ }
+
+ [Fact]
+ public void Should_Throw_If_FilePath_Is_Null()
+ {
+ // Given
+ var issues = new List();
+ FilePath filePath = null;
+
+ // When
+ var result = Record.Exception(() => issues.SerializeToJsonFile(filePath));
+
+ // Then
+ result.IsArgumentNullException("filePath");
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_MessageText_After_Roundtrip()
+ {
+ // Given
+ var messageText1 = "messageText1";
+ var messageText2 = "messageText2";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue(messageText1, "providerType1", "providerName1")
+ .Create(),
+ IssueBuilder
+ .NewIssue(messageText2, "providerType2", "providerName2")
+ .Create(),
+ };
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issues.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().MessageText.ShouldBe(messageText1);
+ result.Last().MessageText.ShouldBe(messageText2);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_MessageMarkdown_After_Roundtrip()
+ {
+ // Given
+ var messageMarkdown1 = "messageMarkdown1";
+ var messageMarkdown2 = "messageMarkdown2";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("messageText1", "providerType1", "providerName1")
+ .WithMessageInMarkdownFormat(messageMarkdown1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("messageText2", "providerType2", "providerName2")
+ .WithMessageInMarkdownFormat(messageMarkdown2)
+ .Create(),
+ };
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issues.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().MessageMarkdown.ShouldBe(messageMarkdown1);
+ result.Last().MessageMarkdown.ShouldBe(messageMarkdown2);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_MessageHtml_After_Roundtrip()
+ {
+ // Given
+ var messageHtml1 = "messageHtml1";
+ var messageHtml2 = "messageHtml2";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("messageText1", "providerType1", "providerName1")
+ .WithMessageInHtmlFormat(messageHtml1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("messageText2", "providerType2", "providerName2")
+ .WithMessageInHtmlFormat(messageHtml2)
+ .Create(),
+ };
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issues.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().MessageHtml.ShouldBe(messageHtml1);
+ result.Last().MessageHtml.ShouldBe(messageHtml2);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_ProviderType_After_Roundtrip()
+ {
+ // Given
+ var providerType1 = "providerType1";
+ var providerType2 = "providerType2";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", providerType1, "providerName1")
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", providerType2, "providerName2")
+ .Create(),
+ };
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issues.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().ProviderType.ShouldBe(providerType1);
+ result.Last().ProviderType.ShouldBe(providerType2);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_ProviderName_After_Roundtrip()
+ {
+ // Given
+ var providerName1 = "providerName1";
+ var providerName2 = "providerName2";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", providerName1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", providerName2)
+ .Create(),
+ };
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issues.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().ProviderName.ShouldBe(providerName1);
+ result.Last().ProviderName.ShouldBe(providerName2);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_ProjectFileRelativePath_After_Roundtrip()
+ {
+ // Given
+ var projectFileRelativePath1 = @"src/myproj1.file";
+ var projectFileRelativePath2 = @"src/myproj2.file";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .InProjectFile(projectFileRelativePath1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .InProjectFile(projectFileRelativePath2)
+ .Create(),
+ };
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issues.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().ProjectFileRelativePath.FullPath.ShouldBe(projectFileRelativePath1);
+ result.Last().ProjectFileRelativePath.FullPath.ShouldBe(projectFileRelativePath2);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_ProjectName_After_Roundtrip()
+ {
+ // Given
+ var projectName1 = "projectName1";
+ var projectName2 = "projectName2";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .InProjectOfName(projectName1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .InProjectOfName(projectName2)
+ .Create(),
+ };
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issues.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().ProjectName.ShouldBe(projectName1);
+ result.Last().ProjectName.ShouldBe(projectName2);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_AffectedFileRelativePath_After_Roundtrip()
+ {
+ // Given
+ var affectedFileRelativePath1 = @"src/foo1.bar";
+ var affectedFileRelativePath2 = @"src/foo2.bar";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .InFile(affectedFileRelativePath1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .InFile(affectedFileRelativePath2)
+ .Create(),
+ };
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issues.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().AffectedFileRelativePath.FullPath.ShouldBe(affectedFileRelativePath1);
+ result.Last().AffectedFileRelativePath.FullPath.ShouldBe(affectedFileRelativePath2);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_Line_After_Roundtrip()
+ {
+ // Given
+ var line1 = 23;
+ var line2 = 42;
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .InFile(@"src/foo.bar", line1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .InFile(@"src/foo.bar", line2)
+ .Create(),
+ };
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issues.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().Line.ShouldBe(line1);
+ result.Last().Line.ShouldBe(line2);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_Priority_After_Roundtrip()
+ {
+ // Given
+ var priority1 = 23;
+ var priority2 = 42;
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .WithPriority(priority1, "priorityName")
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .WithPriority(priority2, "priorityName")
+ .Create(),
+ };
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issues.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().Priority.ShouldBe(priority1);
+ result.Last().Priority.ShouldBe(priority2);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_PriorityName_After_Roundtrip()
+ {
+ // Given
+ var priorityName1 = "priorityName1";
+ var priorityName2 = "priorityName2";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .WithPriority(42, priorityName1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .WithPriority(42, priorityName2)
+ .Create(),
+ };
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issues.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().PriorityName.ShouldBe(priorityName1);
+ result.Last().PriorityName.ShouldBe(priorityName2);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_Rule_After_Roundtrip()
+ {
+ // Given
+ var rule1 = "rule1";
+ var rule2 = "rule2";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .OfRule(rule1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .OfRule(rule2)
+ .Create(),
+ };
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issues.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().Rule.ShouldBe(rule1);
+ result.Last().Rule.ShouldBe(rule2);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_RuleUrl_After_Roundtrip()
+ {
+ // Given
+ var ruleUrl1 = new Uri("https://rule1.url");
+ var ruleUrl2 = new Uri("https://rule2.url");
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .OfRule("rule", ruleUrl1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .OfRule("rule", ruleUrl2)
+ .Create(),
+ };
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issues.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().RuleUrl.ToString().ShouldBe(ruleUrl1.ToString());
+ result.Last().RuleUrl.ToString().ShouldBe(ruleUrl2.ToString());
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+ }
+
+ public sealed class TheToSerializableIssueExtension
+ {
+ [Fact]
+ public void Should_Throw_If_Issue_Is_Null()
+ {
+ // Given
+ IIssue issue = null;
+
+ // When
+ var result = Record.Exception(() => issue.ToSerializableIssue());
+
+ // Then
+ result.IsArgumentNullException("issue");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Cake.Issues.Tests/Serialization/SerializableIssueExtensionsTests.cs b/src/Cake.Issues.Tests/Serialization/SerializableIssueExtensionsTests.cs
new file mode 100644
index 000000000..79e174bae
--- /dev/null
+++ b/src/Cake.Issues.Tests/Serialization/SerializableIssueExtensionsTests.cs
@@ -0,0 +1,25 @@
+namespace Cake.Issues.Tests.Serialization
+{
+ using Cake.Issues.Serialization;
+ using Cake.Issues.Testing;
+ using Xunit;
+
+ public sealed class SerializableIssueExtensionsTests
+ {
+ public sealed class TheToIssueExtension
+ {
+ [Fact]
+ public void Should_Throw_If_SerializableIssue_Is_Null()
+ {
+ // Given
+ SerializableIssue serializableIssue = null;
+
+ // When
+ var result = Record.Exception(() => serializableIssue.ToIssue());
+
+ // Then
+ result.IsArgumentNullException("serializableIssue");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Cake.Issues.Tests/Serialization/SerializableIssueV2ExtensionsTests.cs b/src/Cake.Issues.Tests/Serialization/SerializableIssueV2ExtensionsTests.cs
new file mode 100644
index 000000000..4ef0f43c0
--- /dev/null
+++ b/src/Cake.Issues.Tests/Serialization/SerializableIssueV2ExtensionsTests.cs
@@ -0,0 +1,25 @@
+namespace Cake.Issues.Tests.Serialization
+{
+ using Cake.Issues.Serialization;
+ using Cake.Issues.Testing;
+ using Xunit;
+
+ public sealed class SerializableIssueV2ExtensionsTests
+ {
+ public sealed class TheToIssueExtension
+ {
+ [Fact]
+ public void Should_Throw_If_SerializableIssue_Is_Null()
+ {
+ // Given
+ SerializableIssueV2 serializableIssue = null;
+
+ // When
+ var result = Record.Exception(() => serializableIssue.ToIssue());
+
+ // Then
+ result.IsArgumentNullException("serializableIssue");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Cake.Issues.Tests/Testfiles/issueV2.json b/src/Cake.Issues.Tests/Testfiles/issueV2.json
new file mode 100644
index 000000000..88edfa346
--- /dev/null
+++ b/src/Cake.Issues.Tests/Testfiles/issueV2.json
@@ -0,0 +1,16 @@
+{
+ "Version": 2,
+ "AffectedFileRelativePath": "src\/Foo\/Bar.cs",
+ "Line": 42,
+ "MessageText": "Something went wrong.",
+ "MessageHtml": "Something went wrong.",
+ "MessageMarkdown": "Something went **wrong**.",
+ "Priority": 300,
+ "PriorityName": "Warning",
+ "ProjectFileRelativePath": "src\/Foo\/Bar.csproj",
+ "ProjectName": "Bar",
+ "ProviderName": "Test Provider",
+ "ProviderType": "TestProvider",
+ "Rule": "Rule",
+ "RuleUrl": "https://google.com"
+}
\ No newline at end of file
diff --git a/src/Cake.Issues.Tests/Testfiles/issuesV2.json b/src/Cake.Issues.Tests/Testfiles/issuesV2.json
new file mode 100644
index 000000000..9b42ecc13
--- /dev/null
+++ b/src/Cake.Issues.Tests/Testfiles/issuesV2.json
@@ -0,0 +1,34 @@
+[
+ {
+ "Version": 2,
+ "AffectedFileRelativePath": "src\/Foo\/Bar.cs",
+ "Line": 42,
+ "MessageText": "Something went wrong.",
+ "MessageHtml": "Something went wrong.",
+ "MessageMarkdown": "Something went **wrong**.",
+ "Priority": 300,
+ "PriorityName": "Warning",
+ "ProjectFileRelativePath": "src\/Foo\/Bar.csproj",
+ "ProjectName": "Bar",
+ "ProviderName": "Test Provider",
+ "ProviderType": "TestProvider",
+ "Rule": "Rule",
+ "RuleUrl": "https://google.com"
+ },
+ {
+ "Version": 2,
+ "AffectedFileRelativePath": "src\/Foo\/Bar2.cs",
+ "Line": null,
+ "MessageText": "Something went wrong again.",
+ "MessageHtml": "Something went wrong again.",
+ "MessageMarkdown": "Something went **wrong** again.",
+ "Priority": 300,
+ "PriorityName": "Warning",
+ "ProjectFileRelativePath": "src\/Foo\/Bar.csproj",
+ "ProjectName": "Bar",
+ "ProviderName": "Test Provider",
+ "ProviderType": "TestProvider",
+ "Rule": null,
+ "RuleUrl": null
+ }
+]
\ No newline at end of file
diff --git a/src/Cake.Issues.Tests/Testing/IssueCheckerFixture.cs b/src/Cake.Issues.Tests/Testing/IssueCheckerFixture.cs
index e6102eeb4..918571a1d 100644
--- a/src/Cake.Issues.Tests/Testing/IssueCheckerFixture.cs
+++ b/src/Cake.Issues.Tests/Testing/IssueCheckerFixture.cs
@@ -9,8 +9,8 @@ public IssueCheckerFixture()
{
}
- public IssueCheckerFixture(string message, string providerType, string providerName)
- : base(message, providerType, providerName)
+ public IssueCheckerFixture(string messageText, string providerType, string providerName)
+ : base(messageText, providerType, providerName)
{
this.ProviderType = providerType;
this.ProviderName = providerName;
@@ -18,13 +18,17 @@ public IssueCheckerFixture(string message, string providerType, string providerN
this.ProjectName = "ProjectName";
this.AffectedFileRelativePath = @"src\source.file";
this.Line = 42;
- this.Message = message;
+ this.MessageText = messageText;
+ this.MessageHtml = "messageHtml";
+ this.MessageMarkdown = "messageMarkdown";
this.Priority = 100;
this.PriorityName = "PriorityName";
this.Rule = "Rule";
this.RuleUrl = new Uri("https://google.com");
this.IssueBuilder
+ .WithMessageInHtmlFormat(this.MessageHtml)
+ .WithMessageInMarkdownFormat(this.MessageMarkdown)
.InProject(this.ProjectFileRelativePath, this.ProjectName)
.InFile(this.AffectedFileRelativePath, this.Line)
.OfRule(this.Rule, this.RuleUrl)
@@ -48,7 +52,11 @@ public IssueCheckerFixture(string message, string providerType, string providerN
public int Line { get; private set; }
- public string Message { get; private set; }
+ public string MessageText { get; private set; }
+
+ public string MessageHtml { get; private set; }
+
+ public string MessageMarkdown { get; private set; }
public int Priority { get; private set; }
diff --git a/src/Cake.Issues.Tests/Testing/IssueCheckerTests.cs b/src/Cake.Issues.Tests/Testing/IssueCheckerTests.cs
index 310fdd7ca..2b8c8fddf 100644
--- a/src/Cake.Issues.Tests/Testing/IssueCheckerTests.cs
+++ b/src/Cake.Issues.Tests/Testing/IssueCheckerTests.cs
@@ -148,7 +148,9 @@ public void Should_Throw_If_Issue_Is_Null()
fixture.ProjectName,
fixture.AffectedFileRelativePath,
fixture.Line,
- fixture.Message,
+ fixture.MessageText,
+ fixture.MessageHtml,
+ fixture.MessageMarkdown,
fixture.Priority,
fixture.PriorityName,
fixture.Rule,
@@ -173,7 +175,9 @@ public void Should_Not_Throw_If_All_Values_Are_The_Same()
fixture.ProjectName,
fixture.AffectedFileRelativePath,
fixture.Line,
- fixture.Message,
+ fixture.MessageText,
+ fixture.MessageHtml,
+ fixture.MessageMarkdown,
fixture.Priority,
fixture.PriorityName,
fixture.Rule,
@@ -202,7 +206,9 @@ public void Should_Throw_If_ProviderType_Is_Different(string expectedValue, stri
fixture.ProjectName,
fixture.AffectedFileRelativePath,
fixture.Line,
- fixture.Message,
+ fixture.MessageText,
+ fixture.MessageHtml,
+ fixture.MessageMarkdown,
fixture.Priority,
fixture.PriorityName,
fixture.Rule,
@@ -233,7 +239,9 @@ public void Should_Throw_If_ProviderName_Is_Different(string expectedValue, stri
fixture.ProjectName,
fixture.AffectedFileRelativePath,
fixture.Line,
- fixture.Message,
+ fixture.MessageText,
+ fixture.MessageHtml,
+ fixture.MessageMarkdown,
fixture.Priority,
fixture.PriorityName,
fixture.Rule,
@@ -265,7 +273,9 @@ public void Should_Throw_If_ProjectFileRelativePath_Is_Different(string expected
fixture.ProjectName,
fixture.AffectedFileRelativePath,
fixture.Line,
- fixture.Message,
+ fixture.MessageText,
+ fixture.MessageHtml,
+ fixture.MessageMarkdown,
fixture.Priority,
fixture.PriorityName,
fixture.Rule,
@@ -300,7 +310,9 @@ public void Should_Throw_If_ProjectName_Is_Different(string expectedValue, strin
expectedValue,
fixture.AffectedFileRelativePath,
fixture.Line,
- fixture.Message,
+ fixture.MessageText,
+ fixture.MessageHtml,
+ fixture.MessageMarkdown,
fixture.Priority,
fixture.PriorityName,
fixture.Rule,
@@ -332,7 +344,9 @@ public void Should_Throw_If_AffectedFileRelativePath_Is_Different(string expecte
fixture.ProjectName,
expectedValue,
fixture.Line,
- fixture.Message,
+ fixture.MessageText,
+ fixture.MessageHtml,
+ fixture.MessageMarkdown,
fixture.Priority,
fixture.PriorityName,
fixture.Rule,
@@ -366,7 +380,9 @@ public void Should_Throw_If_Line_Is_Different(int? expectedValue, int? actualVal
fixture.ProjectName,
fixture.AffectedFileRelativePath,
expectedValue,
- fixture.Message,
+ fixture.MessageText,
+ fixture.MessageHtml,
+ fixture.MessageMarkdown,
fixture.Priority,
fixture.PriorityName,
fixture.Rule,
@@ -382,7 +398,7 @@ public void Should_Throw_If_Line_Is_Different(int? expectedValue, int? actualVal
[InlineData(null, "Foo")]
[InlineData("", "Foo")]
[InlineData(" ", "Foo")]
- public void Should_Throw_If_Message_Is_Different(string expectedValue, string actualValue)
+ public void Should_Throw_If_MessageText_Is_Different(string expectedValue, string actualValue)
{
// Given
var fixture = new IssueCheckerFixture(actualValue, "ProviderType", "ProviderName");
@@ -398,6 +414,8 @@ public void Should_Throw_If_Message_Is_Different(string expectedValue, string ac
fixture.AffectedFileRelativePath,
fixture.Line,
expectedValue,
+ fixture.MessageHtml,
+ fixture.MessageMarkdown,
fixture.Priority,
fixture.PriorityName,
fixture.Rule,
@@ -405,7 +423,81 @@ public void Should_Throw_If_Message_Is_Different(string expectedValue, string ac
// Then
result.ShouldBeOfType();
- result.Message.ShouldStartWith("Expected issue.Message");
+ result.Message.ShouldStartWith("Expected issue.MessageText");
+ }
+
+ [Theory]
+ [InlineData("Message", "Foo")]
+ [InlineData(null, "Foo")]
+ [InlineData("", "Foo")]
+ [InlineData(" ", "Foo")]
+ public void Should_Throw_If_MessageHtml_Is_Different(string expectedValue, string actualValue)
+ {
+ // Given
+ var fixture = new IssueCheckerFixture();
+ var issue =
+ fixture.IssueBuilder
+ .WithMessageInHtmlFormat(actualValue)
+ .Create();
+
+ // When
+ var result = Record.Exception(() =>
+ IssueChecker.Check(
+ fixture.Issue,
+ fixture.ProviderType,
+ fixture.ProviderName,
+ fixture.ProjectFileRelativePath,
+ fixture.ProjectName,
+ fixture.AffectedFileRelativePath,
+ fixture.Line,
+ fixture.MessageText,
+ expectedValue,
+ fixture.MessageMarkdown,
+ fixture.Priority,
+ fixture.PriorityName,
+ fixture.Rule,
+ fixture.RuleUrl));
+
+ // Then
+ result.ShouldBeOfType();
+ result.Message.ShouldStartWith("Expected issue.MessageHtml");
+ }
+
+ [Theory]
+ [InlineData("Message", "Foo")]
+ [InlineData(null, "Foo")]
+ [InlineData("", "Foo")]
+ [InlineData(" ", "Foo")]
+ public void Should_Throw_If_MessageMarkdown_Is_Different(string expectedValue, string actualValue)
+ {
+ // Given
+ var fixture = new IssueCheckerFixture();
+ var issue =
+ fixture.IssueBuilder
+ .WithMessageInMarkdownFormat(actualValue)
+ .Create();
+
+ // When
+ var result = Record.Exception(() =>
+ IssueChecker.Check(
+ fixture.Issue,
+ fixture.ProviderType,
+ fixture.ProviderName,
+ fixture.ProjectFileRelativePath,
+ fixture.ProjectName,
+ fixture.AffectedFileRelativePath,
+ fixture.Line,
+ fixture.MessageText,
+ fixture.MessageHtml,
+ expectedValue,
+ fixture.Priority,
+ fixture.PriorityName,
+ fixture.Rule,
+ fixture.RuleUrl));
+
+ // Then
+ result.ShouldBeOfType();
+ result.Message.ShouldStartWith("Expected issue.MessageMarkdown");
}
[Theory]
@@ -429,7 +521,9 @@ public void Should_Throw_If_Priority_Is_Different(IssuePriority expectedValue, I
fixture.ProjectName,
fixture.AffectedFileRelativePath,
fixture.Line,
- fixture.Message,
+ fixture.MessageText,
+ fixture.MessageHtml,
+ fixture.MessageMarkdown,
(int)expectedValue,
fixture.PriorityName,
fixture.Rule,
@@ -464,7 +558,9 @@ public void Should_Throw_If_PriorityName_Is_Different(string expectedValue, stri
fixture.ProjectName,
fixture.AffectedFileRelativePath,
fixture.Line,
- fixture.Message,
+ fixture.MessageText,
+ fixture.MessageHtml,
+ fixture.MessageMarkdown,
fixture.Priority,
expectedValue,
fixture.Rule,
@@ -499,7 +595,9 @@ public void Should_Throw_If_Rule_Is_Different(string expectedValue, string actua
fixture.ProjectName,
fixture.AffectedFileRelativePath,
fixture.Line,
- fixture.Message,
+ fixture.MessageText,
+ fixture.MessageHtml,
+ fixture.MessageMarkdown,
fixture.Priority,
fixture.PriorityName,
expectedValue,
@@ -531,7 +629,9 @@ public void Should_Throw_If_RuleUrl_Is_Different(string expectedValue, string ac
fixture.ProjectName,
fixture.AffectedFileRelativePath,
fixture.Line,
- fixture.Message,
+ fixture.MessageText,
+ fixture.MessageHtml,
+ fixture.MessageMarkdown,
fixture.Priority,
fixture.PriorityName,
fixture.Rule,
diff --git a/src/Cake.Issues.sln b/src/Cake.Issues.sln
index 8b6a67117..12fdc0efa 100644
--- a/src/Cake.Issues.sln
+++ b/src/Cake.Issues.sln
@@ -9,7 +9,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cake.Issues.Tests", "Cake.I
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{12963AB7-D907-4D27-B1F0-8C77A55BD2F2}"
ProjectSection(SolutionItems) = preProject
- ..\setup.cake = ..\setup.cake
+ ..\recipe.cake = ..\recipe.cake
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "nuspec", "nuspec", "{C9E29268-658F-4887-95C3-99C48F9A2DAD}"
diff --git a/src/Cake.Issues/Aliases.IssueSerialization.cs b/src/Cake.Issues/Aliases.IssueSerialization.cs
index 56959cff3..c1422b39d 100644
--- a/src/Cake.Issues/Aliases.IssueSerialization.cs
+++ b/src/Cake.Issues/Aliases.IssueSerialization.cs
@@ -4,6 +4,7 @@
using Cake.Core;
using Cake.Core.Annotations;
using Cake.Core.IO;
+ using Cake.Issues.Serialization;
///
/// Contains functionality related to serializing and deserializing issues.
diff --git a/src/Cake.Issues/Aliases.ReadIssues.cs b/src/Cake.Issues/Aliases.ReadIssues.cs
index cb302213c..1abb5a8d6 100644
--- a/src/Cake.Issues/Aliases.ReadIssues.cs
+++ b/src/Cake.Issues/Aliases.ReadIssues.cs
@@ -182,7 +182,7 @@ public static IEnumerable ReadIssues(
var issuesReader =
new IssuesReader(context.Log, issueProviders, settings);
- return issuesReader.ReadIssues(settings.Format);
+ return issuesReader.ReadIssues();
}
}
}
diff --git a/src/Cake.Issues/BaseIssueProvider.cs b/src/Cake.Issues/BaseIssueProvider.cs
index 198821f40..e3eeb928b 100644
--- a/src/Cake.Issues/BaseIssueProvider.cs
+++ b/src/Cake.Issues/BaseIssueProvider.cs
@@ -21,19 +21,18 @@ protected BaseIssueProvider(ICakeLog log)
public abstract string ProviderName { get; }
///
- public IEnumerable ReadIssues(IssueCommentFormat format)
+ public IEnumerable ReadIssues()
{
this.AssertInitialized();
- return this.InternalReadIssues(format);
+ return this.InternalReadIssues();
}
///
/// Gets all issues.
/// Compared to it is safe to access Settings from this method.
///
- /// Preferred format of the comments.
/// List of issues.
- protected abstract IEnumerable InternalReadIssues(IssueCommentFormat format);
+ protected abstract IEnumerable InternalReadIssues();
}
}
diff --git a/src/Cake.Issues/BaseLogFileFormat.cs b/src/Cake.Issues/BaseLogFileFormat.cs
index 0e51dbc6a..facf44245 100644
--- a/src/Cake.Issues/BaseLogFileFormat.cs
+++ b/src/Cake.Issues/BaseLogFileFormat.cs
@@ -31,7 +31,6 @@ protected BaseLogFileFormat(ICakeLog log)
///
public abstract IEnumerable ReadIssues(
TIssueProvider issueProvider,
- IssueCommentFormat format,
RepositorySettings repositorySettings,
TSettings issueProviderSettings);
}
diff --git a/src/Cake.Issues/BaseMultiFormatIssueProvider.cs b/src/Cake.Issues/BaseMultiFormatIssueProvider.cs
index 4b40c25d8..92ebb7042 100644
--- a/src/Cake.Issues/BaseMultiFormatIssueProvider.cs
+++ b/src/Cake.Issues/BaseMultiFormatIssueProvider.cs
@@ -23,12 +23,11 @@ protected BaseMultiFormatIssueProvider(ICakeLog log, TSettings settings)
}
///
- protected override IEnumerable InternalReadIssues(IssueCommentFormat format)
+ protected override IEnumerable InternalReadIssues()
{
return
this.IssueProviderSettings.Format.ReadIssues(
(TIssueProvider)this,
- format,
this.Settings,
this.IssueProviderSettings);
}
diff --git a/src/Cake.Issues/Cake.Issues.csproj b/src/Cake.Issues/Cake.Issues.csproj
index d4003de5f..294cf68fc 100644
--- a/src/Cake.Issues/Cake.Issues.csproj
+++ b/src/Cake.Issues/Cake.Issues.csproj
@@ -24,7 +24,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/Cake.Issues/IIssue.cs b/src/Cake.Issues/IIssue.cs
index 2394f725b..0a90ff793 100644
--- a/src/Cake.Issues/IIssue.cs
+++ b/src/Cake.Issues/IIssue.cs
@@ -35,9 +35,19 @@ public interface IIssue
int? Line { get; }
///
- /// Gets the message of the issue.
+ /// Gets the message of the issue in text format.
///
- string Message { get; }
+ string MessageText { get; }
+
+ ///
+ /// Gets the message of the issue in HTML format.
+ ///
+ string MessageHtml { get; }
+
+ ///
+ /// Gets the message of the issue in Markdown format.
+ ///
+ string MessageMarkdown { get; }
///
/// Gets the priority of the message. A higher value indicates a higher priority.
diff --git a/src/Cake.Issues/IIssueComparer.cs b/src/Cake.Issues/IIssueComparer.cs
new file mode 100644
index 000000000..d7367fba3
--- /dev/null
+++ b/src/Cake.Issues/IIssueComparer.cs
@@ -0,0 +1,135 @@
+namespace Cake.Issues
+{
+ using System.Collections.Generic;
+
+ ///
+ /// Comparer to compare if two issues are identical.
+ ///
+ public class IIssueComparer : IEqualityComparer
+ {
+ private readonly bool compareOnlyPersistentProperties;
+
+ ///
+ /// Initializes a new instance of the class.
+ /// Two issues are seen as identical if all properties have identical values.
+ ///
+ public IIssueComparer()
+ : this(false)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Flag indicating whether properties which
+ /// are affected by changes in files should be considered while comparing issues.
+ /// If set to true, the comparer can be used to compare issues from different
+ /// build runs, where files might have been changed or renamed.
+ ///
+ /// If is set to true the following
+ /// properties will be ignored while comparing the issue:
+ ///
+ /// -
+ ///
+ ///
+ /// -
+ ///
+ ///
+ /// -
+ ///
+ ///
+ ///
+ ///
+ public IIssueComparer(bool compareOnlyPersistentProperties)
+ {
+ this.compareOnlyPersistentProperties = compareOnlyPersistentProperties;
+ }
+
+ ///
+ public bool Equals(IIssue x, IIssue y)
+ {
+ if (object.ReferenceEquals(x, y))
+ {
+ return true;
+ }
+
+ if (x is null || y is null)
+ {
+ return false;
+ }
+
+ return
+ (this.compareOnlyPersistentProperties || x.ProjectFileRelativePath?.FullPath == y.ProjectFileRelativePath?.FullPath) &&
+ (x.ProjectName == y.ProjectName) &&
+ (this.compareOnlyPersistentProperties || x.AffectedFileRelativePath?.FullPath == y.AffectedFileRelativePath?.FullPath) &&
+ (this.compareOnlyPersistentProperties || x.Line == y.Line) &&
+ (x.MessageText == y.MessageText) &&
+ (x.MessageHtml == y.MessageHtml) &&
+ (x.MessageMarkdown == y.MessageMarkdown) &&
+ (x.Priority == y.Priority) &&
+ (x.PriorityName == y.PriorityName) &&
+ (x.Rule == y.Rule) &&
+ (x.RuleUrl?.ToString() == y.RuleUrl?.ToString()) &&
+ (x.ProviderType == y.ProviderType) &&
+ (x.ProviderName == y.ProviderName);
+ }
+
+ ///
+ public int GetHashCode(IIssue obj)
+ {
+ if (obj is null)
+ {
+ return 0;
+ }
+
+ if (this.compareOnlyPersistentProperties)
+ {
+ return
+ GetHashCode(
+ obj.ProjectName,
+ obj.MessageText,
+ obj.MessageHtml,
+ obj.MessageMarkdown,
+ obj.Priority,
+ obj.PriorityName,
+ obj.Rule,
+ obj.RuleUrl,
+ obj.ProviderType,
+ obj.ProviderName);
+ }
+ else
+ {
+ return
+ GetHashCode(
+ obj.ProjectFileRelativePath?.ToString(),
+ obj.ProjectName,
+ obj.AffectedFileRelativePath?.ToString(),
+ obj.Line,
+ obj.MessageText,
+ obj.MessageHtml,
+ obj.MessageMarkdown,
+ obj.Priority,
+ obj.PriorityName,
+ obj.Rule,
+ obj.RuleUrl,
+ obj.ProviderType,
+ obj.ProviderName);
+ }
+ }
+
+ private static int GetHashCode(params object[] objects)
+ {
+ unchecked
+ {
+ int hash = 17;
+
+ foreach (var obj in objects)
+ {
+ hash = (23 * hash) + (obj is object ? obj.GetHashCode() : 0);
+ }
+
+ return hash;
+ }
+ }
+ }
+}
diff --git a/src/Cake.Issues/IIssueExtensions.cs b/src/Cake.Issues/IIssueExtensions.cs
index eccddde38..4c3c604bc 100644
--- a/src/Cake.Issues/IIssueExtensions.cs
+++ b/src/Cake.Issues/IIssueExtensions.cs
@@ -1,10 +1,38 @@
namespace Cake.Issues
{
+ using System;
+
///
/// Extensions for .
///
public static class IIssueExtensions
{
+ ///
+ /// Gets the message of the issue in a specific format.
+ /// If the message is not available in the specific format, the message in
+ /// text format will be returned.
+ ///
+ /// Issue for which the message should be returned.
+ /// Format in which the message should be returned.
+ /// Message in the format specified by or message in text
+ /// format if it is not available in the desired format.
+ public static string Message(this IIssue issue, IssueCommentFormat format)
+ {
+ issue.NotNull(nameof(issue));
+
+ switch (format)
+ {
+ case IssueCommentFormat.PlainText:
+ return issue.MessageText;
+ case IssueCommentFormat.Html:
+ return !string.IsNullOrEmpty(issue.MessageHtml) ? issue.MessageHtml : issue.MessageText;
+ case IssueCommentFormat.Markdown:
+ return !string.IsNullOrEmpty(issue.MessageMarkdown) ? issue.MessageMarkdown : issue.MessageText;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(format));
+ }
+ }
+
///
/// Returns the full path of or null.
///
@@ -128,8 +156,18 @@ public static string FileName(this IIssue issue)
/// The value of .
///
/// -
- /// {Message}
- /// The value of .
+ /// {MessageText}
+ /// The value of .
+ ///
+ /// -
+ /// {MessageHtml}
+ /// The value of or
+ /// if message in HTML format is not available.
+ ///
+ /// -
+ /// {MessageMarkdown}
+ /// The value of or
+ /// if message in Markdown format is not available.
///
///
///
@@ -155,7 +193,9 @@ public static string ReplaceIssuePattern(this string pattern, IIssue issue)
.Replace("{Line}", issue.Line?.ToString())
.Replace("{Rule}", issue.Rule)
.Replace("{RuleUrl}", issue.RuleUrl?.ToString())
- .Replace("{Message}", issue.Message);
+ .Replace("{MessageText}", issue.Message(IssueCommentFormat.PlainText))
+ .Replace("{MessageHtml}", issue.Message(IssueCommentFormat.Html))
+ .Replace("{MessageMarkdown}", issue.Message(IssueCommentFormat.Markdown));
}
}
}
\ No newline at end of file
diff --git a/src/Cake.Issues/IIssueProvider.cs b/src/Cake.Issues/IIssueProvider.cs
index 832a1e66b..dd3231b46 100644
--- a/src/Cake.Issues/IIssueProvider.cs
+++ b/src/Cake.Issues/IIssueProvider.cs
@@ -15,8 +15,7 @@ public interface IIssueProvider : IBaseIssueComponent
///
/// Gets all issues.
///
- /// Preferred format of the comments.
/// List of issues.
- IEnumerable ReadIssues(IssueCommentFormat format);
+ IEnumerable ReadIssues();
}
}
diff --git a/src/Cake.Issues/ILogFileFormat.cs b/src/Cake.Issues/ILogFileFormat.cs
index ca62fdcdd..457bc8f12 100644
--- a/src/Cake.Issues/ILogFileFormat.cs
+++ b/src/Cake.Issues/ILogFileFormat.cs
@@ -15,13 +15,11 @@ public interface ILogFileFormat
/// Gets all issues.
///
/// Issue provider instance.
- /// Preferred format for comments.
/// Repository settings to use.
/// Settings for issue provider to use.
/// List of issues.
IEnumerable ReadIssues(
TIssueProvider issueProvider,
- IssueCommentFormat format,
RepositorySettings repositorySettings,
TSettings issueProviderSettings);
}
diff --git a/src/Cake.Issues/Issue.cs b/src/Cake.Issues/Issue.cs
index c33cc31c2..e699c512b 100644
--- a/src/Cake.Issues/Issue.cs
+++ b/src/Cake.Issues/Issue.cs
@@ -21,7 +21,9 @@ public class Issue : IIssue
/// null or if issue is not related to a change in a file.
/// The line in the file where the issues has occurred.
/// null if the issue affects the whole file or an asssembly.
- /// The message of the issue.
+ /// The message of the issue in plain text format.
+ /// The message of the issue in Html format.
+ /// The message of the issue in Markdown format.
/// The priority of the message.
/// null if no priority was assigned.
/// The human friendly name of the priority.
@@ -37,7 +39,9 @@ public Issue(
string projectName,
string affectedFileRelativePath,
int? line,
- string message,
+ string messageText,
+ string messageHtml,
+ string messageMarkdown,
int? priority,
string priorityName,
string rule,
@@ -46,7 +50,7 @@ public Issue(
string providerName)
{
line?.NotNegativeOrZero(nameof(line));
- message.NotNullOrWhiteSpace(nameof(message));
+ messageText.NotNullOrWhiteSpace(nameof(messageText));
providerType.NotNullOrWhiteSpace(nameof(providerType));
providerName.NotNullOrWhiteSpace(nameof(providerName));
@@ -81,7 +85,7 @@ public Issue(
if (!this.AffectedFileRelativePath.IsRelative)
{
throw new ArgumentOutOfRangeException(
- nameof(affectedFileRelativePath),
+ nameof(affectedFileRelativePath),
$"File path '{this.AffectedFileRelativePath}' needs to be relative to the repository root.");
}
}
@@ -93,7 +97,9 @@ public Issue(
this.ProjectName = projectName;
this.Line = line;
- this.Message = message;
+ this.MessageText = messageText;
+ this.MessageHtml = messageHtml;
+ this.MessageMarkdown = messageMarkdown;
this.Priority = priority;
this.PriorityName = priorityName;
this.Rule = rule;
@@ -115,7 +121,13 @@ public Issue(
public int? Line { get; }
///
- public string Message { get; }
+ public string MessageText { get; }
+
+ ///
+ public string MessageHtml { get; }
+
+ ///
+ public string MessageMarkdown { get; }
///
public int? Priority { get; }
diff --git a/src/Cake.Issues/IssueBuilder.cs b/src/Cake.Issues/IssueBuilder.cs
index 0be1bf428..aee2041d6 100644
--- a/src/Cake.Issues/IssueBuilder.cs
+++ b/src/Cake.Issues/IssueBuilder.cs
@@ -7,9 +7,11 @@
///
public class IssueBuilder
{
- private readonly string message;
private readonly string providerType;
private readonly string providerName;
+ private readonly string messageText;
+ private string messageHtml;
+ private string messageMarkdown;
private string projectFileRelativePath;
private string projectName;
private string filePath;
@@ -22,7 +24,7 @@ public class IssueBuilder
///
/// Initializes a new instance of the class.
///
- /// The message of the issue.
+ /// The message of the issue in plain text format.
/// The type of the issue provider.
/// The human friendly name of the issue provider.
private IssueBuilder(
@@ -34,7 +36,7 @@ private IssueBuilder(
providerType.NotNullOrWhiteSpace(nameof(providerType));
providerName.NotNullOrWhiteSpace(nameof(providerName));
- this.message = message;
+ this.messageText = message;
this.providerType = providerType;
this.providerName = providerName;
}
@@ -42,7 +44,7 @@ private IssueBuilder(
///
/// Initiates the creation of a new .
///
- /// The message of the issue.
+ /// The message of the issue in plain text format.
/// The type of the issue provider.
/// The human friendly name of the issue provider.
/// Builder class for creating a new issue.
@@ -62,7 +64,7 @@ public static IssueBuilder NewIssue(
/// Initiates the creation of a new .
///
/// Type of the issue provider which has the issue created.
- /// The message of the issue.
+ /// The message of the issue in plain text format.
/// Issue provider which has the issue created.
/// Builder class for creating a new issue.
public static IssueBuilder NewIssue(
@@ -80,6 +82,32 @@ public static IssueBuilder NewIssue(
return new IssueBuilder(message, typeof(T).FullName, issueProvider.ProviderName);
}
+ ///
+ /// Sets the message in HTML format.
+ ///
+ /// Message in HTML format.
+ /// Can be null or if issue doesn't have a message in HTML format.
+ /// Issue Builder instance.
+ public IssueBuilder WithMessageInHtmlFormat(string message)
+ {
+ this.messageHtml = message;
+
+ return this;
+ }
+
+ ///
+ /// Sets the message in Markdown format.
+ ///
+ /// Message in Markdown format.
+ /// Can be null or if issue doesn't have a message in Markdown format.
+ /// Issue Builder instance.
+ public IssueBuilder WithMessageInMarkdownFormat(string message)
+ {
+ this.messageMarkdown = message;
+
+ return this;
+ }
+
///
/// Sets the path of the project to which the file affected by the issue belongs.
///
@@ -224,7 +252,9 @@ public IIssue Create()
this.projectName,
this.filePath,
this.line,
- this.message,
+ this.messageText,
+ this.messageHtml,
+ this.messageMarkdown,
this.priority,
this.priorityName,
this.rule,
diff --git a/src/Cake.Issues/IssueSerializationExtensions.cs b/src/Cake.Issues/IssueSerializationExtensions.cs
deleted file mode 100644
index 3a6a9e6d5..000000000
--- a/src/Cake.Issues/IssueSerializationExtensions.cs
+++ /dev/null
@@ -1,226 +0,0 @@
-namespace Cake.Issues
-{
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Runtime.Serialization.Json;
- using System.Text;
- using Cake.Core.IO;
-
- ///
- /// Extensions for serializing and deserializing an .
- ///
- internal static class IssueSerializationExtensions
- {
- ///
- /// Serializes an to a JSON string.
- ///
- /// Issue which should be serialized.
- /// Serialized issue.
- public static string SerializeToJsonString(this IIssue issue)
- {
- issue.NotNull(nameof(issue));
-
- var serializer = new DataContractJsonSerializer(typeof(SerializableIssue));
-
- using (var stream = new MemoryStream())
- {
- serializer.WriteObject(stream, issue.ToSerializableIssue());
- return Encoding.UTF8.GetString(stream.ToArray());
- }
- }
-
- ///
- /// Serializes an to a JSON string.
- ///
- /// Issues which should be serialized.
- /// Serialized issues.
- public static string SerializeToJsonString(this IEnumerable issues)
- {
- issues.NotNull(nameof(issues));
-
- var serializer = new DataContractJsonSerializer(typeof(IEnumerable));
-
- using (var stream = new MemoryStream())
- {
- serializer.WriteObject(stream, issues.Select(x => x.ToSerializableIssue()));
- return Encoding.UTF8.GetString(stream.ToArray());
- }
- }
-
- ///
- /// Serializes an to a JSON file.
- ///
- /// Issue which should be serialized.
- /// Path to the file.
- public static void SerializeToJsonFile(this IIssue issue, FilePath filePath)
- {
- issue.NotNull(nameof(issue));
- filePath.NotNull(nameof(filePath));
-
- var serializer = new DataContractJsonSerializer(typeof(SerializableIssue));
-
- using (var stream = File.Open(filePath.FullPath, FileMode.Create))
- {
- serializer.WriteObject(stream, issue.ToSerializableIssue());
- }
- }
-
- ///
- /// Serializes an to a JSON file.
- ///
- /// Issues which should be serialized.
- /// Path to the file.
- public static void SerializeToJsonFile(this IEnumerable issues, FilePath filePath)
- {
- issues.NotNull(nameof(issues));
- filePath.NotNull(nameof(filePath));
-
- var serializer = new DataContractJsonSerializer(typeof(IEnumerable));
-
- using (var stream = File.Open(filePath.FullPath, FileMode.Create))
- {
- serializer.WriteObject(stream, issues.Select(x => x.ToSerializableIssue()));
- }
- }
-
- ///
- /// Deserializes an from a JSON string.
- ///
- /// JSON representation of the issue.
- /// Instance of the issue.
- public static Issue DeserializeToIssue(this string jsonString)
- {
- jsonString.NotNullOrWhiteSpace(nameof(jsonString));
-
- using (var stream = new MemoryStream(Encoding.Default.GetBytes(jsonString)))
- {
- return DeserializeStreamToIssue(stream);
- }
- }
-
- ///
- /// Deserializes an from a JSON string.
- ///
- /// JSON representation of the issues.
- /// List of issues.
- public static IEnumerable DeserializeToIssues(this string jsonString)
- {
- jsonString.NotNullOrWhiteSpace(nameof(jsonString));
-
- using (var stream = new MemoryStream(Encoding.Default.GetBytes(jsonString)))
- {
- return DeserializeStreamToIssues(stream);
- }
- }
-
- ///
- /// Deserializes an from a JSON file.
- ///
- /// Path to the JSON file.
- /// Instance of the issue.
- public static Issue DeserializeToIssue(this FilePath filePath)
- {
- filePath.NotNull(nameof(filePath));
-
- using (var stream = File.Open(filePath.FullPath, FileMode.Open))
- {
- return DeserializeStreamToIssue(stream);
- }
- }
-
- ///
- /// Deserializes an from a JSON file.
- ///
- /// Path to the JSON file.
- /// List of issues.
- public static IEnumerable DeserializeToIssues(this FilePath filePath)
- {
- filePath.NotNull(nameof(filePath));
-
- using (var stream = File.Open(filePath.FullPath, FileMode.Open))
- {
- return DeserializeStreamToIssues(stream);
- }
- }
-
- ///
- /// Converts an to a .
- ///
- /// Issue which should be converted.
- /// Converted issue.
- internal static SerializableIssue ToSerializableIssue(this IIssue issue)
- {
- issue.NotNull(nameof(issue));
-
- return new SerializableIssue
- {
- ProjectFileRelativePath = issue.ProjectFileRelativePath?.FullPath,
- ProjectName = issue.ProjectName,
- AffectedFileRelativePath = issue.AffectedFileRelativePath?.FullPath,
- Line = issue.Line,
- Message = issue.Message,
- Priority = issue.Priority,
- PriorityName = issue.PriorityName,
- Rule = issue.Rule,
- RuleUrl = issue.RuleUrl?.ToString(),
- ProviderType = issue.ProviderType,
- ProviderName = issue.ProviderName,
- };
- }
-
- ///
- /// Converts a to an .
- ///
- /// Issue which should be converted.
- /// Converted issue.
- internal static Issue ToIssue(this SerializableIssue serializableIssue)
- {
- serializableIssue.NotNull(nameof(serializableIssue));
-
- Uri ruleUrl = null;
- if (!string.IsNullOrWhiteSpace(serializableIssue.RuleUrl))
- {
- ruleUrl = new Uri(serializableIssue.RuleUrl);
- }
-
- return new Issue(
- serializableIssue.ProjectFileRelativePath,
- serializableIssue.ProjectName,
- serializableIssue.AffectedFileRelativePath,
- serializableIssue.Line,
- serializableIssue.Message,
- serializableIssue.Priority,
- serializableIssue.PriorityName,
- serializableIssue.Rule,
- ruleUrl,
- serializableIssue.ProviderType,
- serializableIssue.ProviderName);
- }
-
- private static Issue DeserializeStreamToIssue(Stream stream)
- {
- var serializer = new DataContractJsonSerializer(typeof(SerializableIssue));
-
- if (!(serializer.ReadObject(stream) is SerializableIssue deserializedIssue))
- {
- return null;
- }
-
- return deserializedIssue.ToIssue();
- }
-
- private static IEnumerable DeserializeStreamToIssues(Stream stream)
- {
- var serializer = new DataContractJsonSerializer(typeof(IEnumerable));
-
- if (!(serializer.ReadObject(stream) is IEnumerable deserializedIssues))
- {
- return new List();
- }
-
- return deserializedIssues.Select(x => x.ToIssue());
- }
- }
-}
diff --git a/src/Cake.Issues/IssuesReader.cs b/src/Cake.Issues/IssuesReader.cs
index 2eacfe2e2..7751cbc34 100644
--- a/src/Cake.Issues/IssuesReader.cs
+++ b/src/Cake.Issues/IssuesReader.cs
@@ -40,9 +40,8 @@ public IssuesReader(
///
/// Read issues from issue providers.
///
- /// Preferred format for comments.
/// List of issues.
- public IEnumerable ReadIssues(IssueCommentFormat format)
+ public IEnumerable ReadIssues()
{
// Initialize issue providers and read issues.
var issues = new List();
@@ -53,7 +52,7 @@ public IEnumerable ReadIssues(IssueCommentFormat format)
if (issueProvider.Initialize(this.settings))
{
this.log.Verbose("Reading issues from {0}...", providerName);
- var currentIssues = issueProvider.ReadIssues(format).ToList();
+ var currentIssues = issueProvider.ReadIssues().ToList();
this.log.Verbose(
"Found {0} issues using issue provider {1}...",
diff --git a/src/Cake.Issues/ReadIssuesSettings.cs b/src/Cake.Issues/ReadIssuesSettings.cs
index d12003994..d3c52dcec 100644
--- a/src/Cake.Issues/ReadIssuesSettings.cs
+++ b/src/Cake.Issues/ReadIssuesSettings.cs
@@ -15,10 +15,5 @@ public ReadIssuesSettings(DirectoryPath repositoryRoot)
: base(repositoryRoot)
{
}
-
- ///
- /// Gets or sets the preferred format in which issue comments should be returned.
- ///
- public IssueCommentFormat Format { get; set; } = IssueCommentFormat.Undefined;
}
}
diff --git a/src/Cake.Issues/Serialization/IssueDeserializationExtensions.cs b/src/Cake.Issues/Serialization/IssueDeserializationExtensions.cs
new file mode 100644
index 000000000..49b3ef740
--- /dev/null
+++ b/src/Cake.Issues/Serialization/IssueDeserializationExtensions.cs
@@ -0,0 +1,141 @@
+namespace Cake.Issues.Serialization
+{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Text;
+ using Cake.Core.IO;
+ using LitJson;
+
+ ///
+ /// Extensions for deserializing an .
+ ///
+ internal static class IssueDeserializationExtensions
+ {
+ ///
+ /// Deserializes an from a JSON string.
+ ///
+ /// JSON representation of the issue.
+ /// Instance of the issue.
+ public static Issue DeserializeToIssue(this string jsonString)
+ {
+ jsonString.NotNullOrWhiteSpace(nameof(jsonString));
+
+ using (var stream = new MemoryStream(Encoding.Default.GetBytes(jsonString)))
+ {
+ return DeserializeStreamToIssue(stream);
+ }
+ }
+
+ ///
+ /// Deserializes an from a JSON string.
+ ///
+ /// JSON representation of the issues.
+ /// List of issues.
+ public static IEnumerable DeserializeToIssues(this string jsonString)
+ {
+ jsonString.NotNullOrWhiteSpace(nameof(jsonString));
+
+ using (var stream = new MemoryStream(Encoding.Default.GetBytes(jsonString)))
+ {
+ return DeserializeStreamToIssues(stream);
+ }
+ }
+
+ ///
+ /// Deserializes an from a JSON file.
+ ///
+ /// Path to the JSON file.
+ /// Instance of the issue.
+ public static Issue DeserializeToIssue(this FilePath filePath)
+ {
+ filePath.NotNull(nameof(filePath));
+
+ using (var stream = File.Open(filePath.FullPath, FileMode.Open))
+ {
+ return DeserializeStreamToIssue(stream);
+ }
+ }
+
+ ///
+ /// Deserializes an from a JSON file.
+ ///
+ /// Path to the JSON file.
+ /// List of issues.
+ public static IEnumerable DeserializeToIssues(this FilePath filePath)
+ {
+ filePath.NotNull(nameof(filePath));
+
+ using (var stream = File.Open(filePath.FullPath, FileMode.Open))
+ {
+ return DeserializeStreamToIssues(stream);
+ }
+ }
+
+ ///
+ /// Deserializes a stream containing the JSON representation of an issue to an .
+ ///
+ /// Stream whose content should be deserialized.
+ /// Issue instance.
+ private static Issue DeserializeStreamToIssue(Stream stream)
+ {
+ using (var reader = new StreamReader(stream))
+ {
+ var jsonContent = reader.ReadToEnd();
+
+ var data = JsonMapper.ToObject(jsonContent);
+
+ return DeserializeJsonDataToIssue(data);
+ }
+ }
+
+ ///
+ /// Deserializes a stream containing the JSON representation of an array of issues to an .
+ ///
+ /// Stream whose content should be deserialized.
+ /// List of issues.
+ private static IEnumerable DeserializeStreamToIssues(Stream stream)
+ {
+ using (var reader = new StreamReader(stream))
+ {
+ var jsonContent = reader.ReadToEnd();
+
+ var data = JsonMapper.ToObject(jsonContent);
+ var issues = new List();
+ foreach (JsonData element in data)
+ {
+ issues.Add(DeserializeJsonDataToIssue(element));
+ }
+
+ return issues;
+ }
+ }
+
+ ///
+ /// Deserializes JSON repesentation of an issue to an .
+ /// Supports serialization format of the current version of Cake.Issues as versions
+ /// written with previous versions of Cake.Issues.
+ ///
+ /// JSON representation of the issue.
+ /// Issue instance.
+ private static Issue DeserializeJsonDataToIssue(JsonData data)
+ {
+ if (data.ContainsKey("Version"))
+ {
+ var version = (int)data["Version"];
+ switch (version)
+ {
+ case 2:
+ return JsonMapper.ToObject(data.ToJson()).ToIssue();
+ default:
+ throw new Exception($"Not supported issue serialization format {version}");
+ }
+ }
+ else
+ {
+ // If no version is available deserialize to original format.
+ return JsonMapper.ToObject(data.ToJson()).ToIssue();
+ }
+ }
+ }
+}
diff --git a/src/Cake.Issues/Serialization/IssueSerializationExtensions.cs b/src/Cake.Issues/Serialization/IssueSerializationExtensions.cs
new file mode 100644
index 000000000..c107779ec
--- /dev/null
+++ b/src/Cake.Issues/Serialization/IssueSerializationExtensions.cs
@@ -0,0 +1,99 @@
+namespace Cake.Issues.Serialization
+{
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Linq;
+ using Cake.Core.IO;
+ using LitJson;
+
+ ///
+ /// Extensions for serializing an to the latest serialization format.
+ ///
+ internal static class IssueSerializationExtensions
+ {
+ ///
+ /// Serializes an to a JSON string.
+ ///
+ /// Issue which should be serialized.
+ /// Serialized issue.
+ public static string SerializeToJsonString(this IIssue issue)
+ {
+ issue.NotNull(nameof(issue));
+
+ return JsonMapper.ToJson(issue.ToSerializableIssue());
+ }
+
+ ///
+ /// Serializes an to a JSON string.
+ ///
+ /// Issues which should be serialized.
+ /// Serialized issues.
+ public static string SerializeToJsonString(this IEnumerable issues)
+ {
+ issues.NotNull(nameof(issues));
+
+ return JsonMapper.ToJson(issues.Select(x => x.ToSerializableIssue()).ToArray());
+ }
+
+ ///
+ /// Serializes an to a JSON file.
+ ///
+ /// Issue which should be serialized.
+ /// Path to the file.
+ public static void SerializeToJsonFile(this IIssue issue, FilePath filePath)
+ {
+ issue.NotNull(nameof(issue));
+ filePath.NotNull(nameof(filePath));
+
+ using (var stream = File.Open(filePath.FullPath, FileMode.Create))
+ using (var writer = new StreamWriter(stream))
+ {
+ JsonMapper.ToJson(issue.ToSerializableIssue(), new JsonWriter(writer));
+ }
+ }
+
+ ///
+ /// Serializes an to a JSON file.
+ ///
+ /// Issues which should be serialized.
+ /// Path to the file.
+ public static void SerializeToJsonFile(this IEnumerable issues, FilePath filePath)
+ {
+ issues.NotNull(nameof(issues));
+ filePath.NotNull(nameof(filePath));
+
+ using (var stream = File.Open(filePath.FullPath, FileMode.Create))
+ using (var writer = new StreamWriter(stream))
+ {
+ JsonMapper.ToJson(issues.Select(x => x.ToSerializableIssue()).ToArray(), new JsonWriter(writer));
+ }
+ }
+
+ ///
+ /// Converts an to a .
+ ///
+ /// Issue which should be converted.
+ /// Converted issue.
+ internal static SerializableIssueV2 ToSerializableIssue(this IIssue issue)
+ {
+ issue.NotNull(nameof(issue));
+
+ return new SerializableIssueV2
+ {
+ ProjectFileRelativePath = issue.ProjectFileRelativePath?.FullPath,
+ ProjectName = issue.ProjectName,
+ AffectedFileRelativePath = issue.AffectedFileRelativePath?.FullPath,
+ Line = issue.Line,
+ MessageText = issue.MessageText,
+ MessageMarkdown = issue.MessageMarkdown,
+ MessageHtml = issue.MessageHtml,
+ Priority = issue.Priority,
+ PriorityName = issue.PriorityName,
+ Rule = issue.Rule,
+ RuleUrl = issue.RuleUrl?.ToString(),
+ ProviderType = issue.ProviderType,
+ ProviderName = issue.ProviderName,
+ };
+ }
+ }
+}
diff --git a/src/Cake.Issues/Serialization/LitJson/IJsonWrapper.cs b/src/Cake.Issues/Serialization/LitJson/IJsonWrapper.cs
new file mode 100644
index 000000000..34b2b820d
--- /dev/null
+++ b/src/Cake.Issues/Serialization/LitJson/IJsonWrapper.cs
@@ -0,0 +1,66 @@
+#pragma warning disable 1587
+#pragma warning disable 1591
+
+#region Header
+/**
+ * IJsonWrapper.cs
+ * Interface that represents a type capable of handling all kinds of JSON
+ * data. This is mainly used when mapping objects through JsonMapper, and
+ * it's implemented by JsonData.
+ *
+ * The authors disclaim copyright to this source code. For more details, see
+ * the 3rd-Party-License.md file included with this distribution.
+ **/
+
+// This file isn't generated, but this comment is necessary to exclude it from code analysis.
+//
+#endregion
+
+
+using System.Collections;
+using System.Collections.Specialized;
+
+
+namespace LitJson
+{
+ internal enum JsonType
+ {
+ None,
+
+ Object,
+ Array,
+ String,
+ Int,
+ Long,
+ Double,
+ Boolean
+ }
+
+ internal interface IJsonWrapper : IList, IOrderedDictionary
+ {
+ bool IsArray { get; }
+ bool IsBoolean { get; }
+ bool IsDouble { get; }
+ bool IsInt { get; }
+ bool IsLong { get; }
+ bool IsObject { get; }
+ bool IsString { get; }
+
+ bool GetBoolean ();
+ double GetDouble ();
+ int GetInt ();
+ JsonType GetJsonType ();
+ long GetLong ();
+ string GetString ();
+
+ void SetBoolean (bool val);
+ void SetDouble (double val);
+ void SetInt (int val);
+ void SetJsonType (JsonType type);
+ void SetLong (long val);
+ void SetString (string val);
+
+ string ToJson ();
+ void ToJson (JsonWriter writer);
+ }
+}
diff --git a/src/Cake.Issues/Serialization/LitJson/JsonData.cs b/src/Cake.Issues/Serialization/LitJson/JsonData.cs
new file mode 100644
index 000000000..d595bfc2e
--- /dev/null
+++ b/src/Cake.Issues/Serialization/LitJson/JsonData.cs
@@ -0,0 +1,1065 @@
+#pragma warning disable 1587
+#pragma warning disable 1591
+
+#region Header
+/**
+ * JsonData.cs
+ * Generic type to hold JSON data (objects, arrays, and so on). This is
+ * the default type returned by JsonMapper.ToObject().
+ *
+ * The authors disclaim copyright to this source code. For more details, see
+ * the 3rd-Party-License.md file included with this distribution.
+ **/
+
+// This file isn't generated, but this comment is necessary to exclude it from code analysis.
+//
+#endregion
+
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.IO;
+
+
+namespace LitJson
+{
+ internal class JsonData : IJsonWrapper, IEquatable
+ {
+ #region Fields
+ private IList inst_array;
+ private bool inst_boolean;
+ private double inst_double;
+ private int inst_int;
+ private long inst_long;
+ private IDictionary inst_object;
+ private string inst_string;
+ private string json;
+ private JsonType type;
+
+ // Used to implement the IOrderedDictionary interface
+ private IList> object_list;
+ #endregion
+
+
+ #region Properties
+ public int Count {
+ get { return EnsureCollection ().Count; }
+ }
+
+ public bool IsArray {
+ get { return type == JsonType.Array; }
+ }
+
+ public bool IsBoolean {
+ get { return type == JsonType.Boolean; }
+ }
+
+ public bool IsDouble {
+ get { return type == JsonType.Double; }
+ }
+
+ public bool IsInt {
+ get { return type == JsonType.Int; }
+ }
+
+ public bool IsLong {
+ get { return type == JsonType.Long; }
+ }
+
+ public bool IsObject {
+ get { return type == JsonType.Object; }
+ }
+
+ public bool IsString {
+ get { return type == JsonType.String; }
+ }
+
+ public ICollection Keys {
+ get { EnsureDictionary (); return inst_object.Keys; }
+ }
+
+ ///
+ /// Determines whether the json contains an element that has the specified key.
+ ///
+ /// The key to locate in the json.
+ /// true if the json contains an element that has the specified key; otherwise, false.
+ public Boolean ContainsKey(String key) {
+ EnsureDictionary();
+ return this.inst_object.Keys.Contains(key);
+ }
+ #endregion
+
+
+ #region ICollection Properties
+ int ICollection.Count {
+ get {
+ return Count;
+ }
+ }
+
+ bool ICollection.IsSynchronized {
+ get {
+ return EnsureCollection ().IsSynchronized;
+ }
+ }
+
+ object ICollection.SyncRoot {
+ get {
+ return EnsureCollection ().SyncRoot;
+ }
+ }
+ #endregion
+
+
+ #region IDictionary Properties
+ bool IDictionary.IsFixedSize {
+ get {
+ return EnsureDictionary ().IsFixedSize;
+ }
+ }
+
+ bool IDictionary.IsReadOnly {
+ get {
+ return EnsureDictionary ().IsReadOnly;
+ }
+ }
+
+ ICollection IDictionary.Keys {
+ get {
+ EnsureDictionary ();
+ IList keys = new List ();
+
+ foreach (KeyValuePair entry in
+ object_list) {
+ keys.Add (entry.Key);
+ }
+
+ return (ICollection) keys;
+ }
+ }
+
+ ICollection IDictionary.Values {
+ get {
+ EnsureDictionary ();
+ IList values = new List ();
+
+ foreach (KeyValuePair entry in
+ object_list) {
+ values.Add (entry.Value);
+ }
+
+ return (ICollection) values;
+ }
+ }
+ #endregion
+
+
+
+ #region IJsonWrapper Properties
+ bool IJsonWrapper.IsArray {
+ get { return IsArray; }
+ }
+
+ bool IJsonWrapper.IsBoolean {
+ get { return IsBoolean; }
+ }
+
+ bool IJsonWrapper.IsDouble {
+ get { return IsDouble; }
+ }
+
+ bool IJsonWrapper.IsInt {
+ get { return IsInt; }
+ }
+
+ bool IJsonWrapper.IsLong {
+ get { return IsLong; }
+ }
+
+ bool IJsonWrapper.IsObject {
+ get { return IsObject; }
+ }
+
+ bool IJsonWrapper.IsString {
+ get { return IsString; }
+ }
+ #endregion
+
+
+ #region IList Properties
+ bool IList.IsFixedSize {
+ get {
+ return EnsureList ().IsFixedSize;
+ }
+ }
+
+ bool IList.IsReadOnly {
+ get {
+ return EnsureList ().IsReadOnly;
+ }
+ }
+ #endregion
+
+
+ #region IDictionary Indexer
+ object IDictionary.this[object key] {
+ get {
+ return EnsureDictionary ()[key];
+ }
+
+ set {
+ if (! (key is String))
+ throw new ArgumentException (
+ "The key has to be a string");
+
+ JsonData data = ToJsonData (value);
+
+ this[(string) key] = data;
+ }
+ }
+ #endregion
+
+
+ #region IOrderedDictionary Indexer
+ object IOrderedDictionary.this[int idx] {
+ get {
+ EnsureDictionary ();
+ return object_list[idx].Value;
+ }
+
+ set {
+ EnsureDictionary ();
+ JsonData data = ToJsonData (value);
+
+ KeyValuePair old_entry = object_list[idx];
+
+ inst_object[old_entry.Key] = data;
+
+ KeyValuePair entry =
+ new KeyValuePair (old_entry.Key, data);
+
+ object_list[idx] = entry;
+ }
+ }
+ #endregion
+
+
+ #region IList Indexer
+ object IList.this[int index] {
+ get {
+ return EnsureList ()[index];
+ }
+
+ set {
+ EnsureList ();
+ JsonData data = ToJsonData (value);
+
+ this[index] = data;
+ }
+ }
+ #endregion
+
+
+ #region Public Indexers
+ public JsonData this[string prop_name] {
+ get {
+ EnsureDictionary ();
+ return inst_object[prop_name];
+ }
+
+ set {
+ EnsureDictionary ();
+
+ KeyValuePair entry =
+ new KeyValuePair (prop_name, value);
+
+ if (inst_object.ContainsKey (prop_name)) {
+ for (int i = 0; i < object_list.Count; i++) {
+ if (object_list[i].Key == prop_name) {
+ object_list[i] = entry;
+ break;
+ }
+ }
+ } else
+ object_list.Add (entry);
+
+ inst_object[prop_name] = value;
+
+ json = null;
+ }
+ }
+
+ public JsonData this[int index] {
+ get {
+ EnsureCollection ();
+
+ if (type == JsonType.Array)
+ return inst_array[index];
+
+ return object_list[index].Value;
+ }
+
+ set {
+ EnsureCollection ();
+
+ if (type == JsonType.Array)
+ inst_array[index] = value;
+ else {
+ KeyValuePair entry = object_list[index];
+ KeyValuePair new_entry =
+ new KeyValuePair (entry.Key, value);
+
+ object_list[index] = new_entry;
+ inst_object[entry.Key] = value;
+ }
+
+ json = null;
+ }
+ }
+ #endregion
+
+
+ #region Constructors
+ public JsonData ()
+ {
+ }
+
+ public JsonData (bool boolean)
+ {
+ type = JsonType.Boolean;
+ inst_boolean = boolean;
+ }
+
+ public JsonData (double number)
+ {
+ type = JsonType.Double;
+ inst_double = number;
+ }
+
+ public JsonData (int number)
+ {
+ type = JsonType.Int;
+ inst_int = number;
+ }
+
+ public JsonData (long number)
+ {
+ type = JsonType.Long;
+ inst_long = number;
+ }
+
+ public JsonData (object obj)
+ {
+ if (obj is Boolean) {
+ type = JsonType.Boolean;
+ inst_boolean = (bool) obj;
+ return;
+ }
+
+ if (obj is Double) {
+ type = JsonType.Double;
+ inst_double = (double) obj;
+ return;
+ }
+
+ if (obj is Int32) {
+ type = JsonType.Int;
+ inst_int = (int) obj;
+ return;
+ }
+
+ if (obj is Int64) {
+ type = JsonType.Long;
+ inst_long = (long) obj;
+ return;
+ }
+
+ if (obj is String) {
+ type = JsonType.String;
+ inst_string = (string) obj;
+ return;
+ }
+
+ throw new ArgumentException (
+ "Unable to wrap the given object with JsonData");
+ }
+
+ public JsonData (string str)
+ {
+ type = JsonType.String;
+ inst_string = str;
+ }
+ #endregion
+
+
+ #region Implicit Conversions
+ public static implicit operator JsonData (Boolean data)
+ {
+ return new JsonData (data);
+ }
+
+ public static implicit operator JsonData (Double data)
+ {
+ return new JsonData (data);
+ }
+
+ public static implicit operator JsonData (Int32 data)
+ {
+ return new JsonData (data);
+ }
+
+ public static implicit operator JsonData (Int64 data)
+ {
+ return new JsonData (data);
+ }
+
+ public static implicit operator JsonData (String data)
+ {
+ return new JsonData (data);
+ }
+ #endregion
+
+
+ #region Explicit Conversions
+ public static explicit operator Boolean (JsonData data)
+ {
+ if (data.type != JsonType.Boolean)
+ throw new InvalidCastException (
+ "Instance of JsonData doesn't hold a double");
+
+ return data.inst_boolean;
+ }
+
+ public static explicit operator Double (JsonData data)
+ {
+ if (data.type != JsonType.Double)
+ throw new InvalidCastException (
+ "Instance of JsonData doesn't hold a double");
+
+ return data.inst_double;
+ }
+
+ public static explicit operator Int32(JsonData data)
+ {
+ if (data.type != JsonType.Int && data.type != JsonType.Long)
+ {
+ throw new InvalidCastException(
+ "Instance of JsonData doesn't hold an int");
+ }
+
+ // cast may truncate data... but that's up to the user to consider
+ return data.type == JsonType.Int ? data.inst_int : (int)data.inst_long;
+ }
+
+ public static explicit operator Int64(JsonData data)
+ {
+ if (data.type != JsonType.Long && data.type != JsonType.Int)
+ {
+ throw new InvalidCastException(
+ "Instance of JsonData doesn't hold a long");
+ }
+
+ return data.type == JsonType.Long ? data.inst_long : data.inst_int;
+ }
+
+ public static explicit operator String (JsonData data)
+ {
+ if (data.type != JsonType.String)
+ throw new InvalidCastException (
+ "Instance of JsonData doesn't hold a string");
+
+ return data.inst_string;
+ }
+ #endregion
+
+
+ #region ICollection Methods
+ void ICollection.CopyTo (Array array, int index)
+ {
+ EnsureCollection ().CopyTo (array, index);
+ }
+ #endregion
+
+
+ #region IDictionary Methods
+ void IDictionary.Add (object key, object value)
+ {
+ JsonData data = ToJsonData (value);
+
+ EnsureDictionary ().Add (key, data);
+
+ KeyValuePair entry =
+ new KeyValuePair ((string) key, data);
+ object_list.Add (entry);
+
+ json = null;
+ }
+
+ void IDictionary.Clear ()
+ {
+ EnsureDictionary ().Clear ();
+ object_list.Clear ();
+ json = null;
+ }
+
+ bool IDictionary.Contains (object key)
+ {
+ return EnsureDictionary ().Contains (key);
+ }
+
+ IDictionaryEnumerator IDictionary.GetEnumerator ()
+ {
+ return ((IOrderedDictionary) this).GetEnumerator ();
+ }
+
+ void IDictionary.Remove (object key)
+ {
+ EnsureDictionary ().Remove (key);
+
+ for (int i = 0; i < object_list.Count; i++) {
+ if (object_list[i].Key == (string) key) {
+ object_list.RemoveAt (i);
+ break;
+ }
+ }
+
+ json = null;
+ }
+ #endregion
+
+
+ #region IEnumerable Methods
+ IEnumerator IEnumerable.GetEnumerator ()
+ {
+ return EnsureCollection ().GetEnumerator ();
+ }
+ #endregion
+
+
+ #region IJsonWrapper Methods
+ bool IJsonWrapper.GetBoolean ()
+ {
+ if (type != JsonType.Boolean)
+ throw new InvalidOperationException (
+ "JsonData instance doesn't hold a boolean");
+
+ return inst_boolean;
+ }
+
+ double IJsonWrapper.GetDouble ()
+ {
+ if (type != JsonType.Double)
+ throw new InvalidOperationException (
+ "JsonData instance doesn't hold a double");
+
+ return inst_double;
+ }
+
+ int IJsonWrapper.GetInt ()
+ {
+ if (type != JsonType.Int)
+ throw new InvalidOperationException (
+ "JsonData instance doesn't hold an int");
+
+ return inst_int;
+ }
+
+ long IJsonWrapper.GetLong ()
+ {
+ if (type != JsonType.Long)
+ throw new InvalidOperationException (
+ "JsonData instance doesn't hold a long");
+
+ return inst_long;
+ }
+
+ string IJsonWrapper.GetString ()
+ {
+ if (type != JsonType.String)
+ throw new InvalidOperationException (
+ "JsonData instance doesn't hold a string");
+
+ return inst_string;
+ }
+
+ void IJsonWrapper.SetBoolean (bool val)
+ {
+ type = JsonType.Boolean;
+ inst_boolean = val;
+ json = null;
+ }
+
+ void IJsonWrapper.SetDouble (double val)
+ {
+ type = JsonType.Double;
+ inst_double = val;
+ json = null;
+ }
+
+ void IJsonWrapper.SetInt (int val)
+ {
+ type = JsonType.Int;
+ inst_int = val;
+ json = null;
+ }
+
+ void IJsonWrapper.SetLong (long val)
+ {
+ type = JsonType.Long;
+ inst_long = val;
+ json = null;
+ }
+
+ void IJsonWrapper.SetString (string val)
+ {
+ type = JsonType.String;
+ inst_string = val;
+ json = null;
+ }
+
+ string IJsonWrapper.ToJson ()
+ {
+ return ToJson ();
+ }
+
+ void IJsonWrapper.ToJson (JsonWriter writer)
+ {
+ ToJson (writer);
+ }
+ #endregion
+
+
+ #region IList Methods
+ int IList.Add (object value)
+ {
+ return Add (value);
+ }
+
+ void IList.Clear ()
+ {
+ EnsureList ().Clear ();
+ json = null;
+ }
+
+ bool IList.Contains (object value)
+ {
+ return EnsureList ().Contains (value);
+ }
+
+ int IList.IndexOf (object value)
+ {
+ return EnsureList ().IndexOf (value);
+ }
+
+ void IList.Insert (int index, object value)
+ {
+ EnsureList ().Insert (index, value);
+ json = null;
+ }
+
+ void IList.Remove (object value)
+ {
+ EnsureList ().Remove (value);
+ json = null;
+ }
+
+ void IList.RemoveAt (int index)
+ {
+ EnsureList ().RemoveAt (index);
+ json = null;
+ }
+ #endregion
+
+
+ #region IOrderedDictionary Methods
+ IDictionaryEnumerator IOrderedDictionary.GetEnumerator ()
+ {
+ EnsureDictionary ();
+
+ return new OrderedDictionaryEnumerator (
+ object_list.GetEnumerator ());
+ }
+
+ void IOrderedDictionary.Insert (int idx, object key, object value)
+ {
+ string property = (string) key;
+ JsonData data = ToJsonData (value);
+
+ this[property] = data;
+
+ KeyValuePair entry =
+ new KeyValuePair (property, data);
+
+ object_list.Insert (idx, entry);
+ }
+
+ void IOrderedDictionary.RemoveAt (int idx)
+ {
+ EnsureDictionary ();
+
+ inst_object.Remove (object_list[idx].Key);
+ object_list.RemoveAt (idx);
+ }
+ #endregion
+
+
+ #region Private Methods
+ private ICollection EnsureCollection ()
+ {
+ if (type == JsonType.Array)
+ return (ICollection) inst_array;
+
+ if (type == JsonType.Object)
+ return (ICollection) inst_object;
+
+ throw new InvalidOperationException (
+ "The JsonData instance has to be initialized first");
+ }
+
+ private IDictionary EnsureDictionary ()
+ {
+ if (type == JsonType.Object)
+ return (IDictionary) inst_object;
+
+ if (type != JsonType.None)
+ throw new InvalidOperationException (
+ "Instance of JsonData is not a dictionary");
+
+ type = JsonType.Object;
+ inst_object = new Dictionary ();
+ object_list = new List> ();
+
+ return (IDictionary) inst_object;
+ }
+
+ private IList EnsureList ()
+ {
+ if (type == JsonType.Array)
+ return (IList) inst_array;
+
+ if (type != JsonType.None)
+ throw new InvalidOperationException (
+ "Instance of JsonData is not a list");
+
+ type = JsonType.Array;
+ inst_array = new List ();
+
+ return (IList) inst_array;
+ }
+
+ private JsonData ToJsonData (object obj)
+ {
+ if (obj == null)
+ return null;
+
+ if (obj is JsonData)
+ return (JsonData) obj;
+
+ return new JsonData (obj);
+ }
+
+ private static void WriteJson (IJsonWrapper obj, JsonWriter writer)
+ {
+ if (obj == null) {
+ writer.Write (null);
+ return;
+ }
+
+ if (obj.IsString) {
+ writer.Write (obj.GetString ());
+ return;
+ }
+
+ if (obj.IsBoolean) {
+ writer.Write (obj.GetBoolean ());
+ return;
+ }
+
+ if (obj.IsDouble) {
+ writer.Write (obj.GetDouble ());
+ return;
+ }
+
+ if (obj.IsInt) {
+ writer.Write (obj.GetInt ());
+ return;
+ }
+
+ if (obj.IsLong) {
+ writer.Write (obj.GetLong ());
+ return;
+ }
+
+ if (obj.IsArray) {
+ writer.WriteArrayStart ();
+ foreach (object elem in (IList) obj)
+ WriteJson ((JsonData) elem, writer);
+ writer.WriteArrayEnd ();
+
+ return;
+ }
+
+ if (obj.IsObject) {
+ writer.WriteObjectStart ();
+
+ foreach (DictionaryEntry entry in ((IDictionary) obj)) {
+ writer.WritePropertyName ((string) entry.Key);
+ WriteJson ((JsonData) entry.Value, writer);
+ }
+ writer.WriteObjectEnd ();
+
+ return;
+ }
+ }
+ #endregion
+
+
+ public int Add (object value)
+ {
+ JsonData data = ToJsonData (value);
+
+ json = null;
+
+ return EnsureList ().Add (data);
+ }
+
+ public bool Remove(object obj)
+ {
+ json = null;
+ if(IsObject)
+ {
+ JsonData value = null;
+ if (inst_object.TryGetValue((string)obj, out value))
+ return inst_object.Remove((string)obj) && object_list.Remove(new KeyValuePair((string)obj, value));
+ else
+ throw new KeyNotFoundException("The specified key was not found in the JsonData object.");
+ }
+ if(IsArray)
+ {
+ return inst_array.Remove(ToJsonData(obj));
+ }
+ throw new InvalidOperationException (
+ "Instance of JsonData is not an object or a list.");
+ }
+
+ public void Clear ()
+ {
+ if (IsObject) {
+ ((IDictionary) this).Clear ();
+ return;
+ }
+
+ if (IsArray) {
+ ((IList) this).Clear ();
+ return;
+ }
+ }
+
+ public bool Equals (JsonData x)
+ {
+ if (x == null)
+ return false;
+
+ if (x.type != this.type)
+ {
+ // further check to see if this is a long to int comparison
+ if ((x.type != JsonType.Int && x.type != JsonType.Long)
+ || (this.type != JsonType.Int && this.type != JsonType.Long))
+ {
+ return false;
+ }
+ }
+
+ switch (this.type) {
+ case JsonType.None:
+ return true;
+
+ case JsonType.Object:
+ return this.inst_object.Equals (x.inst_object);
+
+ case JsonType.Array:
+ return this.inst_array.Equals (x.inst_array);
+
+ case JsonType.String:
+ return this.inst_string.Equals (x.inst_string);
+
+ case JsonType.Int:
+ {
+ if (x.IsLong)
+ {
+ if (x.inst_long < Int32.MinValue || x.inst_long > Int32.MaxValue)
+ return false;
+ return this.inst_int.Equals((int)x.inst_long);
+ }
+ return this.inst_int.Equals(x.inst_int);
+ }
+
+ case JsonType.Long:
+ {
+ if (x.IsInt)
+ {
+ if (this.inst_long < Int32.MinValue || this.inst_long > Int32.MaxValue)
+ return false;
+ return x.inst_int.Equals((int)this.inst_long);
+ }
+ return this.inst_long.Equals(x.inst_long);
+ }
+
+ case JsonType.Double:
+ return this.inst_double.Equals (x.inst_double);
+
+ case JsonType.Boolean:
+ return this.inst_boolean.Equals (x.inst_boolean);
+ }
+
+ return false;
+ }
+
+ public JsonType GetJsonType ()
+ {
+ return type;
+ }
+
+ public void SetJsonType (JsonType type)
+ {
+ if (this.type == type)
+ return;
+
+ switch (type) {
+ case JsonType.None:
+ break;
+
+ case JsonType.Object:
+ inst_object = new Dictionary ();
+ object_list = new List> ();
+ break;
+
+ case JsonType.Array:
+ inst_array = new List ();
+ break;
+
+ case JsonType.String:
+ inst_string = default (String);
+ break;
+
+ case JsonType.Int:
+ inst_int = default (Int32);
+ break;
+
+ case JsonType.Long:
+ inst_long = default (Int64);
+ break;
+
+ case JsonType.Double:
+ inst_double = default (Double);
+ break;
+
+ case JsonType.Boolean:
+ inst_boolean = default (Boolean);
+ break;
+ }
+
+ this.type = type;
+ }
+
+ public string ToJson ()
+ {
+ if (json != null)
+ return json;
+
+ StringWriter sw = new StringWriter ();
+ JsonWriter writer = new JsonWriter (sw);
+ writer.Validate = false;
+
+ WriteJson (this, writer);
+ json = sw.ToString ();
+
+ return json;
+ }
+
+ public void ToJson (JsonWriter writer)
+ {
+ bool old_validate = writer.Validate;
+
+ writer.Validate = false;
+
+ WriteJson (this, writer);
+
+ writer.Validate = old_validate;
+ }
+
+ public override string ToString ()
+ {
+ switch (type) {
+ case JsonType.Array:
+ return "JsonData array";
+
+ case JsonType.Boolean:
+ return inst_boolean.ToString ();
+
+ case JsonType.Double:
+ return inst_double.ToString ();
+
+ case JsonType.Int:
+ return inst_int.ToString ();
+
+ case JsonType.Long:
+ return inst_long.ToString ();
+
+ case JsonType.Object:
+ return "JsonData object";
+
+ case JsonType.String:
+ return inst_string;
+ }
+
+ return "Uninitialized JsonData";
+ }
+ }
+
+
+ internal class OrderedDictionaryEnumerator : IDictionaryEnumerator
+ {
+ IEnumerator> list_enumerator;
+
+
+ public object Current {
+ get { return Entry; }
+ }
+
+ public DictionaryEntry Entry {
+ get {
+ KeyValuePair curr = list_enumerator.Current;
+ return new DictionaryEntry (curr.Key, curr.Value);
+ }
+ }
+
+ public object Key {
+ get { return list_enumerator.Current.Key; }
+ }
+
+ public object Value {
+ get { return list_enumerator.Current.Value; }
+ }
+
+
+ public OrderedDictionaryEnumerator (
+ IEnumerator> enumerator)
+ {
+ list_enumerator = enumerator;
+ }
+
+
+ public bool MoveNext ()
+ {
+ return list_enumerator.MoveNext ();
+ }
+
+ public void Reset ()
+ {
+ list_enumerator.Reset ();
+ }
+ }
+}
diff --git a/src/Cake.Issues/Serialization/LitJson/JsonException.cs b/src/Cake.Issues/Serialization/LitJson/JsonException.cs
new file mode 100644
index 000000000..6353b6995
--- /dev/null
+++ b/src/Cake.Issues/Serialization/LitJson/JsonException.cs
@@ -0,0 +1,71 @@
+#pragma warning disable 1587
+#pragma warning disable 1591
+
+#region Header
+/**
+ * JsonException.cs
+ * Base class throwed by LitJSON when a parsing error occurs.
+ *
+ * The authors disclaim copyright to this source code. For more details, see
+ * the 3rd-Party-License.md file included with this distribution.
+ **/
+
+// This file isn't generated, but this comment is necessary to exclude it from code analysis.
+//
+#endregion
+
+
+using System;
+
+
+namespace LitJson
+{
+ internal class JsonException :
+#if NETSTANDARD1_5
+ Exception
+#else
+ ApplicationException
+#endif
+ {
+ public JsonException () : base ()
+ {
+ }
+
+ internal JsonException (ParserToken token) :
+ base (String.Format (
+ "Invalid token '{0}' in input string", token))
+ {
+ }
+
+ internal JsonException (ParserToken token,
+ Exception inner_exception) :
+ base (String.Format (
+ "Invalid token '{0}' in input string", token),
+ inner_exception)
+ {
+ }
+
+ internal JsonException (int c) :
+ base (String.Format (
+ "Invalid character '{0}' in input string", (char) c))
+ {
+ }
+
+ internal JsonException (int c, Exception inner_exception) :
+ base (String.Format (
+ "Invalid character '{0}' in input string", (char) c),
+ inner_exception)
+ {
+ }
+
+
+ public JsonException (string message) : base (message)
+ {
+ }
+
+ public JsonException (string message, Exception inner_exception) :
+ base (message, inner_exception)
+ {
+ }
+ }
+}
diff --git a/src/Cake.Issues/Serialization/LitJson/JsonMapper.cs b/src/Cake.Issues/Serialization/LitJson/JsonMapper.cs
new file mode 100644
index 000000000..d9dd42f3f
--- /dev/null
+++ b/src/Cake.Issues/Serialization/LitJson/JsonMapper.cs
@@ -0,0 +1,967 @@
+#pragma warning disable 1587
+#pragma warning disable 1591
+
+#region Header
+/**
+ * JsonMapper.cs
+ * JSON to .Net object and object to JSON conversions.
+ *
+ * The authors disclaim copyright to this source code. For more details, see
+ * the 3rd-Party-License.md file included with this distribution.
+ **/
+
+// This file isn't generated, but this comment is necessary to exclude it from code analysis.
+//
+#endregion
+
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+
+
+namespace LitJson
+{
+ internal struct PropertyMetadata
+ {
+ public MemberInfo Info;
+ public bool IsField;
+ public Type Type;
+ }
+
+
+ internal struct ArrayMetadata
+ {
+ private Type element_type;
+ private bool is_array;
+ private bool is_list;
+
+
+ public Type ElementType {
+ get {
+ if (element_type == null)
+ return typeof (JsonData);
+
+ return element_type;
+ }
+
+ set { element_type = value; }
+ }
+
+ public bool IsArray {
+ get { return is_array; }
+ set { is_array = value; }
+ }
+
+ public bool IsList {
+ get { return is_list; }
+ set { is_list = value; }
+ }
+ }
+
+
+ internal struct ObjectMetadata
+ {
+ private Type element_type;
+ private bool is_dictionary;
+
+ private IDictionary properties;
+
+
+ public Type ElementType {
+ get {
+ if (element_type == null)
+ return typeof (JsonData);
+
+ return element_type;
+ }
+
+ set { element_type = value; }
+ }
+
+ public bool IsDictionary {
+ get { return is_dictionary; }
+ set { is_dictionary = value; }
+ }
+
+ public IDictionary Properties {
+ get { return properties; }
+ set { properties = value; }
+ }
+ }
+
+
+ internal delegate void ExporterFunc (object obj, JsonWriter writer);
+ internal delegate void ExporterFunc (T obj, JsonWriter writer);
+
+ internal delegate object ImporterFunc (object input);
+ internal delegate TValue ImporterFunc (TJson input);
+
+ internal delegate IJsonWrapper WrapperFactory ();
+
+
+ internal class JsonMapper
+ {
+ #region Fields
+ private static readonly int max_nesting_depth;
+
+ private static readonly IFormatProvider datetime_format;
+
+ private static readonly IDictionary base_exporters_table;
+ private static readonly IDictionary custom_exporters_table;
+
+ private static readonly IDictionary> base_importers_table;
+ private static readonly IDictionary> custom_importers_table;
+
+ private static readonly IDictionary array_metadata;
+ private static readonly object array_metadata_lock = new Object ();
+
+ private static readonly IDictionary> conv_ops;
+ private static readonly object conv_ops_lock = new Object ();
+
+ private static readonly IDictionary object_metadata;
+ private static readonly object object_metadata_lock = new Object ();
+
+ private static readonly IDictionary> type_properties;
+ private static readonly object type_properties_lock = new Object ();
+
+ private static readonly JsonWriter static_writer;
+ private static readonly object static_writer_lock = new Object ();
+ #endregion
+
+
+ #region Constructors
+ static JsonMapper ()
+ {
+ max_nesting_depth = 100;
+
+ array_metadata = new Dictionary ();
+ conv_ops = new Dictionary> ();
+ object_metadata = new Dictionary ();
+ type_properties = new Dictionary> ();
+
+ static_writer = new JsonWriter ();
+
+ datetime_format = DateTimeFormatInfo.InvariantInfo;
+
+ base_exporters_table = new Dictionary ();
+ custom_exporters_table = new Dictionary ();
+
+ base_importers_table = new Dictionary> ();
+ custom_importers_table = new Dictionary> ();
+
+ RegisterBaseExporters ();
+ RegisterBaseImporters ();
+ }
+ #endregion
+
+
+ #region Private Methods
+ private static void AddArrayMetadata (Type type)
+ {
+ if (array_metadata.ContainsKey (type))
+ return;
+
+ ArrayMetadata data = new ArrayMetadata ();
+
+ data.IsArray = type.IsArray;
+
+ if (type.GetInterface ("System.Collections.IList") != null)
+ data.IsList = true;
+
+ foreach (PropertyInfo p_info in type.GetProperties ()) {
+ if (p_info.Name != "Item")
+ continue;
+
+ ParameterInfo[] parameters = p_info.GetIndexParameters ();
+
+ if (parameters.Length != 1)
+ continue;
+
+ if (parameters[0].ParameterType == typeof (int))
+ data.ElementType = p_info.PropertyType;
+ }
+
+ lock (array_metadata_lock) {
+ try {
+ array_metadata.Add (type, data);
+ } catch (ArgumentException) {
+ return;
+ }
+ }
+ }
+
+ private static void AddObjectMetadata (Type type)
+ {
+ if (object_metadata.ContainsKey (type))
+ return;
+
+ ObjectMetadata data = new ObjectMetadata ();
+
+ if (type.GetInterface ("System.Collections.IDictionary") != null)
+ data.IsDictionary = true;
+
+ data.Properties = new Dictionary ();
+
+ foreach (PropertyInfo p_info in type.GetProperties ()) {
+ if (p_info.Name == "Item") {
+ ParameterInfo[] parameters = p_info.GetIndexParameters ();
+
+ if (parameters.Length != 1)
+ continue;
+
+ if (parameters[0].ParameterType == typeof (string))
+ data.ElementType = p_info.PropertyType;
+
+ continue;
+ }
+
+ PropertyMetadata p_data = new PropertyMetadata ();
+ p_data.Info = p_info;
+ p_data.Type = p_info.PropertyType;
+
+ data.Properties.Add (p_info.Name, p_data);
+ }
+
+ foreach (FieldInfo f_info in type.GetFields ()) {
+ PropertyMetadata p_data = new PropertyMetadata ();
+ p_data.Info = f_info;
+ p_data.IsField = true;
+ p_data.Type = f_info.FieldType;
+
+ data.Properties.Add (f_info.Name, p_data);
+ }
+
+ lock (object_metadata_lock) {
+ try {
+ object_metadata.Add (type, data);
+ } catch (ArgumentException) {
+ return;
+ }
+ }
+ }
+
+ private static void AddTypeProperties (Type type)
+ {
+ if (type_properties.ContainsKey (type))
+ return;
+
+ IList props = new List ();
+
+ foreach (PropertyInfo p_info in type.GetProperties ()) {
+ if (p_info.Name == "Item")
+ continue;
+
+ PropertyMetadata p_data = new PropertyMetadata ();
+ p_data.Info = p_info;
+ p_data.IsField = false;
+ props.Add (p_data);
+ }
+
+ foreach (FieldInfo f_info in type.GetFields ()) {
+ PropertyMetadata p_data = new PropertyMetadata ();
+ p_data.Info = f_info;
+ p_data.IsField = true;
+
+ props.Add (p_data);
+ }
+
+ lock (type_properties_lock) {
+ try {
+ type_properties.Add (type, props);
+ } catch (ArgumentException) {
+ return;
+ }
+ }
+ }
+
+ private static MethodInfo GetConvOp (Type t1, Type t2)
+ {
+ lock (conv_ops_lock) {
+ if (! conv_ops.ContainsKey (t1))
+ conv_ops.Add (t1, new Dictionary ());
+ }
+
+ if (conv_ops[t1].ContainsKey (t2))
+ return conv_ops[t1][t2];
+
+ MethodInfo op = t1.GetMethod (
+ "op_Implicit", new Type[] { t2 });
+
+ lock (conv_ops_lock) {
+ try {
+ conv_ops[t1].Add (t2, op);
+ } catch (ArgumentException) {
+ return conv_ops[t1][t2];
+ }
+ }
+
+ return op;
+ }
+
+ private static object ReadValue (Type inst_type, JsonReader reader)
+ {
+ reader.Read ();
+
+ if (reader.Token == JsonToken.ArrayEnd)
+ return null;
+
+ Type underlying_type = Nullable.GetUnderlyingType(inst_type);
+ Type value_type = underlying_type ?? inst_type;
+
+ if (reader.Token == JsonToken.Null) {
+ #if NETSTANDARD1_5
+ if (inst_type.IsClass() || underlying_type != null) {
+ return null;
+ }
+ #else
+ if (inst_type.IsClass || underlying_type != null) {
+ return null;
+ }
+ #endif
+
+ throw new JsonException (String.Format (
+ "Can't assign null to an instance of type {0}",
+ inst_type));
+ }
+
+ if (reader.Token == JsonToken.Double ||
+ reader.Token == JsonToken.Int ||
+ reader.Token == JsonToken.Long ||
+ reader.Token == JsonToken.String ||
+ reader.Token == JsonToken.Boolean) {
+
+ Type json_type = reader.Value.GetType ();
+
+ if (value_type.IsAssignableFrom (json_type))
+ return reader.Value;
+
+ // If there's a custom importer that fits, use it
+ if (custom_importers_table.ContainsKey (json_type) &&
+ custom_importers_table[json_type].ContainsKey (
+ value_type)) {
+
+ ImporterFunc importer =
+ custom_importers_table[json_type][value_type];
+
+ return importer (reader.Value);
+ }
+
+ // Maybe there's a base importer that works
+ if (base_importers_table.ContainsKey (json_type) &&
+ base_importers_table[json_type].ContainsKey (
+ value_type)) {
+
+ ImporterFunc importer =
+ base_importers_table[json_type][value_type];
+
+ return importer (reader.Value);
+ }
+
+ // Maybe it's an enum
+ #if NETSTANDARD1_5
+ if (value_type.IsEnum())
+ return Enum.ToObject (value_type, reader.Value);
+ #else
+ if (value_type.IsEnum)
+ return Enum.ToObject (value_type, reader.Value);
+ #endif
+ // Try using an implicit conversion operator
+ MethodInfo conv_op = GetConvOp (value_type, json_type);
+
+ if (conv_op != null)
+ return conv_op.Invoke (null,
+ new object[] { reader.Value });
+
+ // No luck
+ throw new JsonException (String.Format (
+ "Can't assign value '{0}' (type {1}) to type {2}",
+ reader.Value, json_type, inst_type));
+ }
+
+ object instance = null;
+
+ if (reader.Token == JsonToken.ArrayStart) {
+
+ AddArrayMetadata (inst_type);
+ ArrayMetadata t_data = array_metadata[inst_type];
+
+ if (! t_data.IsArray && ! t_data.IsList)
+ throw new JsonException (String.Format (
+ "Type {0} can't act as an array",
+ inst_type));
+
+ IList list;
+ Type elem_type;
+
+ if (! t_data.IsArray) {
+ list = (IList) Activator.CreateInstance (inst_type);
+ elem_type = t_data.ElementType;
+ } else {
+ list = new ArrayList ();
+ elem_type = inst_type.GetElementType ();
+ }
+
+ while (true) {
+ object item = ReadValue (elem_type, reader);
+ if (item == null && reader.Token == JsonToken.ArrayEnd)
+ break;
+
+ list.Add (item);
+ }
+
+ if (t_data.IsArray) {
+ int n = list.Count;
+ instance = Array.CreateInstance (elem_type, n);
+
+ for (int i = 0; i < n; i++)
+ ((Array) instance).SetValue (list[i], i);
+ } else
+ instance = list;
+
+ } else if (reader.Token == JsonToken.ObjectStart) {
+ AddObjectMetadata (value_type);
+ ObjectMetadata t_data = object_metadata[value_type];
+
+ instance = Activator.CreateInstance (value_type);
+
+ while (true) {
+ reader.Read ();
+
+ if (reader.Token == JsonToken.ObjectEnd)
+ break;
+
+ string property = (string) reader.Value;
+
+ if (t_data.Properties.ContainsKey (property)) {
+ PropertyMetadata prop_data =
+ t_data.Properties[property];
+
+ if (prop_data.IsField) {
+ ((FieldInfo) prop_data.Info).SetValue (
+ instance, ReadValue (prop_data.Type, reader));
+ } else {
+ PropertyInfo p_info =
+ (PropertyInfo) prop_data.Info;
+
+ if (p_info.CanWrite)
+ p_info.SetValue (
+ instance,
+ ReadValue (prop_data.Type, reader),
+ null);
+ else
+ ReadValue (prop_data.Type, reader);
+ }
+
+ } else {
+ if (! t_data.IsDictionary) {
+
+ if (! reader.SkipNonMembers) {
+ throw new JsonException (String.Format (
+ "The type {0} doesn't have the " +
+ "property '{1}'",
+ inst_type, property));
+ } else {
+ ReadSkip (reader);
+ continue;
+ }
+ }
+
+ ((IDictionary) instance).Add (
+ property, ReadValue (
+ t_data.ElementType, reader));
+ }
+
+ }
+
+ }
+
+ return instance;
+ }
+
+ private static IJsonWrapper ReadValue (WrapperFactory factory,
+ JsonReader reader)
+ {
+ reader.Read ();
+
+ if (reader.Token == JsonToken.ArrayEnd ||
+ reader.Token == JsonToken.Null)
+ return null;
+
+ IJsonWrapper instance = factory ();
+
+ if (reader.Token == JsonToken.String) {
+ instance.SetString ((string) reader.Value);
+ return instance;
+ }
+
+ if (reader.Token == JsonToken.Double) {
+ instance.SetDouble ((double) reader.Value);
+ return instance;
+ }
+
+ if (reader.Token == JsonToken.Int) {
+ instance.SetInt ((int) reader.Value);
+ return instance;
+ }
+
+ if (reader.Token == JsonToken.Long) {
+ instance.SetLong ((long) reader.Value);
+ return instance;
+ }
+
+ if (reader.Token == JsonToken.Boolean) {
+ instance.SetBoolean ((bool) reader.Value);
+ return instance;
+ }
+
+ if (reader.Token == JsonToken.ArrayStart) {
+ instance.SetJsonType (JsonType.Array);
+
+ while (true) {
+ IJsonWrapper item = ReadValue (factory, reader);
+ if (item == null && reader.Token == JsonToken.ArrayEnd)
+ break;
+
+ ((IList) instance).Add (item);
+ }
+ }
+ else if (reader.Token == JsonToken.ObjectStart) {
+ instance.SetJsonType (JsonType.Object);
+
+ while (true) {
+ reader.Read ();
+
+ if (reader.Token == JsonToken.ObjectEnd)
+ break;
+
+ string property = (string) reader.Value;
+
+ ((IDictionary) instance)[property] = ReadValue (
+ factory, reader);
+ }
+
+ }
+
+ return instance;
+ }
+
+ private static void ReadSkip (JsonReader reader)
+ {
+ ToWrapper (
+ delegate { return new JsonMockWrapper (); }, reader);
+ }
+
+ private static void RegisterBaseExporters ()
+ {
+ base_exporters_table[typeof (byte)] =
+ delegate (object obj, JsonWriter writer) {
+ writer.Write (Convert.ToInt32 ((byte) obj));
+ };
+
+ base_exporters_table[typeof (char)] =
+ delegate (object obj, JsonWriter writer) {
+ writer.Write (Convert.ToString ((char) obj));
+ };
+
+ base_exporters_table[typeof (DateTime)] =
+ delegate (object obj, JsonWriter writer) {
+ writer.Write (Convert.ToString ((DateTime) obj,
+ datetime_format));
+ };
+
+ base_exporters_table[typeof (decimal)] =
+ delegate (object obj, JsonWriter writer) {
+ writer.Write ((decimal) obj);
+ };
+
+ base_exporters_table[typeof (sbyte)] =
+ delegate (object obj, JsonWriter writer) {
+ writer.Write (Convert.ToInt32 ((sbyte) obj));
+ };
+
+ base_exporters_table[typeof (short)] =
+ delegate (object obj, JsonWriter writer) {
+ writer.Write (Convert.ToInt32 ((short) obj));
+ };
+
+ base_exporters_table[typeof (ushort)] =
+ delegate (object obj, JsonWriter writer) {
+ writer.Write (Convert.ToInt32 ((ushort) obj));
+ };
+
+ base_exporters_table[typeof (uint)] =
+ delegate (object obj, JsonWriter writer) {
+ writer.Write (Convert.ToUInt64 ((uint) obj));
+ };
+
+ base_exporters_table[typeof (ulong)] =
+ delegate (object obj, JsonWriter writer) {
+ writer.Write ((ulong) obj);
+ };
+
+ base_exporters_table[typeof(DateTimeOffset)] =
+ delegate (object obj, JsonWriter writer) {
+ writer.Write(((DateTimeOffset)obj).ToString("yyyy-MM-ddTHH:mm:ss.fffffffzzz", datetime_format));
+ };
+ }
+
+ private static void RegisterBaseImporters ()
+ {
+ ImporterFunc importer;
+
+ importer = delegate (object input) {
+ return Convert.ToByte ((int) input);
+ };
+ RegisterImporter (base_importers_table, typeof (int),
+ typeof (byte), importer);
+
+ importer = delegate (object input) {
+ return Convert.ToUInt64 ((int) input);
+ };
+ RegisterImporter (base_importers_table, typeof (int),
+ typeof (ulong), importer);
+
+ importer = delegate (object input) {
+ return Convert.ToInt64((int)input);
+ };
+ RegisterImporter(base_importers_table, typeof(int),
+ typeof(long), importer);
+
+ importer = delegate (object input) {
+ return Convert.ToSByte ((int) input);
+ };
+ RegisterImporter (base_importers_table, typeof (int),
+ typeof (sbyte), importer);
+
+ importer = delegate (object input) {
+ return Convert.ToInt16 ((int) input);
+ };
+ RegisterImporter (base_importers_table, typeof (int),
+ typeof (short), importer);
+
+ importer = delegate (object input) {
+ return Convert.ToUInt16 ((int) input);
+ };
+ RegisterImporter (base_importers_table, typeof (int),
+ typeof (ushort), importer);
+
+ importer = delegate (object input) {
+ return Convert.ToUInt32 ((int) input);
+ };
+ RegisterImporter (base_importers_table, typeof (int),
+ typeof (uint), importer);
+
+ importer = delegate (object input) {
+ return Convert.ToSingle ((int) input);
+ };
+ RegisterImporter (base_importers_table, typeof (int),
+ typeof (float), importer);
+
+ importer = delegate (object input) {
+ return Convert.ToDouble ((int) input);
+ };
+ RegisterImporter (base_importers_table, typeof (int),
+ typeof (double), importer);
+
+ importer = delegate (object input) {
+ return Convert.ToDecimal ((double) input);
+ };
+ RegisterImporter (base_importers_table, typeof (double),
+ typeof (decimal), importer);
+
+
+ importer = delegate (object input) {
+ return Convert.ToUInt32 ((long) input);
+ };
+ RegisterImporter (base_importers_table, typeof (long),
+ typeof (uint), importer);
+
+ importer = delegate (object input) {
+ return Convert.ToChar ((string) input);
+ };
+ RegisterImporter (base_importers_table, typeof (string),
+ typeof (char), importer);
+
+ importer = delegate (object input) {
+ return Convert.ToDateTime ((string) input, datetime_format);
+ };
+ RegisterImporter (base_importers_table, typeof (string),
+ typeof (DateTime), importer);
+
+ importer = delegate (object input) {
+ return DateTimeOffset.Parse((string)input, datetime_format);
+ };
+ RegisterImporter(base_importers_table, typeof(string),
+ typeof(DateTimeOffset), importer);
+ }
+
+ private static void RegisterImporter (
+ IDictionary> table,
+ Type json_type, Type value_type, ImporterFunc importer)
+ {
+ if (! table.ContainsKey (json_type))
+ table.Add (json_type, new Dictionary ());
+
+ table[json_type][value_type] = importer;
+ }
+
+ private static void WriteValue (object obj, JsonWriter writer,
+ bool writer_is_private,
+ int depth)
+ {
+ if (depth > max_nesting_depth)
+ throw new JsonException (
+ String.Format ("Max allowed object depth reached while " +
+ "trying to export from type {0}",
+ obj.GetType ()));
+
+ if (obj == null) {
+ writer.Write (null);
+ return;
+ }
+
+ if (obj is IJsonWrapper) {
+ if (writer_is_private)
+ writer.TextWriter.Write (((IJsonWrapper) obj).ToJson ());
+ else
+ ((IJsonWrapper) obj).ToJson (writer);
+
+ return;
+ }
+
+ if (obj is String) {
+ writer.Write ((string) obj);
+ return;
+ }
+
+ if (obj is Double) {
+ writer.Write ((double) obj);
+ return;
+ }
+
+ if (obj is Int32) {
+ writer.Write ((int) obj);
+ return;
+ }
+
+ if (obj is Boolean) {
+ writer.Write ((bool) obj);
+ return;
+ }
+
+ if (obj is Int64) {
+ writer.Write ((long) obj);
+ return;
+ }
+
+ if (obj is Array) {
+ writer.WriteArrayStart ();
+
+ foreach (object elem in (Array) obj)
+ WriteValue (elem, writer, writer_is_private, depth + 1);
+
+ writer.WriteArrayEnd ();
+
+ return;
+ }
+
+ if (obj is IList) {
+ writer.WriteArrayStart ();
+ foreach (object elem in (IList) obj)
+ WriteValue (elem, writer, writer_is_private, depth + 1);
+ writer.WriteArrayEnd ();
+
+ return;
+ }
+
+ if (obj is IDictionary) {
+ writer.WriteObjectStart ();
+ foreach (DictionaryEntry entry in (IDictionary) obj) {
+ writer.WritePropertyName ((string) entry.Key);
+ WriteValue (entry.Value, writer, writer_is_private,
+ depth + 1);
+ }
+ writer.WriteObjectEnd ();
+
+ return;
+ }
+
+ Type obj_type = obj.GetType ();
+
+ // See if there's a custom exporter for the object
+ if (custom_exporters_table.ContainsKey (obj_type)) {
+ ExporterFunc exporter = custom_exporters_table[obj_type];
+ exporter (obj, writer);
+
+ return;
+ }
+
+ // If not, maybe there's a base exporter
+ if (base_exporters_table.ContainsKey (obj_type)) {
+ ExporterFunc exporter = base_exporters_table[obj_type];
+ exporter (obj, writer);
+
+ return;
+ }
+
+ // Last option, let's see if it's an enum
+ if (obj is Enum) {
+ Type e_type = Enum.GetUnderlyingType (obj_type);
+
+ if (e_type == typeof (long)
+ || e_type == typeof (uint)
+ || e_type == typeof (ulong))
+ writer.Write ((ulong) obj);
+ else
+ writer.Write ((int) obj);
+
+ return;
+ }
+
+ // Okay, so it looks like the input should be exported as an
+ // object
+ AddTypeProperties (obj_type);
+ IList props = type_properties[obj_type];
+
+ writer.WriteObjectStart ();
+ foreach (PropertyMetadata p_data in props) {
+ if (p_data.IsField) {
+ writer.WritePropertyName (p_data.Info.Name);
+ WriteValue (((FieldInfo) p_data.Info).GetValue (obj),
+ writer, writer_is_private, depth + 1);
+ }
+ else {
+ PropertyInfo p_info = (PropertyInfo) p_data.Info;
+
+ if (p_info.CanRead) {
+ writer.WritePropertyName (p_data.Info.Name);
+ WriteValue (p_info.GetValue (obj, null),
+ writer, writer_is_private, depth + 1);
+ }
+ }
+ }
+ writer.WriteObjectEnd ();
+ }
+ #endregion
+
+
+ public static string ToJson (object obj)
+ {
+ lock (static_writer_lock) {
+ static_writer.Reset ();
+
+ WriteValue (obj, static_writer, true, 0);
+
+ return static_writer.ToString ();
+ }
+ }
+
+ public static void ToJson (object obj, JsonWriter writer)
+ {
+ WriteValue (obj, writer, false, 0);
+ }
+
+ public static JsonData ToObject (JsonReader reader)
+ {
+ return (JsonData) ToWrapper (
+ delegate { return new JsonData (); }, reader);
+ }
+
+ public static JsonData ToObject (TextReader reader)
+ {
+ JsonReader json_reader = new JsonReader (reader);
+
+ return (JsonData) ToWrapper (
+ delegate { return new JsonData (); }, json_reader);
+ }
+
+ public static JsonData ToObject (string json)
+ {
+ return (JsonData) ToWrapper (
+ delegate { return new JsonData (); }, json);
+ }
+
+ public static T ToObject (JsonReader reader)
+ {
+ return (T) ReadValue (typeof (T), reader);
+ }
+
+ public static T ToObject (TextReader reader)
+ {
+ JsonReader json_reader = new JsonReader (reader);
+
+ return (T) ReadValue (typeof (T), json_reader);
+ }
+
+ public static T ToObject (string json)
+ {
+ JsonReader reader = new JsonReader (json);
+
+ return (T) ReadValue (typeof (T), reader);
+ }
+
+ public static object ToObject(string json, Type ConvertType )
+ {
+ JsonReader reader = new JsonReader(json);
+
+ return ReadValue(ConvertType, reader);
+ }
+
+ public static IJsonWrapper ToWrapper (WrapperFactory factory,
+ JsonReader reader)
+ {
+ return ReadValue (factory, reader);
+ }
+
+ public static IJsonWrapper ToWrapper (WrapperFactory factory,
+ string json)
+ {
+ JsonReader reader = new JsonReader (json);
+
+ return ReadValue (factory, reader);
+ }
+
+ public static void RegisterExporter (ExporterFunc exporter)
+ {
+ ExporterFunc exporter_wrapper =
+ delegate (object obj, JsonWriter writer) {
+ exporter ((T) obj, writer);
+ };
+
+ custom_exporters_table[typeof (T)] = exporter_wrapper;
+ }
+
+ public static void RegisterImporter (
+ ImporterFunc importer)
+ {
+ ImporterFunc importer_wrapper =
+ delegate (object input) {
+ return importer ((TJson) input);
+ };
+
+ RegisterImporter (custom_importers_table, typeof (TJson),
+ typeof (TValue), importer_wrapper);
+ }
+
+ public static void UnregisterExporters ()
+ {
+ custom_exporters_table.Clear ();
+ }
+
+ public static void UnregisterImporters ()
+ {
+ custom_importers_table.Clear ();
+ }
+ }
+}
diff --git a/src/Cake.Issues/Serialization/LitJson/JsonMockWrapper.cs b/src/Cake.Issues/Serialization/LitJson/JsonMockWrapper.cs
new file mode 100644
index 000000000..2b02d338d
--- /dev/null
+++ b/src/Cake.Issues/Serialization/LitJson/JsonMockWrapper.cs
@@ -0,0 +1,111 @@
+#pragma warning disable 1587
+#pragma warning disable 1591
+
+#region Header
+/**
+ * JsonMockWrapper.cs
+ * Mock object implementing IJsonWrapper, to facilitate actions like
+ * skipping data more efficiently.
+ *
+ * The authors disclaim copyright to this source code. For more details, see
+ * the 3rd-Party-License.md file included with this distribution.
+ **/
+
+// This file isn't generated, but this comment is necessary to exclude it from code analysis.
+//
+#endregion
+
+
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+
+
+namespace LitJson
+{
+ internal class JsonMockWrapper : IJsonWrapper
+ {
+ public bool IsArray { get { return false; } }
+ public bool IsBoolean { get { return false; } }
+ public bool IsDouble { get { return false; } }
+ public bool IsInt { get { return false; } }
+ public bool IsLong { get { return false; } }
+ public bool IsObject { get { return false; } }
+ public bool IsString { get { return false; } }
+
+ public bool GetBoolean () { return false; }
+ public double GetDouble () { return 0.0; }
+ public int GetInt () { return 0; }
+ public JsonType GetJsonType () { return JsonType.None; }
+ public long GetLong () { return 0L; }
+ public string GetString () { return ""; }
+
+ public void SetBoolean (bool val) {}
+ public void SetDouble (double val) {}
+ public void SetInt (int val) {}
+ public void SetJsonType (JsonType type) {}
+ public void SetLong (long val) {}
+ public void SetString (string val) {}
+
+ public string ToJson () { return ""; }
+ public void ToJson (JsonWriter writer) {}
+
+
+ bool IList.IsFixedSize { get { return true; } }
+ bool IList.IsReadOnly { get { return true; } }
+
+ object IList.this[int index] {
+ get { return null; }
+ set {}
+ }
+
+ int IList.Add (object value) { return 0; }
+ void IList.Clear () {}
+ bool IList.Contains (object value) { return false; }
+ int IList.IndexOf (object value) { return -1; }
+ void IList.Insert (int i, object v) {}
+ void IList.Remove (object value) {}
+ void IList.RemoveAt (int index) {}
+
+
+ int ICollection.Count { get { return 0; } }
+ bool ICollection.IsSynchronized { get { return false; } }
+ object ICollection.SyncRoot { get { return null; } }
+
+ void ICollection.CopyTo (Array array, int index) {}
+
+
+ IEnumerator IEnumerable.GetEnumerator () { return null; }
+
+
+ bool IDictionary.IsFixedSize { get { return true; } }
+ bool IDictionary.IsReadOnly { get { return true; } }
+
+ ICollection IDictionary.Keys { get { return null; } }
+ ICollection IDictionary.Values { get { return null; } }
+
+ object IDictionary.this[object key] {
+ get { return null; }
+ set {}
+ }
+
+ void IDictionary.Add (object k, object v) {}
+ void IDictionary.Clear () {}
+ bool IDictionary.Contains (object key) { return false; }
+ void IDictionary.Remove (object key) {}
+
+ IDictionaryEnumerator IDictionary.GetEnumerator () { return null; }
+
+
+ object IOrderedDictionary.this[int idx] {
+ get { return null; }
+ set {}
+ }
+
+ IDictionaryEnumerator IOrderedDictionary.GetEnumerator () {
+ return null;
+ }
+ void IOrderedDictionary.Insert (int i, object k, object v) {}
+ void IOrderedDictionary.RemoveAt (int i) {}
+ }
+}
diff --git a/src/Cake.Issues/Serialization/LitJson/JsonReader.cs b/src/Cake.Issues/Serialization/LitJson/JsonReader.cs
new file mode 100644
index 000000000..b298d6aad
--- /dev/null
+++ b/src/Cake.Issues/Serialization/LitJson/JsonReader.cs
@@ -0,0 +1,484 @@
+#pragma warning disable 1587
+#pragma warning disable 1591
+
+#region Header
+/**
+ * JsonReader.cs
+ * Stream-like access to JSON text.
+ *
+ * The authors disclaim copyright to this source code. For more details, see
+ * the 3rd-Party-License.md file included with this distribution.
+ **/
+
+// This file isn't generated, but this comment is necessary to exclude it from code analysis.
+//
+#endregion
+
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Text;
+
+
+namespace LitJson
+{
+ internal enum JsonToken
+ {
+ None,
+
+ ObjectStart,
+ PropertyName,
+ ObjectEnd,
+
+ ArrayStart,
+ ArrayEnd,
+
+ Int,
+ Long,
+ Double,
+
+ String,
+
+ Boolean,
+ Null
+ }
+
+
+ internal class JsonReader
+ {
+ #region Fields
+ private static readonly IDictionary> parse_table;
+
+ private Stack automaton_stack;
+ private int current_input;
+ private int current_symbol;
+ private bool end_of_json;
+ private bool end_of_input;
+ private Lexer lexer;
+ private bool parser_in_string;
+ private bool parser_return;
+ private bool read_started;
+ private TextReader reader;
+ private bool reader_is_owned;
+ private bool skip_non_members;
+ private object token_value;
+ private JsonToken token;
+ #endregion
+
+
+ #region Public Properties
+ public bool AllowComments {
+ get { return lexer.AllowComments; }
+ set { lexer.AllowComments = value; }
+ }
+
+ public bool AllowSingleQuotedStrings {
+ get { return lexer.AllowSingleQuotedStrings; }
+ set { lexer.AllowSingleQuotedStrings = value; }
+ }
+
+ public bool SkipNonMembers {
+ get { return skip_non_members; }
+ set { skip_non_members = value; }
+ }
+
+ public bool EndOfInput {
+ get { return end_of_input; }
+ }
+
+ public bool EndOfJson {
+ get { return end_of_json; }
+ }
+
+ public JsonToken Token {
+ get { return token; }
+ }
+
+ public object Value {
+ get { return token_value; }
+ }
+ #endregion
+
+
+ #region Constructors
+ static JsonReader ()
+ {
+ parse_table = PopulateParseTable ();
+ }
+
+ public JsonReader (string json_text) :
+ this (new StringReader (json_text), true)
+ {
+ }
+
+ public JsonReader (TextReader reader) :
+ this (reader, false)
+ {
+ }
+
+ private JsonReader (TextReader reader, bool owned)
+ {
+ if (reader == null)
+ throw new ArgumentNullException ("reader");
+
+ parser_in_string = false;
+ parser_return = false;
+
+ read_started = false;
+ automaton_stack = new Stack ();
+ automaton_stack.Push ((int) ParserToken.End);
+ automaton_stack.Push ((int) ParserToken.Text);
+
+ lexer = new Lexer (reader);
+
+ end_of_input = false;
+ end_of_json = false;
+
+ skip_non_members = true;
+
+ this.reader = reader;
+ reader_is_owned = owned;
+ }
+ #endregion
+
+
+ #region Static Methods
+ private static IDictionary> PopulateParseTable ()
+ {
+ // See section A.2. of the manual for details
+ IDictionary> parse_table = new Dictionary> ();
+
+ TableAddRow (parse_table, ParserToken.Array);
+ TableAddCol (parse_table, ParserToken.Array, '[',
+ '[',
+ (int) ParserToken.ArrayPrime);
+
+ TableAddRow (parse_table, ParserToken.ArrayPrime);
+ TableAddCol (parse_table, ParserToken.ArrayPrime, '"',
+ (int) ParserToken.Value,
+
+ (int) ParserToken.ValueRest,
+ ']');
+ TableAddCol (parse_table, ParserToken.ArrayPrime, '[',
+ (int) ParserToken.Value,
+ (int) ParserToken.ValueRest,
+ ']');
+ TableAddCol (parse_table, ParserToken.ArrayPrime, ']',
+ ']');
+ TableAddCol (parse_table, ParserToken.ArrayPrime, '{',
+ (int) ParserToken.Value,
+ (int) ParserToken.ValueRest,
+ ']');
+ TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.Number,
+ (int) ParserToken.Value,
+ (int) ParserToken.ValueRest,
+ ']');
+ TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.True,
+ (int) ParserToken.Value,
+ (int) ParserToken.ValueRest,
+ ']');
+ TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.False,
+ (int) ParserToken.Value,
+ (int) ParserToken.ValueRest,
+ ']');
+ TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.Null,
+ (int) ParserToken.Value,
+ (int) ParserToken.ValueRest,
+ ']');
+
+ TableAddRow (parse_table, ParserToken.Object);
+ TableAddCol (parse_table, ParserToken.Object, '{',
+ '{',
+ (int) ParserToken.ObjectPrime);
+
+ TableAddRow (parse_table, ParserToken.ObjectPrime);
+ TableAddCol (parse_table, ParserToken.ObjectPrime, '"',
+ (int) ParserToken.Pair,
+ (int) ParserToken.PairRest,
+ '}');
+ TableAddCol (parse_table, ParserToken.ObjectPrime, '}',
+ '}');
+
+ TableAddRow (parse_table, ParserToken.Pair);
+ TableAddCol (parse_table, ParserToken.Pair, '"',
+ (int) ParserToken.String,
+ ':',
+ (int) ParserToken.Value);
+
+ TableAddRow (parse_table, ParserToken.PairRest);
+ TableAddCol (parse_table, ParserToken.PairRest, ',',
+ ',',
+ (int) ParserToken.Pair,
+ (int) ParserToken.PairRest);
+ TableAddCol (parse_table, ParserToken.PairRest, '}',
+ (int) ParserToken.Epsilon);
+
+ TableAddRow (parse_table, ParserToken.String);
+ TableAddCol (parse_table, ParserToken.String, '"',
+ '"',
+ (int) ParserToken.CharSeq,
+ '"');
+
+ TableAddRow (parse_table, ParserToken.Text);
+ TableAddCol (parse_table, ParserToken.Text, '[',
+ (int) ParserToken.Array);
+ TableAddCol (parse_table, ParserToken.Text, '{',
+ (int) ParserToken.Object);
+
+ TableAddRow (parse_table, ParserToken.Value);
+ TableAddCol (parse_table, ParserToken.Value, '"',
+ (int) ParserToken.String);
+ TableAddCol (parse_table, ParserToken.Value, '[',
+ (int) ParserToken.Array);
+ TableAddCol (parse_table, ParserToken.Value, '{',
+ (int) ParserToken.Object);
+ TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.Number,
+ (int) ParserToken.Number);
+ TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.True,
+ (int) ParserToken.True);
+ TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.False,
+ (int) ParserToken.False);
+ TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.Null,
+ (int) ParserToken.Null);
+
+ TableAddRow (parse_table, ParserToken.ValueRest);
+ TableAddCol (parse_table, ParserToken.ValueRest, ',',
+ ',',
+ (int) ParserToken.Value,
+ (int) ParserToken.ValueRest);
+ TableAddCol (parse_table, ParserToken.ValueRest, ']',
+ (int) ParserToken.Epsilon);
+
+ return parse_table;
+ }
+
+ private static void TableAddCol (IDictionary> parse_table, ParserToken row, int col,
+ params int[] symbols)
+ {
+ parse_table[(int) row].Add (col, symbols);
+ }
+
+ private static void TableAddRow (IDictionary> parse_table, ParserToken rule)
+ {
+ parse_table.Add ((int) rule, new Dictionary ());
+ }
+ #endregion
+
+
+ #region Private Methods
+ private void ProcessNumber (string number)
+ {
+ if (number.IndexOf ('.') != -1 ||
+ number.IndexOf ('e') != -1 ||
+ number.IndexOf ('E') != -1) {
+
+ double n_double;
+ if (double.TryParse (number, NumberStyles.Any, CultureInfo.InvariantCulture, out n_double)) {
+ token = JsonToken.Double;
+ token_value = n_double;
+
+ return;
+ }
+ }
+
+ int n_int32;
+ if (int.TryParse (number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n_int32)) {
+ token = JsonToken.Int;
+ token_value = n_int32;
+
+ return;
+ }
+
+ long n_int64;
+ if (long.TryParse (number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n_int64)) {
+ token = JsonToken.Long;
+ token_value = n_int64;
+
+ return;
+ }
+
+ ulong n_uint64;
+ if (ulong.TryParse(number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n_uint64))
+ {
+ token = JsonToken.Long;
+ token_value = n_uint64;
+
+ return;
+ }
+
+ // Shouldn't happen, but just in case, return something
+ token = JsonToken.Int;
+ token_value = 0;
+ }
+
+ private void ProcessSymbol ()
+ {
+ if (current_symbol == '[') {
+ token = JsonToken.ArrayStart;
+ parser_return = true;
+
+ } else if (current_symbol == ']') {
+ token = JsonToken.ArrayEnd;
+ parser_return = true;
+
+ } else if (current_symbol == '{') {
+ token = JsonToken.ObjectStart;
+ parser_return = true;
+
+ } else if (current_symbol == '}') {
+ token = JsonToken.ObjectEnd;
+ parser_return = true;
+
+ } else if (current_symbol == '"') {
+ if (parser_in_string) {
+ parser_in_string = false;
+
+ parser_return = true;
+
+ } else {
+ if (token == JsonToken.None)
+ token = JsonToken.String;
+
+ parser_in_string = true;
+ }
+
+ } else if (current_symbol == (int) ParserToken.CharSeq) {
+ token_value = lexer.StringValue;
+
+ } else if (current_symbol == (int) ParserToken.False) {
+ token = JsonToken.Boolean;
+ token_value = false;
+ parser_return = true;
+
+ } else if (current_symbol == (int) ParserToken.Null) {
+ token = JsonToken.Null;
+ parser_return = true;
+
+ } else if (current_symbol == (int) ParserToken.Number) {
+ ProcessNumber (lexer.StringValue);
+
+ parser_return = true;
+
+ } else if (current_symbol == (int) ParserToken.Pair) {
+ token = JsonToken.PropertyName;
+
+ } else if (current_symbol == (int) ParserToken.True) {
+ token = JsonToken.Boolean;
+ token_value = true;
+ parser_return = true;
+
+ }
+ }
+
+ private bool ReadToken ()
+ {
+ if (end_of_input)
+ return false;
+
+ lexer.NextToken ();
+
+ if (lexer.EndOfInput) {
+ Close ();
+
+ return false;
+ }
+
+ current_input = lexer.Token;
+
+ return true;
+ }
+ #endregion
+
+
+ public void Close ()
+ {
+ if (end_of_input)
+ return;
+
+ end_of_input = true;
+ end_of_json = true;
+
+ if (reader_is_owned)
+ {
+ using(reader){}
+ }
+
+ reader = null;
+ }
+
+ public bool Read ()
+ {
+ if (end_of_input)
+ return false;
+
+ if (end_of_json) {
+ end_of_json = false;
+ automaton_stack.Clear ();
+ automaton_stack.Push ((int) ParserToken.End);
+ automaton_stack.Push ((int) ParserToken.Text);
+ }
+
+ parser_in_string = false;
+ parser_return = false;
+
+ token = JsonToken.None;
+ token_value = null;
+
+ if (! read_started) {
+ read_started = true;
+
+ if (! ReadToken ())
+ return false;
+ }
+
+
+ int[] entry_symbols;
+
+ while (true) {
+ if (parser_return) {
+ if (automaton_stack.Peek () == (int) ParserToken.End)
+ end_of_json = true;
+
+ return true;
+ }
+
+ current_symbol = automaton_stack.Pop ();
+
+ ProcessSymbol ();
+
+ if (current_symbol == current_input) {
+ if (! ReadToken ()) {
+ if (automaton_stack.Peek () != (int) ParserToken.End)
+ throw new JsonException (
+ "Input doesn't evaluate to proper JSON text");
+
+ if (parser_return)
+ return true;
+
+ return false;
+ }
+
+ continue;
+ }
+
+ try {
+
+ entry_symbols =
+ parse_table[current_symbol][current_input];
+
+ } catch (KeyNotFoundException e) {
+ throw new JsonException ((ParserToken) current_input, e);
+ }
+
+ if (entry_symbols[0] == (int) ParserToken.Epsilon)
+ continue;
+
+ for (int i = entry_symbols.Length - 1; i >= 0; i--)
+ automaton_stack.Push (entry_symbols[i]);
+ }
+ }
+
+ }
+}
diff --git a/src/Cake.Issues/Serialization/LitJson/JsonWriter.cs b/src/Cake.Issues/Serialization/LitJson/JsonWriter.cs
new file mode 100644
index 000000000..63af4dde8
--- /dev/null
+++ b/src/Cake.Issues/Serialization/LitJson/JsonWriter.cs
@@ -0,0 +1,479 @@
+#pragma warning disable 1587
+#pragma warning disable 1591
+
+#region Header
+/**
+ * JsonWriter.cs
+ * Stream-like facility to output JSON text.
+ *
+ * The authors disclaim copyright to this source code. For more details, see
+ * the 3rd-Party-License.md file included with this distribution.
+ **/
+
+// This file isn't generated, but this comment is necessary to exclude it from code analysis.
+//
+#endregion
+
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Text;
+
+
+namespace LitJson
+{
+ internal enum Condition
+ {
+ InArray,
+ InObject,
+ NotAProperty,
+ Property,
+ Value
+ }
+
+ internal class WriterContext
+ {
+ public int Count;
+ public bool InArray;
+ public bool InObject;
+ public bool ExpectingValue;
+ public int Padding;
+ }
+
+ internal class JsonWriter
+ {
+ #region Fields
+ private static readonly NumberFormatInfo number_format;
+
+ private WriterContext context;
+ private Stack ctx_stack;
+ private bool has_reached_end;
+ private char[] hex_seq;
+ private int indentation;
+ private int indent_value;
+ private StringBuilder inst_string_builder;
+ private bool pretty_print;
+ private bool validate;
+ private bool lower_case_properties;
+ private TextWriter writer;
+ #endregion
+
+
+ #region Properties
+ public int IndentValue {
+ get { return indent_value; }
+ set {
+ indentation = (indentation / indent_value) * value;
+ indent_value = value;
+ }
+ }
+
+ public bool PrettyPrint {
+ get { return pretty_print; }
+ set { pretty_print = value; }
+ }
+
+ public TextWriter TextWriter {
+ get { return writer; }
+ }
+
+ public bool Validate {
+ get { return validate; }
+ set { validate = value; }
+ }
+
+ public bool LowerCaseProperties {
+ get { return lower_case_properties; }
+ set { lower_case_properties = value; }
+ }
+ #endregion
+
+
+ #region Constructors
+ static JsonWriter ()
+ {
+ number_format = NumberFormatInfo.InvariantInfo;
+ }
+
+ public JsonWriter ()
+ {
+ inst_string_builder = new StringBuilder ();
+ writer = new StringWriter (inst_string_builder);
+
+ Init ();
+ }
+
+ public JsonWriter (StringBuilder sb) :
+ this (new StringWriter (sb))
+ {
+ }
+
+ public JsonWriter (TextWriter writer)
+ {
+ if (writer == null)
+ throw new ArgumentNullException ("writer");
+
+ this.writer = writer;
+
+ Init ();
+ }
+ #endregion
+
+
+ #region Private Methods
+ private void DoValidation (Condition cond)
+ {
+ if (! context.ExpectingValue)
+ context.Count++;
+
+ if (! validate)
+ return;
+
+ if (has_reached_end)
+ throw new JsonException (
+ "A complete JSON symbol has already been written");
+
+ switch (cond) {
+ case Condition.InArray:
+ if (! context.InArray)
+ throw new JsonException (
+ "Can't close an array here");
+ break;
+
+ case Condition.InObject:
+ if (! context.InObject || context.ExpectingValue)
+ throw new JsonException (
+ "Can't close an object here");
+ break;
+
+ case Condition.NotAProperty:
+ if (context.InObject && ! context.ExpectingValue)
+ throw new JsonException (
+ "Expected a property");
+ break;
+
+ case Condition.Property:
+ if (! context.InObject || context.ExpectingValue)
+ throw new JsonException (
+ "Can't add a property here");
+ break;
+
+ case Condition.Value:
+ if (! context.InArray &&
+ (! context.InObject || ! context.ExpectingValue))
+ throw new JsonException (
+ "Can't add a value here");
+
+ break;
+ }
+ }
+
+ private void Init ()
+ {
+ has_reached_end = false;
+ hex_seq = new char[4];
+ indentation = 0;
+ indent_value = 4;
+ pretty_print = false;
+ validate = true;
+ lower_case_properties = false;
+
+ ctx_stack = new Stack ();
+ context = new WriterContext ();
+ ctx_stack.Push (context);
+ }
+
+ private static void IntToHex (int n, char[] hex)
+ {
+ int num;
+
+ for (int i = 0; i < 4; i++) {
+ num = n % 16;
+
+ if (num < 10)
+ hex[3 - i] = (char) ('0' + num);
+ else
+ hex[3 - i] = (char) ('A' + (num - 10));
+
+ n >>= 4;
+ }
+ }
+
+ private void Indent ()
+ {
+ if (pretty_print)
+ indentation += indent_value;
+ }
+
+
+ private void Put (string str)
+ {
+ if (pretty_print && ! context.ExpectingValue)
+ for (int i = 0; i < indentation; i++)
+ writer.Write (' ');
+
+ writer.Write (str);
+ }
+
+ private void PutNewline ()
+ {
+ PutNewline (true);
+ }
+
+ private void PutNewline (bool add_comma)
+ {
+ if (add_comma && ! context.ExpectingValue &&
+ context.Count > 1)
+ writer.Write (',');
+
+ if (pretty_print && ! context.ExpectingValue)
+ writer.Write (Environment.NewLine);
+ }
+
+ private void PutString (string str)
+ {
+ Put (String.Empty);
+
+ writer.Write ('"');
+
+ int n = str.Length;
+ for (int i = 0; i < n; i++) {
+ switch (str[i]) {
+ case '\n':
+ writer.Write ("\\n");
+ continue;
+
+ case '\r':
+ writer.Write ("\\r");
+ continue;
+
+ case '\t':
+ writer.Write ("\\t");
+ continue;
+
+ case '"':
+ case '\\':
+ writer.Write ('\\');
+ writer.Write (str[i]);
+ continue;
+
+ case '\f':
+ writer.Write ("\\f");
+ continue;
+
+ case '\b':
+ writer.Write ("\\b");
+ continue;
+ }
+
+ if ((int) str[i] >= 32 && (int) str[i] <= 126) {
+ writer.Write (str[i]);
+ continue;
+ }
+
+ // Default, turn into a \uXXXX sequence
+ IntToHex ((int) str[i], hex_seq);
+ writer.Write ("\\u");
+ writer.Write (hex_seq);
+ }
+
+ writer.Write ('"');
+ }
+
+ private void Unindent ()
+ {
+ if (pretty_print)
+ indentation -= indent_value;
+ }
+ #endregion
+
+
+ public override string ToString ()
+ {
+ if (inst_string_builder == null)
+ return String.Empty;
+
+ return inst_string_builder.ToString ();
+ }
+
+ public void Reset ()
+ {
+ has_reached_end = false;
+
+ ctx_stack.Clear ();
+ context = new WriterContext ();
+ ctx_stack.Push (context);
+
+ if (inst_string_builder != null)
+ inst_string_builder.Remove (0, inst_string_builder.Length);
+ }
+
+ public void Write (bool boolean)
+ {
+ DoValidation (Condition.Value);
+ PutNewline ();
+
+ Put (boolean ? "true" : "false");
+
+ context.ExpectingValue = false;
+ }
+
+ public void Write (decimal number)
+ {
+ DoValidation (Condition.Value);
+ PutNewline ();
+
+ Put (Convert.ToString (number, number_format));
+
+ context.ExpectingValue = false;
+ }
+
+ public void Write (double number)
+ {
+ DoValidation (Condition.Value);
+ PutNewline ();
+
+ string str = Convert.ToString (number, number_format);
+ Put (str);
+
+ if (str.IndexOf ('.') == -1 &&
+ str.IndexOf ('E') == -1)
+ writer.Write (".0");
+
+ context.ExpectingValue = false;
+ }
+
+ public void Write (int number)
+ {
+ DoValidation (Condition.Value);
+ PutNewline ();
+
+ Put (Convert.ToString (number, number_format));
+
+ context.ExpectingValue = false;
+ }
+
+ public void Write (long number)
+ {
+ DoValidation (Condition.Value);
+ PutNewline ();
+
+ Put (Convert.ToString (number, number_format));
+
+ context.ExpectingValue = false;
+ }
+
+ public void Write (string str)
+ {
+ DoValidation (Condition.Value);
+ PutNewline ();
+
+ if (str == null)
+ Put ("null");
+ else
+ PutString (str);
+
+ context.ExpectingValue = false;
+ }
+
+ [CLSCompliant(false)]
+ public void Write (ulong number)
+ {
+ DoValidation (Condition.Value);
+ PutNewline ();
+
+ Put (Convert.ToString (number, number_format));
+
+ context.ExpectingValue = false;
+ }
+
+ public void WriteArrayEnd ()
+ {
+ DoValidation (Condition.InArray);
+ PutNewline (false);
+
+ ctx_stack.Pop ();
+ if (ctx_stack.Count == 1)
+ has_reached_end = true;
+ else {
+ context = ctx_stack.Peek ();
+ context.ExpectingValue = false;
+ }
+
+ Unindent ();
+ Put ("]");
+ }
+
+ public void WriteArrayStart ()
+ {
+ DoValidation (Condition.NotAProperty);
+ PutNewline ();
+
+ Put ("[");
+
+ context = new WriterContext ();
+ context.InArray = true;
+ ctx_stack.Push (context);
+
+ Indent ();
+ }
+
+ public void WriteObjectEnd ()
+ {
+ DoValidation (Condition.InObject);
+ PutNewline (false);
+
+ ctx_stack.Pop ();
+ if (ctx_stack.Count == 1)
+ has_reached_end = true;
+ else {
+ context = ctx_stack.Peek ();
+ context.ExpectingValue = false;
+ }
+
+ Unindent ();
+ Put ("}");
+ }
+
+ public void WriteObjectStart ()
+ {
+ DoValidation (Condition.NotAProperty);
+ PutNewline ();
+
+ Put ("{");
+
+ context = new WriterContext ();
+ context.InObject = true;
+ ctx_stack.Push (context);
+
+ Indent ();
+ }
+
+ public void WritePropertyName (string property_name)
+ {
+ DoValidation (Condition.Property);
+ PutNewline ();
+ string propertyName = (property_name == null || !lower_case_properties)
+ ? property_name
+ : property_name.ToLowerInvariant();
+
+ PutString (propertyName);
+
+ if (pretty_print) {
+ if (propertyName.Length > context.Padding)
+ context.Padding = propertyName.Length;
+
+ for (int i = context.Padding - propertyName.Length;
+ i >= 0; i--)
+ writer.Write (' ');
+
+ writer.Write (": ");
+ } else
+ writer.Write (':');
+
+ context.ExpectingValue = true;
+ }
+ }
+}
diff --git a/src/Cake.Issues/Serialization/LitJson/Lexer.cs b/src/Cake.Issues/Serialization/LitJson/Lexer.cs
new file mode 100644
index 000000000..9f604509d
--- /dev/null
+++ b/src/Cake.Issues/Serialization/LitJson/Lexer.cs
@@ -0,0 +1,918 @@
+#pragma warning disable 1587
+#pragma warning disable 1591
+
+#region Header
+/**
+ * Lexer.cs
+ * JSON lexer implementation based on a finite state machine.
+ *
+ * The authors disclaim copyright to this source code. For more details, see
+ * the 3rd-Party-License.md file included with this distribution.
+ **/
+
+// This file isn't generated, but this comment is necessary to exclude it from code analysis.
+//
+#endregion
+
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+
+namespace LitJson
+{
+ internal class FsmContext
+ {
+ public bool Return;
+ public int NextState;
+ public Lexer L;
+ public int StateStack;
+ }
+
+
+ internal class Lexer
+ {
+ #region Fields
+ private delegate bool StateHandler (FsmContext ctx);
+
+ private static readonly int[] fsm_return_table;
+ private static readonly StateHandler[] fsm_handler_table;
+
+ private bool allow_comments;
+ private bool allow_single_quoted_strings;
+ private bool end_of_input;
+ private FsmContext fsm_context;
+ private int input_buffer;
+ private int input_char;
+ private TextReader reader;
+ private int state;
+ private StringBuilder string_buffer;
+ private string string_value;
+ private int token;
+ private int unichar;
+ #endregion
+
+
+ #region Properties
+ public bool AllowComments {
+ get { return allow_comments; }
+ set { allow_comments = value; }
+ }
+
+ public bool AllowSingleQuotedStrings {
+ get { return allow_single_quoted_strings; }
+ set { allow_single_quoted_strings = value; }
+ }
+
+ public bool EndOfInput {
+ get { return end_of_input; }
+ }
+
+ public int Token {
+ get { return token; }
+ }
+
+ public string StringValue {
+ get { return string_value; }
+ }
+ #endregion
+
+
+ #region Constructors
+ static Lexer ()
+ {
+ PopulateFsmTables (out fsm_handler_table, out fsm_return_table);
+ }
+
+ public Lexer (TextReader reader)
+ {
+ allow_comments = true;
+ allow_single_quoted_strings = true;
+
+ input_buffer = 0;
+ string_buffer = new StringBuilder (128);
+ state = 1;
+ end_of_input = false;
+ this.reader = reader;
+
+ fsm_context = new FsmContext ();
+ fsm_context.L = this;
+ }
+ #endregion
+
+
+ #region Static Methods
+ private static int HexValue (int digit)
+ {
+ switch (digit) {
+ case 'a':
+ case 'A':
+ return 10;
+
+ case 'b':
+ case 'B':
+ return 11;
+
+ case 'c':
+ case 'C':
+ return 12;
+
+ case 'd':
+ case 'D':
+ return 13;
+
+ case 'e':
+ case 'E':
+ return 14;
+
+ case 'f':
+ case 'F':
+ return 15;
+
+ default:
+ return digit - '0';
+ }
+ }
+
+ private static void PopulateFsmTables (out StateHandler[] fsm_handler_table, out int[] fsm_return_table)
+ {
+ // See section A.1. of the manual for details of the finite
+ // state machine.
+ fsm_handler_table = new StateHandler[28] {
+ State1,
+ State2,
+ State3,
+ State4,
+ State5,
+ State6,
+ State7,
+ State8,
+ State9,
+ State10,
+ State11,
+ State12,
+ State13,
+ State14,
+ State15,
+ State16,
+ State17,
+ State18,
+ State19,
+ State20,
+ State21,
+ State22,
+ State23,
+ State24,
+ State25,
+ State26,
+ State27,
+ State28
+ };
+
+ fsm_return_table = new int[28] {
+ (int) ParserToken.Char,
+ 0,
+ (int) ParserToken.Number,
+ (int) ParserToken.Number,
+ 0,
+ (int) ParserToken.Number,
+ 0,
+ (int) ParserToken.Number,
+ 0,
+ 0,
+ (int) ParserToken.True,
+ 0,
+ 0,
+ 0,
+ (int) ParserToken.False,
+ 0,
+ 0,
+ (int) ParserToken.Null,
+ (int) ParserToken.CharSeq,
+ (int) ParserToken.Char,
+ 0,
+ 0,
+ (int) ParserToken.CharSeq,
+ (int) ParserToken.Char,
+ 0,
+ 0,
+ 0,
+ 0
+ };
+ }
+
+ private static char ProcessEscChar (int esc_char)
+ {
+ switch (esc_char) {
+ case '"':
+ case '\'':
+ case '\\':
+ case '/':
+ return Convert.ToChar (esc_char);
+
+ case 'n':
+ return '\n';
+
+ case 't':
+ return '\t';
+
+ case 'r':
+ return '\r';
+
+ case 'b':
+ return '\b';
+
+ case 'f':
+ return '\f';
+
+ default:
+ // Unreachable
+ return '?';
+ }
+ }
+
+ private static bool State1 (FsmContext ctx)
+ {
+ while (ctx.L.GetChar ()) {
+ if (ctx.L.input_char == ' ' ||
+ ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r')
+ continue;
+
+ if (ctx.L.input_char >= '1' && ctx.L.input_char <= '9') {
+ ctx.L.string_buffer.Append ((char) ctx.L.input_char);
+ ctx.NextState = 3;
+ return true;
+ }
+
+ switch (ctx.L.input_char) {
+ case '"':
+ ctx.NextState = 19;
+ ctx.Return = true;
+ return true;
+
+ case ',':
+ case ':':
+ case '[':
+ case ']':
+ case '{':
+ case '}':
+ ctx.NextState = 1;
+ ctx.Return = true;
+ return true;
+
+ case '-':
+ ctx.L.string_buffer.Append ((char) ctx.L.input_char);
+ ctx.NextState = 2;
+ return true;
+
+ case '0':
+ ctx.L.string_buffer.Append ((char) ctx.L.input_char);
+ ctx.NextState = 4;
+ return true;
+
+ case 'f':
+ ctx.NextState = 12;
+ return true;
+
+ case 'n':
+ ctx.NextState = 16;
+ return true;
+
+ case 't':
+ ctx.NextState = 9;
+ return true;
+
+ case '\'':
+ if (! ctx.L.allow_single_quoted_strings)
+ return false;
+
+ ctx.L.input_char = '"';
+ ctx.NextState = 23;
+ ctx.Return = true;
+ return true;
+
+ case '/':
+ if (! ctx.L.allow_comments)
+ return false;
+
+ ctx.NextState = 25;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static bool State2 (FsmContext ctx)
+ {
+ ctx.L.GetChar ();
+
+ if (ctx.L.input_char >= '1' && ctx.L.input_char<= '9') {
+ ctx.L.string_buffer.Append ((char) ctx.L.input_char);
+ ctx.NextState = 3;
+ return true;
+ }
+
+ switch (ctx.L.input_char) {
+ case '0':
+ ctx.L.string_buffer.Append ((char) ctx.L.input_char);
+ ctx.NextState = 4;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private static bool State3 (FsmContext ctx)
+ {
+ while (ctx.L.GetChar ()) {
+ if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') {
+ ctx.L.string_buffer.Append ((char) ctx.L.input_char);
+ continue;
+ }
+
+ if (ctx.L.input_char == ' ' ||
+ ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') {
+ ctx.Return = true;
+ ctx.NextState = 1;
+ return true;
+ }
+
+ switch (ctx.L.input_char) {
+ case ',':
+ case ']':
+ case '}':
+ ctx.L.UngetChar ();
+ ctx.Return = true;
+ ctx.NextState = 1;
+ return true;
+
+ case '.':
+ ctx.L.string_buffer.Append ((char) ctx.L.input_char);
+ ctx.NextState = 5;
+ return true;
+
+ case 'e':
+ case 'E':
+ ctx.L.string_buffer.Append ((char) ctx.L.input_char);
+ ctx.NextState = 7;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static bool State4 (FsmContext ctx)
+ {
+ ctx.L.GetChar ();
+
+ if (ctx.L.input_char == ' ' ||
+ ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') {
+ ctx.Return = true;
+ ctx.NextState = 1;
+ return true;
+ }
+
+ switch (ctx.L.input_char) {
+ case ',':
+ case ']':
+ case '}':
+ ctx.L.UngetChar ();
+ ctx.Return = true;
+ ctx.NextState = 1;
+ return true;
+
+ case '.':
+ ctx.L.string_buffer.Append ((char) ctx.L.input_char);
+ ctx.NextState = 5;
+ return true;
+
+ case 'e':
+ case 'E':
+ ctx.L.string_buffer.Append ((char) ctx.L.input_char);
+ ctx.NextState = 7;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private static bool State5 (FsmContext ctx)
+ {
+ ctx.L.GetChar ();
+
+ if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') {
+ ctx.L.string_buffer.Append ((char) ctx.L.input_char);
+ ctx.NextState = 6;
+ return true;
+ }
+
+ return false;
+ }
+
+ private static bool State6 (FsmContext ctx)
+ {
+ while (ctx.L.GetChar ()) {
+ if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') {
+ ctx.L.string_buffer.Append ((char) ctx.L.input_char);
+ continue;
+ }
+
+ if (ctx.L.input_char == ' ' ||
+ ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') {
+ ctx.Return = true;
+ ctx.NextState = 1;
+ return true;
+ }
+
+ switch (ctx.L.input_char) {
+ case ',':
+ case ']':
+ case '}':
+ ctx.L.UngetChar ();
+ ctx.Return = true;
+ ctx.NextState = 1;
+ return true;
+
+ case 'e':
+ case 'E':
+ ctx.L.string_buffer.Append ((char) ctx.L.input_char);
+ ctx.NextState = 7;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static bool State7 (FsmContext ctx)
+ {
+ ctx.L.GetChar ();
+
+ if (ctx.L.input_char >= '0' && ctx.L.input_char<= '9') {
+ ctx.L.string_buffer.Append ((char) ctx.L.input_char);
+ ctx.NextState = 8;
+ return true;
+ }
+
+ switch (ctx.L.input_char) {
+ case '+':
+ case '-':
+ ctx.L.string_buffer.Append ((char) ctx.L.input_char);
+ ctx.NextState = 8;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private static bool State8 (FsmContext ctx)
+ {
+ while (ctx.L.GetChar ()) {
+ if (ctx.L.input_char >= '0' && ctx.L.input_char<= '9') {
+ ctx.L.string_buffer.Append ((char) ctx.L.input_char);
+ continue;
+ }
+
+ if (ctx.L.input_char == ' ' ||
+ ctx.L.input_char >= '\t' && ctx.L.input_char<= '\r') {
+ ctx.Return = true;
+ ctx.NextState = 1;
+ return true;
+ }
+
+ switch (ctx.L.input_char) {
+ case ',':
+ case ']':
+ case '}':
+ ctx.L.UngetChar ();
+ ctx.Return = true;
+ ctx.NextState = 1;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static bool State9 (FsmContext ctx)
+ {
+ ctx.L.GetChar ();
+
+ switch (ctx.L.input_char) {
+ case 'r':
+ ctx.NextState = 10;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private static bool State10 (FsmContext ctx)
+ {
+ ctx.L.GetChar ();
+
+ switch (ctx.L.input_char) {
+ case 'u':
+ ctx.NextState = 11;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private static bool State11 (FsmContext ctx)
+ {
+ ctx.L.GetChar ();
+
+ switch (ctx.L.input_char) {
+ case 'e':
+ ctx.Return = true;
+ ctx.NextState = 1;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private static bool State12 (FsmContext ctx)
+ {
+ ctx.L.GetChar ();
+
+ switch (ctx.L.input_char) {
+ case 'a':
+ ctx.NextState = 13;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private static bool State13 (FsmContext ctx)
+ {
+ ctx.L.GetChar ();
+
+ switch (ctx.L.input_char) {
+ case 'l':
+ ctx.NextState = 14;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private static bool State14 (FsmContext ctx)
+ {
+ ctx.L.GetChar ();
+
+ switch (ctx.L.input_char) {
+ case 's':
+ ctx.NextState = 15;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private static bool State15 (FsmContext ctx)
+ {
+ ctx.L.GetChar ();
+
+ switch (ctx.L.input_char) {
+ case 'e':
+ ctx.Return = true;
+ ctx.NextState = 1;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private static bool State16 (FsmContext ctx)
+ {
+ ctx.L.GetChar ();
+
+ switch (ctx.L.input_char) {
+ case 'u':
+ ctx.NextState = 17;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private static bool State17 (FsmContext ctx)
+ {
+ ctx.L.GetChar ();
+
+ switch (ctx.L.input_char) {
+ case 'l':
+ ctx.NextState = 18;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private static bool State18 (FsmContext ctx)
+ {
+ ctx.L.GetChar ();
+
+ switch (ctx.L.input_char) {
+ case 'l':
+ ctx.Return = true;
+ ctx.NextState = 1;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private static bool State19 (FsmContext ctx)
+ {
+ while (ctx.L.GetChar ()) {
+ switch (ctx.L.input_char) {
+ case '"':
+ ctx.L.UngetChar ();
+ ctx.Return = true;
+ ctx.NextState = 20;
+ return true;
+
+ case '\\':
+ ctx.StateStack = 19;
+ ctx.NextState = 21;
+ return true;
+
+ default:
+ ctx.L.string_buffer.Append ((char) ctx.L.input_char);
+ continue;
+ }
+ }
+
+ return true;
+ }
+
+ private static bool State20 (FsmContext ctx)
+ {
+ ctx.L.GetChar ();
+
+ switch (ctx.L.input_char) {
+ case '"':
+ ctx.Return = true;
+ ctx.NextState = 1;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private static bool State21 (FsmContext ctx)
+ {
+ ctx.L.GetChar ();
+
+ switch (ctx.L.input_char) {
+ case 'u':
+ ctx.NextState = 22;
+ return true;
+
+ case '"':
+ case '\'':
+ case '/':
+ case '\\':
+ case 'b':
+ case 'f':
+ case 'n':
+ case 'r':
+ case 't':
+ ctx.L.string_buffer.Append (
+ ProcessEscChar (ctx.L.input_char));
+ ctx.NextState = ctx.StateStack;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private static bool State22 (FsmContext ctx)
+ {
+ int counter = 0;
+ int mult = 4096;
+
+ ctx.L.unichar = 0;
+
+ while (ctx.L.GetChar ()) {
+
+ if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9' ||
+ ctx.L.input_char >= 'A' && ctx.L.input_char <= 'F' ||
+ ctx.L.input_char >= 'a' && ctx.L.input_char <= 'f') {
+
+ ctx.L.unichar += HexValue (ctx.L.input_char) * mult;
+
+ counter++;
+ mult /= 16;
+
+ if (counter == 4) {
+ ctx.L.string_buffer.Append (
+ Convert.ToChar (ctx.L.unichar));
+ ctx.NextState = ctx.StateStack;
+ return true;
+ }
+
+ continue;
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ private static bool State23 (FsmContext ctx)
+ {
+ while (ctx.L.GetChar ()) {
+ switch (ctx.L.input_char) {
+ case '\'':
+ ctx.L.UngetChar ();
+ ctx.Return = true;
+ ctx.NextState = 24;
+ return true;
+
+ case '\\':
+ ctx.StateStack = 23;
+ ctx.NextState = 21;
+ return true;
+
+ default:
+ ctx.L.string_buffer.Append ((char) ctx.L.input_char);
+ continue;
+ }
+ }
+
+ return true;
+ }
+
+ private static bool State24 (FsmContext ctx)
+ {
+ ctx.L.GetChar ();
+
+ switch (ctx.L.input_char) {
+ case '\'':
+ ctx.L.input_char = '"';
+ ctx.Return = true;
+ ctx.NextState = 1;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private static bool State25 (FsmContext ctx)
+ {
+ ctx.L.GetChar ();
+
+ switch (ctx.L.input_char) {
+ case '*':
+ ctx.NextState = 27;
+ return true;
+
+ case '/':
+ ctx.NextState = 26;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private static bool State26 (FsmContext ctx)
+ {
+ while (ctx.L.GetChar ()) {
+ if (ctx.L.input_char == '\n') {
+ ctx.NextState = 1;
+ return true;
+ }
+ }
+
+ return true;
+ }
+
+ private static bool State27 (FsmContext ctx)
+ {
+ while (ctx.L.GetChar ()) {
+ if (ctx.L.input_char == '*') {
+ ctx.NextState = 28;
+ return true;
+ }
+ }
+
+ return true;
+ }
+
+ private static bool State28 (FsmContext ctx)
+ {
+ while (ctx.L.GetChar ()) {
+ if (ctx.L.input_char == '*')
+ continue;
+
+ if (ctx.L.input_char == '/') {
+ ctx.NextState = 1;
+ return true;
+ }
+
+ ctx.NextState = 27;
+ return true;
+ }
+
+ return true;
+ }
+ #endregion
+
+
+ private bool GetChar ()
+ {
+ if ((input_char = NextChar ()) != -1)
+ return true;
+
+ end_of_input = true;
+ return false;
+ }
+
+ private int NextChar ()
+ {
+ if (input_buffer != 0) {
+ int tmp = input_buffer;
+ input_buffer = 0;
+
+ return tmp;
+ }
+
+ return reader.Read ();
+ }
+
+ public bool NextToken ()
+ {
+ StateHandler handler;
+ fsm_context.Return = false;
+
+ while (true) {
+ handler = fsm_handler_table[state - 1];
+
+ if (! handler (fsm_context))
+ throw new JsonException (input_char);
+
+ if (end_of_input)
+ return false;
+
+ if (fsm_context.Return) {
+ string_value = string_buffer.ToString ();
+ string_buffer.Remove (0, string_buffer.Length);
+ token = fsm_return_table[state - 1];
+
+ if (token == (int) ParserToken.Char)
+ token = input_char;
+
+ state = fsm_context.NextState;
+
+ return true;
+ }
+
+ state = fsm_context.NextState;
+ }
+ }
+
+ private void UngetChar ()
+ {
+ input_buffer = input_char;
+ }
+ }
+}
diff --git a/src/Cake.Issues/Serialization/LitJson/ParserToken.cs b/src/Cake.Issues/Serialization/LitJson/ParserToken.cs
new file mode 100644
index 000000000..85dd10da3
--- /dev/null
+++ b/src/Cake.Issues/Serialization/LitJson/ParserToken.cs
@@ -0,0 +1,49 @@
+#pragma warning disable 1587
+#pragma warning disable 1591
+
+#region Header
+/**
+ * ParserToken.cs
+ * Internal representation of the tokens used by the lexer and the parser.
+ *
+ * The authors disclaim copyright to this source code. For more details, see
+ * the 3rd-Party-License.md file included with this distribution.
+ **/
+
+// This file isn't generated, but this comment is necessary to exclude it from code analysis.
+//
+#endregion
+
+namespace LitJson
+{
+ internal enum ParserToken
+ {
+ // Lexer tokens (see section A.1.1. of the manual)
+ None = System.Char.MaxValue + 1,
+ Number,
+ True,
+ False,
+ Null,
+ CharSeq,
+ // Single char
+ Char,
+
+ // Parser Rules (see section A.2.1 of the manual)
+ Text,
+ Object,
+ ObjectPrime,
+ Pair,
+ PairRest,
+ Array,
+ ArrayPrime,
+ Value,
+ ValueRest,
+ String,
+
+ // End of input
+ End,
+
+ // The empty rule
+ Epsilon
+ }
+}
diff --git a/src/Cake.Issues/SerializableIssue.cs b/src/Cake.Issues/Serialization/SerializableIssue.cs
similarity index 77%
rename from src/Cake.Issues/SerializableIssue.cs
rename to src/Cake.Issues/Serialization/SerializableIssue.cs
index 86c80e743..86579bd1d 100644
--- a/src/Cake.Issues/SerializableIssue.cs
+++ b/src/Cake.Issues/Serialization/SerializableIssue.cs
@@ -1,55 +1,41 @@
-namespace Cake.Issues
+namespace Cake.Issues.Serialization
{
- using System.Runtime.Serialization;
-
///
/// Class for serializing and deserializing an instance.
///
- [DataContract]
internal class SerializableIssue
{
///
- [DataMember]
public string ProjectFileRelativePath { get; set; }
///
- [DataMember]
public string ProjectName { get; set; }
///
- [DataMember]
public string AffectedFileRelativePath { get; set; }
///
- [DataMember]
public int? Line { get; set; }
- ///
- [DataMember]
+ ///
public string Message { get; set; }
///
- [DataMember]
public int? Priority { get; set; }
///
- [DataMember]
public string PriorityName { get; set; }
///
- [DataMember]
public string Rule { get; set; }
///
- [DataMember]
public string RuleUrl { get; set; }
///
- [DataMember]
public string ProviderType { get; set; }
///
- [DataMember]
public string ProviderName { get; set; }
}
}
diff --git a/src/Cake.Issues/Serialization/SerializableIssueExtensions.cs b/src/Cake.Issues/Serialization/SerializableIssueExtensions.cs
new file mode 100644
index 000000000..9b722e83c
--- /dev/null
+++ b/src/Cake.Issues/Serialization/SerializableIssueExtensions.cs
@@ -0,0 +1,47 @@
+namespace Cake.Issues.Serialization
+{
+ using System;
+
+ ///
+ /// Extensions for .
+ ///
+ internal static class SerializableIssueExtensions
+ {
+ ///
+ /// Converts a to an .
+ ///
+ /// Issue which should be converted.
+ /// Converted issue.
+ internal static Issue ToIssue(this SerializableIssue serializableIssue)
+ {
+#pragma warning disable SA1123 // Do not place regions within elements
+ #region DupFinder Exclusion
+#pragma warning restore SA1123 // Do not place regions within elements
+
+ serializableIssue.NotNull(nameof(serializableIssue));
+
+ Uri ruleUrl = null;
+ if (!string.IsNullOrWhiteSpace(serializableIssue.RuleUrl))
+ {
+ ruleUrl = new Uri(serializableIssue.RuleUrl);
+ }
+
+ return new Issue(
+ serializableIssue.ProjectFileRelativePath,
+ serializableIssue.ProjectName,
+ serializableIssue.AffectedFileRelativePath,
+ serializableIssue.Line,
+ serializableIssue.Message,
+ null,
+ null,
+ serializableIssue.Priority,
+ serializableIssue.PriorityName,
+ serializableIssue.Rule,
+ ruleUrl,
+ serializableIssue.ProviderType,
+ serializableIssue.ProviderName);
+
+ #endregion
+ }
+ }
+}
diff --git a/src/Cake.Issues/Serialization/SerializableIssueV2.cs b/src/Cake.Issues/Serialization/SerializableIssueV2.cs
new file mode 100644
index 000000000..9afe5e54c
--- /dev/null
+++ b/src/Cake.Issues/Serialization/SerializableIssueV2.cs
@@ -0,0 +1,75 @@
+namespace Cake.Issues.Serialization
+{
+ using System.Runtime.Serialization;
+
+ ///
+ /// Class for serializing and deserializing an instance.
+ ///
+ [DataContract]
+ internal class SerializableIssueV2
+ {
+ ///
+ /// Gets the version of the serialization format.
+ ///
+ [DataMember]
+ public int Version
+ {
+ get
+ {
+ return 2;
+ }
+ }
+
+ ///
+ [DataMember]
+ public string ProjectFileRelativePath { get; set; }
+
+ ///
+ [DataMember]
+ public string ProjectName { get; set; }
+
+ ///
+ [DataMember]
+ public string AffectedFileRelativePath { get; set; }
+
+ ///
+ [DataMember]
+ public int? Line { get; set; }
+
+ ///
+ [DataMember]
+ public string MessageText { get; set; }
+
+ ///
+ [DataMember]
+ public string MessageMarkdown { get; set; }
+
+ ///
+ [DataMember]
+ public string MessageHtml { get; set; }
+
+ ///
+ [DataMember]
+ public int? Priority { get; set; }
+
+ ///
+ [DataMember]
+ public string PriorityName { get; set; }
+
+ ///
+ [DataMember]
+ public string Rule { get; set; }
+
+ ///
+ [DataMember]
+ public string RuleUrl { get; set; }
+
+ ///
+ [DataMember]
+ public string ProviderType { get; set; }
+
+ ///
+ [DataMember]
+ public string ProviderName { get; set; }
+ }
+}
diff --git a/src/Cake.Issues/Serialization/SerializableIssueV2Extensions.cs b/src/Cake.Issues/Serialization/SerializableIssueV2Extensions.cs
new file mode 100644
index 000000000..4ab0491f8
--- /dev/null
+++ b/src/Cake.Issues/Serialization/SerializableIssueV2Extensions.cs
@@ -0,0 +1,47 @@
+namespace Cake.Issues.Serialization
+{
+ using System;
+
+ ///
+ /// Extensions for .
+ ///
+ internal static class SerializableIssueV2Extensions
+ {
+ ///
+ /// Converts a to an .
+ ///
+ /// Issue which should be converted.
+ /// Converted issue.
+ internal static Issue ToIssue(this SerializableIssueV2 serializableIssue)
+ {
+#pragma warning disable SA1123 // Do not place regions within elements
+ #region DupFinder Exclusion
+#pragma warning restore SA1123 // Do not place regions within elements
+
+ serializableIssue.NotNull(nameof(serializableIssue));
+
+ Uri ruleUrl = null;
+ if (!string.IsNullOrWhiteSpace(serializableIssue.RuleUrl))
+ {
+ ruleUrl = new Uri(serializableIssue.RuleUrl);
+ }
+
+ return new Issue(
+ serializableIssue.ProjectFileRelativePath,
+ serializableIssue.ProjectName,
+ serializableIssue.AffectedFileRelativePath,
+ serializableIssue.Line,
+ serializableIssue.MessageText,
+ serializableIssue.MessageHtml,
+ serializableIssue.MessageMarkdown,
+ serializableIssue.Priority,
+ serializableIssue.PriorityName,
+ serializableIssue.Rule,
+ ruleUrl,
+ serializableIssue.ProviderType,
+ serializableIssue.ProviderName);
+
+ #endregion
+ }
+ }
+}