diff --git a/.appveyor.yml b/.appveyor.yml
new file mode 100644
index 0000000..bd21071
--- /dev/null
+++ b/.appveyor.yml
@@ -0,0 +1,31 @@
+#---------------------------------#
+# Build Image #
+#---------------------------------#
+image: Visual Studio 2017
+
+#---------------------------------#
+# Build Script #
+#---------------------------------#
+build_script:
+ - ps: .\build.ps1 -Target AppVeyor
+
+# Tests
+test: off
+
+#---------------------------------#
+# Branches to build #
+#---------------------------------#
+branches:
+ # Whitelist
+ only:
+ - develop
+ - master
+ - /release/.*/
+ - /hotfix/.*/
+
+#---------------------------------#
+# Build Cache #
+#---------------------------------#
+cache:
+- src\packages -> src\**\packages.config
+- tools -> setup.cake
\ No newline at end of file
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..1ff0c42
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,63 @@
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* text=auto
+
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs diff=csharp
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln merge=binary
+#*.csproj merge=binary
+#*.vbproj merge=binary
+#*.vcxproj merge=binary
+#*.vcproj merge=binary
+#*.dbproj merge=binary
+#*.fsproj merge=binary
+#*.lsproj merge=binary
+#*.wixproj merge=binary
+#*.modelproj merge=binary
+#*.sqlproj merge=binary
+#*.wwaproj merge=binary
+
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg binary
+#*.png binary
+#*.gif binary
+
+###############################################################################
+# diff behavior for common document formats
+#
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the
+# entries below.
+###############################################################################
+#*.doc diff=astextplain
+#*.DOC diff=astextplain
+#*.docx diff=astextplain
+#*.DOCX diff=astextplain
+#*.dot diff=astextplain
+#*.DOT diff=astextplain
+#*.pdf diff=astextplain
+#*.PDF diff=astextplain
+#*.rtf diff=astextplain
+#*.RTF diff=astextplain
diff --git a/.gitignore b/.gitignore
index 940794e..ba4e60c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,14 @@
+# Project specific
+
+BuildArtifacts/
+
+# Created by https://www.gitignore.io/api/cake,visualstudio
+
+### Cake ###
+tools/*
+!tools/packages.config
+
+### VisualStudio ###
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
@@ -148,9 +159,11 @@ publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
-# TODO: Comment the next line if you want to checkin your web deploy settings
-# but database connection strings (with potential passwords) will be unencrypted
-*.pubxml
+# TODO: Uncomment the next line to ignore your web deploy settings.
+# By default, sensitive information, such as encrypted password
+# should be stored in the .pubxml.user file.
+#*.pubxml
+*.pubxml.user
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
@@ -286,3 +299,9 @@ __pycache__/
*.btm.cs
*.odx.cs
*.xsd.cs
+
+### VisualStudio Patch ###
+# By default, sensitive information, such as encrypted password
+# should be stored in the .pubxml.user file.
+
+# End of https://www.gitignore.io/api/cake,visualstudio
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..eb79eee
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,10 @@
+language: csharp
+script:
+ - ./build.sh -v diagnostic
+os:
+ - linux
+ - osx
+cache:
+ directories:
+ - packages
+ - tools
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..078295e
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,35 @@
+# Contribution Guidelines
+
+This repository uses [GitFlow] with default configuration.
+Development is happening on `develop` branch.
+
+To contribute:
+
+* Fork this repository.
+* Create a feature branch from `develop`.
+* Implement your changes.
+* Push your feature branch.
+* Create a pull request.
+
+## Build
+
+To build this package we are using Cake.
+
+On Windows PowerShell run:
+
+```powershell
+./build
+```
+
+On OSX/Linux run:
+
+```bash
+./build.sh
+```
+
+## Release
+
+See [Cake.Recipe documentation] how to create a new release of this addin.
+
+[GitFlow]: (http://nvie.com/posts/a-successful-git-branching-model/)
+[Cake.Recipe documentation]: https://cake-contrib.github.io/Cake.Recipe/docs/usage/creating-release
\ No newline at end of file
diff --git a/GitReleaseManager.yaml b/GitReleaseManager.yaml
new file mode 100644
index 0000000..721c1ba
--- /dev/null
+++ b/GitReleaseManager.yaml
@@ -0,0 +1,12 @@
+issue-labels-include:
+- Breaking change
+- Feature
+- Bug
+- Improvement
+- Documentation
+issue-labels-exclude:
+- Build
+issue-labels-alias:
+ - name: Documentation
+ header: Documentation
+ plural: Documentation
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
index f90383f..e052ef6 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2017 Pascal Berger
+Copyright (c) 2017 BBT Software AG and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 78f0579..7de82d6 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,40 @@
-# Cake.Issues.MsBuild
\ No newline at end of file
+# MsBuild Issue Provider for Cake.Issues Addin
+
+This addin for the Cake Build Automation System allows you to read issues logged as warnings by MsBuild
+using the [Cake Issues addin](https://github.com/cake-contrib/Cake.Issues).
+
+For more information about this add-in see the [Cake.Issues website](https://cake-contrib.github.io/Cake.Issues.Website)
+and for general information about the Cake build automation system see the [Cake website](http://cakebuild.net)
+
+[](https://github.com/cake-contrib/Cake.Issues.MsBuild/blob/feature/build/LICENSE)
+
+## Information
+
+| | Stable | Pre-release |
+|:--:|:--:|:--:|
+|GitHub Release|-|[](https://github.com/cake-contrib/Cake.Issues.MsBuild/releases/latest)|
+|NuGet|[](https://www.nuget.org/packages/Cake.Issues.MsBuild)|[](https://www.nuget.org/packages/Cake.Issues.MsBuild)|
+
+## Build Status
+
+|Develop|Master|
+|:--:|:--:|
+|[](https://ci.appveyor.com/project/cakecontrib/cake-issues-msbuild/branch/develop)|[](https://ci.appveyor.com/project/cakecontrib/cake-issues-msbuild/branch/master)|
+
+## Code Coverage
+
+[](https://coveralls.io/github/cake-contrib/Cake.Issues.MsBuild?branch=develop)
+
+## Quick Links
+
+- [Documentation](https://cake-contrib.github.io/Cake.Issues.Website)
+
+## Chat Room
+
+Come join in the conversation about this addin in our Gitter Chat Room
+
+[](https://gitter.im/cake-contrib/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+## Contributing
+
+Contributions are welcome. See [Contribution Guidelines](CONTRIBUTING.md).
\ No newline at end of file
diff --git a/build.ps1 b/build.ps1
new file mode 100644
index 0000000..bdfb32b
--- /dev/null
+++ b/build.ps1
@@ -0,0 +1,184 @@
+##########################################################################
+# This is the Cake bootstrapper script for PowerShell.
+# This file was downloaded from https://github.com/cake-build/resources
+# Feel free to change this file to fit your needs.
+##########################################################################
+
+<#
+.SYNOPSIS
+This is a Powershell script to bootstrap a Cake build.
+.DESCRIPTION
+This Powershell script will download NuGet if missing, restore NuGet tools (including Cake)
+and execute your Cake build script with the parameters you provide.
+.PARAMETER Script
+The build script to execute.
+.PARAMETER Target
+The build script target to run.
+.PARAMETER Configuration
+The build configuration to use.
+.PARAMETER Verbosity
+Specifies the amount of information to be displayed.
+.PARAMETER Experimental
+Tells Cake to use the latest Roslyn release.
+.PARAMETER WhatIf
+Performs a dry run of the build script.
+No tasks will be executed.
+.PARAMETER Mono
+Tells Cake to use the Mono scripting engine.
+.PARAMETER SkipToolPackageRestore
+Skips restoring of packages.
+.PARAMETER ScriptArgs
+Remaining arguments are added here.
+.LINK
+http://cakebuild.net
+#>
+
+[CmdletBinding()]
+Param(
+ [string]$Script = "setup.cake",
+ [string]$Target = "Default",
+ [ValidateSet("Release", "Debug")]
+ [string]$Configuration = "Release",
+ [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")]
+ [string]$Verbosity = "Verbose",
+ [switch]$Experimental,
+ [Alias("DryRun","Noop")]
+ [switch]$WhatIf,
+ [switch]$Mono,
+ [switch]$SkipToolPackageRestore,
+ [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
+ [string[]]$ScriptArgs
+)
+
+[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null
+function MD5HashFile([string] $filePath)
+{
+ if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf))
+ {
+ return $null
+ }
+
+ [System.IO.Stream] $file = $null;
+ [System.Security.Cryptography.MD5] $md5 = $null;
+ try
+ {
+ $md5 = [System.Security.Cryptography.MD5]::Create()
+ $file = [System.IO.File]::OpenRead($filePath)
+ return [System.BitConverter]::ToString($md5.ComputeHash($file))
+ }
+ finally
+ {
+ if ($file -ne $null)
+ {
+ $file.Dispose()
+ }
+ }
+}
+
+Write-Host "Preparing to run build script..."
+
+if(!$PSScriptRoot){
+ $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
+}
+
+$TOOLS_DIR = Join-Path $PSScriptRoot "tools"
+$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe"
+$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe"
+$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
+$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config"
+$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum"
+
+# Should we use mono?
+$UseMono = "";
+if($Mono.IsPresent) {
+ Write-Verbose -Message "Using the Mono based scripting engine."
+ $UseMono = "-mono"
+}
+
+# Should we use the new Roslyn?
+$UseExperimental = "";
+if($Experimental.IsPresent -and !($Mono.IsPresent)) {
+ Write-Verbose -Message "Using experimental version of Roslyn."
+ $UseExperimental = "-experimental"
+}
+
+# Is this a dry run?
+$UseDryRun = "";
+if($WhatIf.IsPresent) {
+ $UseDryRun = "-dryrun"
+}
+
+# Make sure tools folder exists
+if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) {
+ Write-Verbose -Message "Creating tools directory..."
+ New-Item -Path $TOOLS_DIR -Type directory | out-null
+}
+
+# Make sure that packages.config exist.
+if (!(Test-Path $PACKAGES_CONFIG)) {
+ Write-Verbose -Message "Downloading packages.config..."
+ try { (New-Object System.Net.WebClient).DownloadFile("http://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch {
+ Throw "Could not download packages.config."
+ }
+}
+
+# Try find NuGet.exe in path if not exists
+if (!(Test-Path $NUGET_EXE)) {
+ Write-Verbose -Message "Trying to find nuget.exe in PATH..."
+ $existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_) }
+ $NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1
+ if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) {
+ Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)."
+ $NUGET_EXE = $NUGET_EXE_IN_PATH.FullName
+ }
+}
+
+# Try download NuGet.exe if not exists
+if (!(Test-Path $NUGET_EXE)) {
+ Write-Verbose -Message "Downloading NuGet.exe..."
+ try {
+ (New-Object System.Net.WebClient).DownloadFile($NUGET_URL, $NUGET_EXE)
+ } catch {
+ Throw "Could not download NuGet.exe."
+ }
+}
+
+# Save nuget.exe path to environment to be available to child processed
+$ENV:NUGET_EXE = $NUGET_EXE
+
+# Restore tools from NuGet?
+if(-Not $SkipToolPackageRestore.IsPresent) {
+ Push-Location
+ Set-Location $TOOLS_DIR
+
+ # Check for changes in packages.config and remove installed tools if true.
+ [string] $md5Hash = MD5HashFile($PACKAGES_CONFIG)
+ if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or
+ ($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) {
+ Write-Verbose -Message "Missing or changed package.config hash..."
+ Remove-Item * -Recurse -Exclude packages.config,nuget.exe
+ }
+
+ Write-Verbose -Message "Restoring tools from NuGet..."
+ $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -PreRelease -OutputDirectory `"$TOOLS_DIR`" -Source https://www.myget.org/F/cake/api/v3/index.json"
+
+ if ($LASTEXITCODE -ne 0) {
+ Throw "An error occured while restoring NuGet tools."
+ }
+ else
+ {
+ $md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII"
+ }
+ Write-Verbose -Message ($NuGetOutput | out-string)
+ Pop-Location
+}
+
+# Make sure that Cake has been installed.
+if (!(Test-Path $CAKE_EXE)) {
+ Throw "Could not find Cake.exe at $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
diff --git a/build.sh b/build.sh
new file mode 100644
index 0000000..a541ec1
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,82 @@
+#!/usr/bin/env bash
+###############################################################
+# This is the Cake bootstrapper script that is responsible for
+# downloading Cake and all specified tools from NuGet.
+###############################################################
+
+# Define directories.
+SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
+TOOLS_DIR=$SCRIPT_DIR/tools
+NUGET_EXE=$TOOLS_DIR/nuget.exe
+CAKE_EXE=$TOOLS_DIR/Cake/Cake.exe
+
+# Define default arguments.
+SCRIPT="setup.cake"
+TARGET="Default"
+CONFIGURATION="Release"
+VERBOSITY="verbose"
+DRYRUN=
+SHOW_VERSION=false
+SCRIPT_ARGUMENTS=()
+
+# Parse arguments.
+for i in "$@"; do
+ case $1 in
+ -s|--script) SCRIPT="$2"; shift ;;
+ -t|--target) TARGET="$2"; shift ;;
+ -c|--configuration) CONFIGURATION="$2"; shift ;;
+ -v|--verbosity) VERBOSITY="$2"; shift ;;
+ -d|--dryrun) DRYRUN="-dryrun" ;;
+ --version) SHOW_VERSION=true ;;
+ --) shift; SCRIPT_ARGUMENTS+=("$@"); break ;;
+ *) SCRIPT_ARGUMENTS+=("$1") ;;
+ esac
+ shift
+done
+
+# Make sure the tools folder exist.
+if [ ! -d $TOOLS_DIR ]; then
+ mkdir $TOOLS_DIR
+fi
+
+# Make sure that packages.config exist.
+if [ ! -f $TOOLS_DIR/packages.config ]; then
+ echo "Downloading packages.config..."
+ curl -Lsfo $TOOLS_DIR/packages.config http://cakebuild.net/bootstrapper/packages
+ if [ $? -ne 0 ]; then
+ echo "An error occured while downloading packages.config."
+ exit 1
+ fi
+fi
+
+# Download NuGet if it does not exist.
+if [ ! -f $NUGET_EXE ]; then
+ echo "Downloading NuGet..."
+ curl -Lsfo $NUGET_EXE https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
+ if [ $? -ne 0 ]; then
+ echo "An error occured while downloading nuget.exe."
+ exit 1
+ fi
+fi
+
+# Restore tools from NuGet.
+pushd $TOOLS_DIR >/dev/null
+mono $NUGET_EXE install -ExcludeVersion -PreRelease -Source https://www.myget.org/F/cake/api/v3/index.json
+if [ $? -ne 0 ]; then
+ echo "Could not restore NuGet packages."
+ exit 1
+fi
+popd >/dev/null
+
+# Make sure that Cake has been installed.
+if [ ! -f $CAKE_EXE ]; then
+ echo "Could not find Cake.exe at '$CAKE_EXE'."
+ exit 1
+fi
+
+# Start Cake
+if $SHOW_VERSION; then
+ exec mono $CAKE_EXE -version
+else
+ exec mono $CAKE_EXE $SCRIPT -verbosity=$VERBOSITY -configuration=$CONFIGURATION -target=$TARGET $DRYRUN "${SCRIPT_ARGUMENTS[@]}"
+fi
diff --git a/nuspec/nuget/Cake.Issues.MsBuild.nuspec b/nuspec/nuget/Cake.Issues.MsBuild.nuspec
new file mode 100644
index 0000000..634466c
--- /dev/null
+++ b/nuspec/nuget/Cake.Issues.MsBuild.nuspec
@@ -0,0 +1,33 @@
+
+
+
+ Cake.Issues.MsBuild
+ Cake.Issues.MsBuild
+ 0.0.0
+ BBT Software AG and contributors
+ bbtsoftware, pascalberger, cake-contrib
+ MsBuild support for the Cake.Issues addin for Cake Build Automation System
+
+The MsBuild support for the Cake.Issues addin for Cake allows you to read issues logged as warnings in a MsBuild log.
+
+This addin provides the aliases for reading MsBuild warnings and providing them to the Cake.Issues addin.
+It also requires the core Cake.Issues addin.
+
+There are also additional addins for generating reports or posting issues to pull requests.
+
+See the Project Site for an overview of the whole ecosystem of addins for working with issues in Cake scripts.
+
+ https://github.com/cake-contrib/Cake.Issues.MsBuild/blob/develop/LICENSE
+ http://cake-contrib.github.io/Cake.Issues.Website
+ https://cdn.rawgit.com/cake-contrib/graphics/a5cf0f881c390650144b2243ae551d5b9f836196/png/cake-contrib-medium.png
+ false
+ Copyright © 2017 BBT Software AG and contributors
+ Cake Script Cake-Issues Cake-IssueProvider CodeAnalysis Linting MsBuild
+ https://github.com/cake-contrib/Cake.Issues.MsBuild/releases/tag/0.1.0
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/setup.cake b/setup.cake
new file mode 100644
index 0000000..657a438
--- /dev/null
+++ b/setup.cake
@@ -0,0 +1,23 @@
+#load nuget:https://www.myget.org/F/cake-contrib/api/v2?package=Cake.Recipe&prerelease
+
+Environment.SetVariableNames();
+
+BuildParameters.SetParameters(
+ context: Context,
+ buildSystem: BuildSystem,
+ sourceDirectoryPath: "./src",
+ title: "Cake.Issues.MsBuild",
+ repositoryOwner: "cake-contrib",
+ repositoryName: "Cake.Issues.MsBuild",
+ appVeyorAccountName: "cakecontrib");
+
+BuildParameters.PrintParameters(Context);
+
+ToolSettings.SetToolSettings(
+ context: Context,
+ dupFinderExcludePattern: new string[] { BuildParameters.RootDirectoryPath + "/src/Cake.Issues.MsBuild.Tests/*.cs" },
+ testCoverageFilter: "+[*]* -[xunit.*]* -[Cake.Core]* -[Cake.Testing]* -[*.Tests]* -[Cake.Issues]* -[Cake.Issues.Testing]*",
+ testCoverageExcludeByAttribute: "*.ExcludeFromCodeCoverage*",
+ testCoverageExcludeByFile: "*/*Designer.cs;*/*.g.cs;*/*.g.i.cs");
+
+Build.Run();
diff --git a/src/Cake.Issues.MsBuild.Tests.ruleset b/src/Cake.Issues.MsBuild.Tests.ruleset
new file mode 100644
index 0000000..73e07dc
--- /dev/null
+++ b/src/Cake.Issues.MsBuild.Tests.ruleset
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Cake.Issues.MsBuild.Tests/Cake.Issues.MsBuild.Tests.csproj b/src/Cake.Issues.MsBuild.Tests/Cake.Issues.MsBuild.Tests.csproj
new file mode 100644
index 0000000..5f7d7f5
--- /dev/null
+++ b/src/Cake.Issues.MsBuild.Tests/Cake.Issues.MsBuild.Tests.csproj
@@ -0,0 +1,110 @@
+
+
+
+
+
+ Debug
+ AnyCPU
+ {C69329F6-A4D1-4E33-BD9D-5E59973BE781}
+ Library
+ Properties
+ Cake.Issues.MsBuild.Tests
+ Cake.Issues.MsBuild.Tests
+ v4.5.2
+ 512
+
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ ..\Cake.Issues.MsBuild.Tests.ruleset
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ ..\Cake.Issues.MsBuild.Tests.ruleset
+
+
+
+ ..\packages\Cake.Core.0.16.2\lib\net45\Cake.Core.dll
+
+
+ ..\packages\Cake.Issues.0.1.0-beta0001\lib\net45\Cake.Issues.dll
+
+
+ ..\packages\Cake.Issues.Testing.0.1.0-beta0001\lib\net45\Cake.Issues.Testing.dll
+
+
+ ..\packages\Cake.Testing.0.16.2\lib\net45\Cake.Testing.dll
+
+
+ ..\packages\Shouldly.2.8.3\lib\net451\Shouldly.dll
+
+
+
+
+
+
+
+
+
+
+ ..\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll
+
+
+ ..\packages\xunit.assert.2.2.0\lib\netstandard1.1\xunit.assert.dll
+
+
+ ..\packages\xunit.extensibility.core.2.2.0\lib\netstandard1.1\xunit.core.dll
+
+
+ ..\packages\xunit.extensibility.execution.2.2.0\lib\net452\xunit.execution.desktop.dll
+
+
+
+
+
+
+
+
+
+
+
+
+ {1a6c74ce-4775-458a-b013-bde1986c5b88}
+ Cake.Issues.MsBuild
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
\ No newline at end of file
diff --git a/src/Cake.Issues.MsBuild.Tests/MsBuildIssuesProviderFixture.cs b/src/Cake.Issues.MsBuild.Tests/MsBuildIssuesProviderFixture.cs
new file mode 100644
index 0000000..830f03e
--- /dev/null
+++ b/src/Cake.Issues.MsBuild.Tests/MsBuildIssuesProviderFixture.cs
@@ -0,0 +1,49 @@
+namespace Cake.Issues.MsBuild.Tests
+{
+ using System.Collections.Generic;
+ using System.IO;
+ using Cake.Testing;
+ using Core.Diagnostics;
+ using IssueProvider;
+
+ internal class MsBuildIssuesProviderFixture
+ {
+ public MsBuildIssuesProviderFixture(string fileResourceName)
+ {
+ this.Log = new FakeLog { Verbosity = Verbosity.Normal };
+
+ using (var stream = this.GetType().Assembly.GetManifestResourceStream("Cake.Issues.MsBuild.Tests.Testfiles." + fileResourceName))
+ {
+ using (var sr = new StreamReader(stream))
+ {
+ this.MsBuildIssuesSettings =
+ MsBuildIssuesSettings.FromContent(
+ sr.ReadToEnd(),
+ new XmlFileLoggerFormat(this.Log));
+ }
+ }
+
+ this.RepositorySettings =
+ new RepositorySettings(@"c:\Source\Cake.Issues.MsBuild");
+ }
+
+ public FakeLog Log { get; set; }
+
+ public MsBuildIssuesSettings MsBuildIssuesSettings { get; set; }
+
+ public RepositorySettings RepositorySettings { get; set; }
+
+ public MsBuildIssuesProvider Create()
+ {
+ var provider = new MsBuildIssuesProvider(this.Log, this.MsBuildIssuesSettings);
+ provider.Initialize(this.RepositorySettings);
+ return provider;
+ }
+
+ public IEnumerable ReadIssues()
+ {
+ var issueProvider = this.Create();
+ return issueProvider.ReadIssues(IssueCommentFormat.PlainText);
+ }
+ }
+}
diff --git a/src/Cake.Issues.MsBuild.Tests/MsBuildIssuesProviderTests.cs b/src/Cake.Issues.MsBuild.Tests/MsBuildIssuesProviderTests.cs
new file mode 100644
index 0000000..0e08b9a
--- /dev/null
+++ b/src/Cake.Issues.MsBuild.Tests/MsBuildIssuesProviderTests.cs
@@ -0,0 +1,39 @@
+namespace Cake.Issues.MsBuild.Tests
+{
+ using Cake.Testing;
+ using Testing;
+ using Xunit;
+
+ public class MsBuildIssuesProviderTests
+ {
+ public sealed class TheMsBuildCodeAnalysisProviderCtor
+ {
+ [Fact]
+ public void Should_Throw_If_Log_Is_Null()
+ {
+ // Given / When
+ var result = Record.Exception(() =>
+ new MsBuildIssuesProvider(
+ null,
+ MsBuildIssuesSettings.FromContent(
+ "Foo",
+ new XmlFileLoggerFormat(new FakeLog()))));
+
+ // Then
+ result.IsArgumentNullException("log");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Settings_Are_Null()
+ {
+ var result = Record.Exception(() =>
+ new MsBuildIssuesProvider(
+ new FakeLog(),
+ null));
+
+ // Then
+ result.IsArgumentNullException("settings");
+ }
+ }
+ }
+}
diff --git a/src/Cake.Issues.MsBuild.Tests/MsBuildIssuesSettingsTests.cs b/src/Cake.Issues.MsBuild.Tests/MsBuildIssuesSettingsTests.cs
new file mode 100644
index 0000000..1d70647
--- /dev/null
+++ b/src/Cake.Issues.MsBuild.Tests/MsBuildIssuesSettingsTests.cs
@@ -0,0 +1,163 @@
+namespace Cake.Issues.MsBuild.Tests
+{
+ using System;
+ using System.IO;
+ using System.Linq;
+ using System.Text;
+ using Cake.Testing;
+ using Shouldly;
+ using Testing;
+ using Xunit;
+
+ public class MsBuildIssuesSettingsTests
+ {
+ public sealed class TheMsBuildCodeAnalysisSettingsCtor
+ {
+ [Fact]
+ public void Should_Throw_If_LogFilePath_Is_Null()
+ {
+ // Given / When
+ var result = Record.Exception(() =>
+ MsBuildIssuesSettings.FromFilePath(
+ null,
+ new XmlFileLoggerFormat(new FakeLog())));
+
+ // Then
+ result.IsArgumentNullException("logFilePath");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Format_For_LogFilePath_Is_Null()
+ {
+ // Given / When
+ var result = Record.Exception(() =>
+ MsBuildIssuesSettings.FromFilePath(
+ @"C:\foo.log",
+ null));
+
+ // Then
+ result.IsArgumentNullException("format");
+ }
+
+ [Fact]
+ public void Should_Throw_If_LogFileContent_Is_Null()
+ {
+ // Given / When
+ var result = Record.Exception(() =>
+ MsBuildIssuesSettings.FromContent(
+ null,
+ new XmlFileLoggerFormat(new FakeLog())));
+
+ // Then
+ result.IsArgumentNullException("logFileContent");
+ }
+
+ [Fact]
+ public void Should_Throw_If_LogFileContent_Is_Empty()
+ {
+ // Given / When
+ var result = Record.Exception(() =>
+ MsBuildIssuesSettings.FromContent(
+ string.Empty,
+ new XmlFileLoggerFormat(new FakeLog())));
+
+ // Then
+ result.IsArgumentOutOfRangeException("logFileContent");
+ }
+
+ [Fact]
+ public void Should_Throw_If_LogFileContent_Is_WhiteSpace()
+ {
+ // Given / When
+ var result = Record.Exception(() =>
+ MsBuildIssuesSettings.FromContent(
+ " ",
+ new XmlFileLoggerFormat(new FakeLog())));
+
+ // Then
+ result.IsArgumentOutOfRangeException("logFileContent");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Format_For_LogFileContent_Is_Null()
+ {
+ // Given / When
+ var result = Record.Exception(() =>
+ MsBuildIssuesSettings.FromContent(
+ "foo",
+ null));
+
+ // Then
+ result.IsArgumentNullException("format");
+ }
+
+ [Fact]
+ public void Should_Set_Property_Values_Passed_To_Constructor()
+ {
+ // Given
+ const string logFileContent = "foo";
+ var format = new XmlFileLoggerFormat(new FakeLog());
+
+ // When
+ var settings = MsBuildIssuesSettings.FromContent(logFileContent, format);
+
+ // Then
+ settings.LogFileContent.ShouldBe(logFileContent);
+ settings.Format.ShouldBe(format);
+ }
+
+ [Fact]
+ public void Should_Read_File_From_Disk()
+ {
+ var fileName = Path.GetTempFileName();
+ try
+ {
+ // Given
+ string expected;
+ using (var ms = new MemoryStream())
+ using (var stream = this.GetType().Assembly.GetManifestResourceStream("Cake.Issues.MsBuild.Tests.Testfiles.IssueWithFile.xml"))
+ {
+ stream.CopyTo(ms);
+ var data = ms.ToArray();
+
+ using (var file = new FileStream(fileName, FileMode.Create, FileAccess.Write))
+ {
+ file.Write(data, 0, data.Length);
+ }
+
+ expected = ConvertFromUtf8(data);
+ }
+
+ // When
+ var settings =
+ MsBuildIssuesSettings.FromFilePath(
+ fileName,
+ new XmlFileLoggerFormat(new FakeLog()));
+
+ // Then
+ settings.LogFileContent.ShouldBe(expected);
+ }
+ finally
+ {
+ if (File.Exists(fileName))
+ {
+ File.Delete(fileName);
+ }
+ }
+ }
+
+ private static string ConvertFromUtf8(byte[] bytes)
+ {
+ var enc = new UTF8Encoding(true);
+ var preamble = enc.GetPreamble();
+
+ if (preamble.Where((p, i) => p != bytes[i]).Any())
+ {
+ throw new ArgumentException("Not utf8-BOM");
+ }
+
+ return enc.GetString(bytes.Skip(preamble.Length).ToArray());
+ }
+ }
+ }
+}
diff --git a/src/Cake.Issues.MsBuild.Tests/MsBuildRuleUrlResolverTests.cs b/src/Cake.Issues.MsBuild.Tests/MsBuildRuleUrlResolverTests.cs
new file mode 100644
index 0000000..c0ed31d
--- /dev/null
+++ b/src/Cake.Issues.MsBuild.Tests/MsBuildRuleUrlResolverTests.cs
@@ -0,0 +1,96 @@
+namespace Cake.Issues.MsBuild.Tests
+{
+ using System;
+ using Shouldly;
+ using Testing;
+ using Xunit;
+
+ public class MsBuildRuleUrlResolverTests
+ {
+ public sealed class TheResolveRuleUrlMethod
+ {
+ [Fact]
+ public void Should_Throw_If_Rule_Is_Null()
+ {
+ // Given / When
+ var result = Record.Exception(() => MsBuildRuleUrlResolver.Instance.ResolveRuleUrl(null));
+
+ // Then
+ result.IsArgumentNullException("rule");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Rule_Is_Empty()
+ {
+ // Given / When
+ var result = Record.Exception(() => MsBuildRuleUrlResolver.Instance.ResolveRuleUrl(string.Empty));
+
+ // Then
+ result.IsArgumentOutOfRangeException("rule");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Rule_Is_WhiteSpace()
+ {
+ // Given / When
+ var result = Record.Exception(() => MsBuildRuleUrlResolver.Instance.ResolveRuleUrl(" "));
+
+ // Then
+ result.IsArgumentOutOfRangeException("rule");
+ }
+
+ [Theory]
+ [InlineData("CA2201", "https://www.google.im/search?q=\"CA2201:\"+site:msdn.microsoft.com")]
+ [InlineData("SA1652", "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1652.md")]
+ public void Should_Resolve_Url(string rule, string expectedUrl)
+ {
+ // Given
+ var urlResolver = MsBuildRuleUrlResolver.Instance;
+
+ // When
+ var ruleUrl = urlResolver.ResolveRuleUrl(rule);
+
+ // Then
+ ruleUrl.ToString().ShouldBe(expectedUrl);
+ }
+
+ [Theory]
+ [InlineData("CA")]
+ [InlineData("2201")]
+ [InlineData("CA2201Foo")]
+ [InlineData("CS0219")]
+ public void Should_Return_Null_For_Unknown_Rules(string rule)
+ {
+ // Given
+ var urlResolver = MsBuildRuleUrlResolver.Instance;
+
+ // When
+ var ruleUrl = urlResolver.ResolveRuleUrl(rule);
+
+ // Then
+ ruleUrl.ShouldBeNull();
+ }
+
+ [Fact]
+ public void Should_Resolve_Url_From_Custom_Resolvers()
+ {
+ // Given
+ const string foo = "FOO123";
+ const string fooUrl = "http://foo.com/";
+ const string bar = "BAR123";
+ const string barUrl = "http://bar.com/";
+ var urlResolver = MsBuildRuleUrlResolver.Instance;
+ urlResolver.AddUrlResolver(x => x.Rule == foo ? new Uri(fooUrl) : null);
+ urlResolver.AddUrlResolver(x => x.Rule == bar ? new Uri(barUrl) : null);
+
+ // When
+ var fooRuleUrl = urlResolver.ResolveRuleUrl(foo);
+ var barRuleUrl = urlResolver.ResolveRuleUrl(bar);
+
+ // Then
+ fooRuleUrl.ToString().ShouldBe(fooUrl);
+ barRuleUrl.ToString().ShouldBe(barUrl);
+ }
+ }
+ }
+}
diff --git a/src/Cake.Issues.MsBuild.Tests/Properties/AssemblyInfo.cs b/src/Cake.Issues.MsBuild.Tests/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..c2f0bc3
--- /dev/null
+++ b/src/Cake.Issues.MsBuild.Tests/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Cake.Issues.MsBuild")]
+[assembly: AssemblyDescription("MsBuild support for the Cake.Issues Addin for Cake Build Automation System")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("BBT Software AG")]
+[assembly: AssemblyProduct("Cake.Issues")]
+[assembly: AssemblyCopyright("Copyright © 2017 BBT Software AG, Root/Zermatt, Switzerland")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c69329f6-a4d1-4e33-bd9d-5e59973be781")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/Cake.Issues.MsBuild.Tests/Testfiles/IssueWithFile.xml b/src/Cake.Issues.MsBuild.Tests/Testfiles/IssueWithFile.xml
new file mode 100644
index 0000000..f4cc173
--- /dev/null
+++ b/src/Cake.Issues.MsBuild.Tests/Testfiles/IssueWithFile.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/Cake.Issues.MsBuild.Tests/Testfiles/IssueWithOnlyFileName.xml b/src/Cake.Issues.MsBuild.Tests/Testfiles/IssueWithOnlyFileName.xml
new file mode 100644
index 0000000..965aea2
--- /dev/null
+++ b/src/Cake.Issues.MsBuild.Tests/Testfiles/IssueWithOnlyFileName.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Cake.Issues.MsBuild.Tests/Testfiles/IssueWithoutFile.xml b/src/Cake.Issues.MsBuild.Tests/Testfiles/IssueWithoutFile.xml
new file mode 100644
index 0000000..fd20b4d
--- /dev/null
+++ b/src/Cake.Issues.MsBuild.Tests/Testfiles/IssueWithoutFile.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/Cake.Issues.MsBuild.Tests/XmlFileLoggerFormatTests.cs b/src/Cake.Issues.MsBuild.Tests/XmlFileLoggerFormatTests.cs
new file mode 100644
index 0000000..d07e4dd
--- /dev/null
+++ b/src/Cake.Issues.MsBuild.Tests/XmlFileLoggerFormatTests.cs
@@ -0,0 +1,115 @@
+namespace Cake.Issues.MsBuild.Tests
+{
+ using System.Linq;
+ using Core.IO;
+ using IssueProvider;
+ using Shouldly;
+ using Testing;
+ using Xunit;
+
+ public class XmlFileLoggerFormatTests
+ {
+ public sealed class TheXmlFileLoggerFormatCtor
+ {
+ [Fact]
+ public void Should_Throw_If_Log_Is_Null()
+ {
+ // Given / When
+ var result = Record.Exception(() => new XmlFileLoggerFormat(null));
+
+ // Then
+ result.IsArgumentNullException("log");
+ }
+ }
+
+ public sealed class TheReadIssuesMethod
+ {
+ [Fact]
+ public void Should_Read_Issue_With_File_Correct()
+ {
+ // Given
+ var fixture = new MsBuildIssuesProviderFixture("IssueWithFile.xml");
+
+ // When
+ var issues = fixture.ReadIssues().ToList();
+
+ // Then
+ issues.Count.ShouldBe(1);
+ var issue = issues.Single();
+ CheckIssue(
+ issue,
+ @"src\Cake.Issues.MsBuild.Tests\MsBuildIssuesProviderTests.cs",
+ 1311,
+ "CA2201",
+ 0,
+ @"Microsoft.Usage : 'ConfigurationManager.GetSortedConfigFiles(String)' creates an exception of type 'ApplicationException', an exception type that is not sufficiently specific and should never be raised by user code. If this exception instance might be thrown, use a different exception type.");
+ }
+
+ [Fact]
+ public void Should_Read_Issue_With_File_Without_Path_Correct()
+ {
+ // Given
+ var fixture = new MsBuildIssuesProviderFixture("IssueWithOnlyFileName.xml");
+
+ // When
+ var issues = fixture.ReadIssues().ToList();
+
+ // Then
+ issues.Count.ShouldBe(1);
+ var issue = issues.Single();
+ CheckIssue(
+ issue,
+ @"src\Cake.Issues.MsBuild.Tests\MsBuildIssuesProviderTests.cs",
+ 13,
+ "CS0219",
+ 0,
+ "The variable 'foo' is assigned but its value is never used");
+ }
+
+ [Fact]
+ public void Should_Read_Issue_Without_File_Correct()
+ {
+ // Given
+ var fixture = new MsBuildIssuesProviderFixture("IssueWithoutFile.xml");
+
+ // When
+ var issues = fixture.ReadIssues().ToList();
+
+ // Then
+ issues.Count.ShouldBe(1);
+ var issue = issues.Single();
+ CheckIssue(
+ issue,
+ null,
+ null,
+ "CA1711",
+ 0,
+ "Microsoft.Naming : Rename type name 'UniqueQueue(Of T)' so that it does not end in 'Queue'.");
+ }
+
+ private static void CheckIssue(
+ IIssue issue,
+ string affectedFileRelativePath,
+ int? line,
+ string rule,
+ int priority,
+ string message)
+ {
+ if (issue.AffectedFileRelativePath == null)
+ {
+ affectedFileRelativePath.ShouldBeNull();
+ }
+ else
+ {
+ issue.AffectedFileRelativePath.ToString().ShouldBe(new FilePath(affectedFileRelativePath).ToString());
+ issue.AffectedFileRelativePath.IsRelative.ShouldBe(true, "Issue path is not relative");
+ }
+
+ issue.Line.ShouldBe(line);
+ issue.Rule.ShouldBe(rule);
+ issue.Priority.ShouldBe(priority);
+ issue.Message.ShouldBe(message);
+ }
+ }
+ }
+}
diff --git a/src/Cake.Issues.MsBuild.Tests/packages.config b/src/Cake.Issues.MsBuild.Tests/packages.config
new file mode 100644
index 0000000..d8c638c
--- /dev/null
+++ b/src/Cake.Issues.MsBuild.Tests/packages.config
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Cake.Issues.MsBuild.ruleset b/src/Cake.Issues.MsBuild.ruleset
new file mode 100644
index 0000000..1d18efa
--- /dev/null
+++ b/src/Cake.Issues.MsBuild.ruleset
@@ -0,0 +1,241 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Cake.Issues.MsBuild.sln b/src/Cake.Issues.MsBuild.sln
new file mode 100644
index 0000000..d8f23a9
--- /dev/null
+++ b/src/Cake.Issues.MsBuild.sln
@@ -0,0 +1,44 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26730.8
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cake.Issues.MsBuild", "Cake.Issues.MsBuild\Cake.Issues.MsBuild.csproj", "{1A6C74CE-4775-458A-B013-BDE1986C5B88}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cake.Issues.MsBuild.Tests", "Cake.Issues.MsBuild.Tests\Cake.Issues.MsBuild.Tests.csproj", "{C69329F6-A4D1-4E33-BD9D-5E59973BE781}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{2EBEB9BA-3A3B-4EDC-95C0-44DD001AFFDC}"
+ ProjectSection(SolutionItems) = preProject
+ ..\setup.cake = ..\setup.cake
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "nuspec", "nuspec", "{3E340FDE-17DA-429E-BC41-AA5F5F5271DB}"
+ ProjectSection(SolutionItems) = preProject
+ ..\nuspec\nuget\Cake.Issues.MsBuild.nuspec = ..\nuspec\nuget\Cake.Issues.MsBuild.nuspec
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {1A6C74CE-4775-458A-B013-BDE1986C5B88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1A6C74CE-4775-458A-B013-BDE1986C5B88}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1A6C74CE-4775-458A-B013-BDE1986C5B88}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1A6C74CE-4775-458A-B013-BDE1986C5B88}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C69329F6-A4D1-4E33-BD9D-5E59973BE781}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C69329F6-A4D1-4E33-BD9D-5E59973BE781}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C69329F6-A4D1-4E33-BD9D-5E59973BE781}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C69329F6-A4D1-4E33-BD9D-5E59973BE781}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {3E340FDE-17DA-429E-BC41-AA5F5F5271DB} = {2EBEB9BA-3A3B-4EDC-95C0-44DD001AFFDC}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {896FC38E-24E4-4A35-8CF6-01E8EADDB346}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Cake.Issues.MsBuild.sln.DotSettings b/src/Cake.Issues.MsBuild.sln.DotSettings
new file mode 100644
index 0000000..7cc51a4
--- /dev/null
+++ b/src/Cake.Issues.MsBuild.sln.DotSettings
@@ -0,0 +1,3 @@
+
+ DO_NOT_SHOW
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
\ No newline at end of file
diff --git a/src/Cake.Issues.MsBuild/Cake.Issues.MsBuild.csproj b/src/Cake.Issues.MsBuild/Cake.Issues.MsBuild.csproj
new file mode 100644
index 0000000..e64a533
--- /dev/null
+++ b/src/Cake.Issues.MsBuild/Cake.Issues.MsBuild.csproj
@@ -0,0 +1,77 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {1A6C74CE-4775-458A-B013-BDE1986C5B88}
+ Library
+ Properties
+ Cake.Issues.MsBuild
+ Cake.Issues.MsBuild
+ v4.5.2
+ 512
+
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ bin\Debug\Cake.Issues.MsBuild.xml
+ ..\Cake.Issues.MsBuild.ruleset
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ bin\Release\Cake.Issues.MsBuild.xml
+ ..\Cake.Issues.MsBuild.ruleset
+
+
+
+ ..\packages\Cake.Core.0.16.2\lib\net45\Cake.Core.dll
+
+
+ ..\packages\Cake.Issues.0.1.0-beta0001\lib\net45\Cake.Issues.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Cake.Issues.MsBuild/ILogFileFormat.cs b/src/Cake.Issues.MsBuild/ILogFileFormat.cs
new file mode 100644
index 0000000..9cf4ab3
--- /dev/null
+++ b/src/Cake.Issues.MsBuild/ILogFileFormat.cs
@@ -0,0 +1,21 @@
+namespace Cake.Issues.MsBuild
+{
+ using System.Collections.Generic;
+ using IssueProvider;
+
+ ///
+ /// Definition of a MsBuild log file format.
+ ///
+ public interface ILogFileFormat
+ {
+ ///
+ /// Gets all code analysis issues.
+ ///
+ /// Repository settings to use.
+ /// Settings for code analysis provider to use.
+ /// List of code analysis issues
+ IEnumerable ReadIssues(
+ RepositorySettings repositorySettings,
+ MsBuildIssuesSettings msBuildIssuesSettings);
+ }
+}
diff --git a/src/Cake.Issues.MsBuild/LogFileFormat.cs b/src/Cake.Issues.MsBuild/LogFileFormat.cs
new file mode 100644
index 0000000..d431edf
--- /dev/null
+++ b/src/Cake.Issues.MsBuild/LogFileFormat.cs
@@ -0,0 +1,33 @@
+namespace Cake.Issues.MsBuild
+{
+ using System.Collections.Generic;
+ using Core.Diagnostics;
+ using IssueProvider;
+
+ ///
+ /// Base class for all MsBuild log file format implementations.
+ ///
+ public abstract class LogFileFormat : ILogFileFormat
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Cake log instance.
+ protected LogFileFormat(ICakeLog log)
+ {
+ log.NotNull(nameof(log));
+
+ this.Log = log;
+ }
+
+ ///
+ /// Gets the Cake log instance.
+ ///
+ protected ICakeLog Log { get; private set; }
+
+ ///
+ public abstract IEnumerable ReadIssues(
+ RepositorySettings repositorySettings,
+ MsBuildIssuesSettings msBuildIssuesSettings);
+ }
+}
diff --git a/src/Cake.Issues.MsBuild/MsBuildIssuesAliases.cs b/src/Cake.Issues.MsBuild/MsBuildIssuesAliases.cs
new file mode 100644
index 0000000..a3870ef
--- /dev/null
+++ b/src/Cake.Issues.MsBuild/MsBuildIssuesAliases.cs
@@ -0,0 +1,234 @@
+namespace Cake.Issues.MsBuild
+{
+ using System;
+ using Core;
+ using Core.Annotations;
+ using Core.IO;
+ using IssueProvider;
+
+ ///
+ /// Contains functionality related to importing code analysis issues from MSBuild logs to write them to
+ /// pull requests.
+ ///
+ [CakeAliasCategory(IssuesAliasConstants.MainCakeAliasCategory)]
+ public static class MsBuildIssuesAliases
+ {
+ ///
+ /// Registers a new URL resolver with default priority of 0.
+ ///
+ /// The context.
+ /// Resolver which returns an linking to a site
+ /// containing help for a specific .
+ ///
+ /// Adds a provider with default priority of 0 returning a link for all rules of the category CA to
+ /// search msdn.microsoft.com with Google for the rule:
+ ///
+ ///
+ /// x.Category.ToUpperInvariant() == "CA" ?
+ /// new Uri("https://www.google.com/search?q=%22" + x.Rule + ":%22+site:msdn.microsoft.com") :
+ /// null)
+ /// ]]>
+ ///
+ ///
+ [CakeMethodAlias]
+ [CakeAliasCategory(IssuesAliasConstants.IssueProviderCakeAliasCategory)]
+ public static void MsBuildAddRuleUrlResolver(
+ this ICakeContext context,
+ Func resolver)
+ {
+ context.NotNull(nameof(context));
+ resolver.NotNull(nameof(resolver));
+
+ MsBuildRuleUrlResolver.Instance.AddUrlResolver(resolver);
+ }
+
+ ///
+ /// Registers a new URL resolver with a specific priority.
+ ///
+ /// The context.
+ /// Resolver which returns an linking to a site
+ /// containing help for a specific .
+ /// Priority of the resolver. Resolver with a higher priority are considered
+ /// first during resolving of the URL.
+ ///
+ /// Adds a provider of priority 5 returning a link for all rules of the category CA to
+ /// search msdn.microsoft.com with Google for the rule:
+ ///
+ ///
+ /// x.Category.ToUpperInvariant() == "CA" ?
+ /// new Uri("https://www.google.com/search?q=%22" + x.Rule + ":%22+site:msdn.microsoft.com") :
+ /// null,
+ /// 5)
+ /// ]]>
+ ///
+ ///
+ [CakeMethodAlias]
+ [CakeAliasCategory(IssuesAliasConstants.IssueProviderCakeAliasCategory)]
+ public static void MsBuildAddRuleUrlResolver(
+ this ICakeContext context,
+ Func resolver,
+ int priority)
+ {
+ context.NotNull(nameof(context));
+ resolver.NotNull(nameof(resolver));
+
+ MsBuildRuleUrlResolver.Instance.AddUrlResolver(resolver, priority);
+ }
+
+ ///
+ ///
+ /// Gets an instance for the MsBuild log format as written by the XmlFileLogger class
+ /// from MSBuild Extension Pack.
+ ///
+ ///
+ /// You can add the logger to the MSBuildSettings like this:
+ ///
+ /// var settings = new MsBuildSettings()
+ /// .WithLogger(
+ /// Context.Tools.Resolve("MSBuild.ExtensionPack.Loggers.dll").FullPath,
+ /// "XmlFileLogger",
+ /// string.Format(
+ /// "logfile=\"{0}\";verbosity=Detailed;encoding=UTF-8",
+ /// @"C:\build\msbuild.log")
+ /// )
+ ///
+ ///
+ ///
+ /// In order to use the above logger, include the following in your build.cake file to download and
+ /// install from NuGet.org:
+ ///
+ /// #tool "nuget:?package=MSBuild.Extension.Pack"
+ ///
+ ///
+ ///
+ /// The context.
+ /// Instance for the MsBuild log format.
+ [CakePropertyAlias]
+ [CakeAliasCategory(IssuesAliasConstants.IssueProviderCakeAliasCategory)]
+ public static ILogFileFormat MsBuildXmlFileLoggerFormat(
+ this ICakeContext context)
+ {
+ context.NotNull(nameof(context));
+
+ return new XmlFileLoggerFormat(context.Log);
+ }
+
+ ///
+ /// Gets an instance of a provider for code analysis issues reported as MsBuild warnings using a log file from disk.
+ ///
+ /// The context.
+ /// Path to the the MsBuild log file.
+ /// The log file needs to be in the format as defined by the parameter.
+ /// Format of the provided MsBuild log file.
+ /// Instance of a provider for code analysis issues reported as MsBuild warnings.
+ ///
+ /// Report code analysis issues reported as MsBuild warnings to a TFS pull request:
+ ///
+ ///
+ ///
+ ///
+ [CakeMethodAlias]
+ [CakeAliasCategory(IssuesAliasConstants.IssueProviderCakeAliasCategory)]
+ public static IIssueProvider MsBuildIssuesFromFilePath(
+ this ICakeContext context,
+ FilePath logFilePath,
+ ILogFileFormat format)
+ {
+ context.NotNull(nameof(context));
+ logFilePath.NotNull(nameof(logFilePath));
+ format.NotNull(nameof(format));
+
+ return context.MsBuildIssues(MsBuildIssuesSettings.FromFilePath(logFilePath, format));
+ }
+
+ ///
+ /// Gets an instance of a provider for code analysis issues reported as MsBuild warnings using log content.
+ ///
+ /// The context.
+ /// Content of the the MsBuild log file.
+ /// The log file needs to be in the format as defined by the parameter.
+ /// Format of the provided MsBuild log file.
+ /// Instance of a provider for code analysis issues reported as MsBuild warnings.
+ ///
+ /// Report code analysis issues reported as MsBuild warnings to a TFS pull request:
+ ///
+ ///
+ ///
+ ///
+ [CakeMethodAlias]
+ [CakeAliasCategory(IssuesAliasConstants.IssueProviderCakeAliasCategory)]
+ public static IIssueProvider MsBuildIssuesFromContent(
+ this ICakeContext context,
+ string logFileContent,
+ ILogFileFormat format)
+ {
+ context.NotNull(nameof(context));
+ logFileContent.NotNullOrWhiteSpace(nameof(logFileContent));
+ format.NotNull(nameof(format));
+
+ return context.MsBuildIssues(MsBuildIssuesSettings.FromContent(logFileContent, format));
+ }
+
+ ///
+ /// Gets an instance of a provider for code analysis issues reported as MsBuild warnings using specified settings.
+ ///
+ /// The context.
+ /// Settings for reading the MSBuild log.
+ /// Instance of a provider for code analysis issues reported as MsBuild warnings.
+ ///
+ /// Report code analysis issues reported as MsBuild warnings to a TFS pull request:
+ ///
+ ///
+ ///
+ ///
+ [CakeMethodAlias]
+ [CakeAliasCategory(IssuesAliasConstants.IssueProviderCakeAliasCategory)]
+ public static IIssueProvider MsBuildIssues(
+ this ICakeContext context,
+ MsBuildIssuesSettings settings)
+ {
+ context.NotNull(nameof(context));
+ settings.NotNull(nameof(settings));
+
+ return new MsBuildIssuesProvider(context.Log, settings);
+ }
+ }
+}
diff --git a/src/Cake.Issues.MsBuild/MsBuildIssuesProvider.cs b/src/Cake.Issues.MsBuild/MsBuildIssuesProvider.cs
new file mode 100644
index 0000000..f50ee4c
--- /dev/null
+++ b/src/Cake.Issues.MsBuild/MsBuildIssuesProvider.cs
@@ -0,0 +1,33 @@
+namespace Cake.Issues.MsBuild
+{
+ using System.Collections.Generic;
+ using Core.Diagnostics;
+ using IssueProvider;
+
+ ///
+ /// Provider for code analysis issues reported as MsBuild warnings.
+ ///
+ internal class MsBuildIssuesProvider : IssueProvider
+ {
+ private readonly MsBuildIssuesSettings msBuildIssuesSettings;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Cake log context.
+ /// Settings for reading the log file.
+ public MsBuildIssuesProvider(ICakeLog log, MsBuildIssuesSettings settings)
+ : base(log)
+ {
+ settings.NotNull(nameof(settings));
+
+ this.msBuildIssuesSettings = settings;
+ }
+
+ ///
+ protected override IEnumerable InternalReadIssues(IssueCommentFormat format)
+ {
+ return this.msBuildIssuesSettings.Format.ReadIssues(this.Settings, this.msBuildIssuesSettings);
+ }
+ }
+}
diff --git a/src/Cake.Issues.MsBuild/MsBuildIssuesSettings.cs b/src/Cake.Issues.MsBuild/MsBuildIssuesSettings.cs
new file mode 100644
index 0000000..892eb91
--- /dev/null
+++ b/src/Cake.Issues.MsBuild/MsBuildIssuesSettings.cs
@@ -0,0 +1,83 @@
+namespace Cake.Issues.MsBuild
+{
+ using System.IO;
+ using Core.IO;
+
+ ///
+ /// Settings for .
+ ///
+ public class MsBuildIssuesSettings
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Path to the the MsBuild log file.
+ /// The log file needs to be in the format as defined by the parameter.
+ /// Format of the provided MsBuild log file.
+ protected MsBuildIssuesSettings(FilePath logFilePath, ILogFileFormat format)
+ {
+ logFilePath.NotNull(nameof(logFilePath));
+ format.NotNull(nameof(format));
+
+ this.Format = format;
+
+ using (var stream = new FileStream(logFilePath.FullPath, FileMode.Open, FileAccess.Read))
+ {
+ using (var sr = new StreamReader(stream))
+ {
+ this.LogFileContent = sr.ReadToEnd();
+ }
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Content of the the MsBuild log file.
+ /// The log file needs to be in the format as defined by the parameter.
+ /// Format of the provided MsBuild log file.
+ protected MsBuildIssuesSettings(string logFileContent, ILogFileFormat format)
+ {
+ logFileContent.NotNullOrWhiteSpace(nameof(logFileContent));
+ format.NotNull(nameof(format));
+
+ this.LogFileContent = logFileContent;
+ this.Format = format;
+ }
+
+ ///
+ /// Gets the format of the MsBuild log file.
+ ///
+ public ILogFileFormat Format { get; private set; }
+
+ ///
+ /// Gets the content of the log file.
+ ///
+ public string LogFileContent { get; private set; }
+
+ ///
+ /// Returns a new instance of the class from a log file on disk.
+ ///
+ /// Path to the MsBuild log file.
+ /// The log file needs to be in the format as defined by the parameter.
+ /// Format of the provided MsBuild log file.
+ /// Instance of the class.
+ public static MsBuildIssuesSettings FromFilePath(FilePath logFilePath, ILogFileFormat format)
+ {
+ return new MsBuildIssuesSettings(logFilePath, format);
+ }
+
+ ///
+ /// Returns a new instance of the class from the content
+ /// of a MsBuild log file.
+ ///
+ /// Content of the MsBuild log file.
+ /// The log file needs to be in the format as defined by the parameter.
+ /// Format of the provided MsBuild log file.
+ /// Instance of the class.
+ public static MsBuildIssuesSettings FromContent(string logFileContent, ILogFileFormat format)
+ {
+ return new MsBuildIssuesSettings(logFileContent, format);
+ }
+ }
+}
diff --git a/src/Cake.Issues.MsBuild/MsBuildRuleDescription.cs b/src/Cake.Issues.MsBuild/MsBuildRuleDescription.cs
new file mode 100644
index 0000000..e25c270
--- /dev/null
+++ b/src/Cake.Issues.MsBuild/MsBuildRuleDescription.cs
@@ -0,0 +1,20 @@
+namespace Cake.Issues.MsBuild
+{
+ using IssueProvider;
+
+ ///
+ /// Class describing rules appearing in MsBuild logs.
+ ///
+ public class MsBuildRuleDescription : BaseRuleDescription
+ {
+ ///
+ /// Gets or sets the category of the rule.
+ ///
+ public string Category { get; set; }
+
+ ///
+ /// Gets or sets the identifier of the rule.
+ ///
+ public int RuleId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Cake.Issues.MsBuild/MsBuildRuleUrlResolver.cs b/src/Cake.Issues.MsBuild/MsBuildRuleUrlResolver.cs
new file mode 100644
index 0000000..b59fd66
--- /dev/null
+++ b/src/Cake.Issues.MsBuild/MsBuildRuleUrlResolver.cs
@@ -0,0 +1,74 @@
+namespace Cake.Issues.MsBuild
+{
+ using System;
+ using System.Text;
+ using IssueProvider;
+
+ ///
+ /// Class for retrieving an URL linking to a site describing a rule.
+ ///
+ internal class MsBuildRuleUrlResolver : BaseRuleUrlResolver
+ {
+ private static readonly Lazy InstanceValue =
+ new Lazy(() => new MsBuildRuleUrlResolver());
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ private MsBuildRuleUrlResolver()
+ {
+ // Add resolver for common known issue categories.
+ this.AddUrlResolver(x =>
+ x.Category.ToUpperInvariant() == "CA" ?
+ new Uri("https://www.google.im/search?q=%22" + x.Rule + ":%22+site:msdn.microsoft.com") :
+ null);
+ this.AddUrlResolver(x =>
+ x.Category.ToUpperInvariant() == "SA" ?
+ new Uri("https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/" + x.Rule + ".md") :
+ null);
+ }
+
+ ///
+ /// Gets the instance of the rule resolver.
+ ///
+ public static MsBuildRuleUrlResolver Instance => InstanceValue.Value;
+
+ ///
+ protected override bool TryGetRuleDescription(string rule, MsBuildRuleDescription ruleDescription)
+ {
+ // Parse the rule. Expect it in the form starting with a identifier containing characters
+ // followed by the rule id as a number.
+ var digitIndex = -1;
+ var categoryBuilder = new StringBuilder();
+ for (var index = 0; index < rule.Length; index++)
+ {
+ var currentChar = rule[index];
+ if (char.IsDigit(currentChar))
+ {
+ digitIndex = index;
+ break;
+ }
+
+ categoryBuilder.Append(currentChar);
+ }
+
+ // If rule doesn't contain numbers return false.
+ if (digitIndex < 0)
+ {
+ return false;
+ }
+
+ // Try to parse the part after the first number to an integer.
+ int ruleId;
+ if (!int.TryParse(rule.Substring(digitIndex), out ruleId))
+ {
+ return false;
+ }
+
+ ruleDescription.RuleId = ruleId;
+ ruleDescription.Category = categoryBuilder.ToString();
+
+ return true;
+ }
+ }
+}
diff --git a/src/Cake.Issues.MsBuild/Properties/AssemblyInfo.cs b/src/Cake.Issues.MsBuild/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..cf1a87a
--- /dev/null
+++ b/src/Cake.Issues.MsBuild/Properties/AssemblyInfo.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Cake.Issues.MsBuild")]
+[assembly: AssemblyDescription("MsBuild support for the Cake.Issues Addin for Cake Build Automation System")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("BBT Software AG")]
+[assembly: AssemblyProduct("Cake.Issues")]
+[assembly: AssemblyCopyright("Copyright © 2017 BBT Software AG, Root/Zermatt, Switzerland")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("1a6c74ce-4775-458a-b013-bde1986c5b88")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+
+[assembly: CLSCompliant(true)]
+[assembly: InternalsVisibleTo("Cake.Issues.MsBuild.Tests")]
diff --git a/src/Cake.Issues.MsBuild/XmlFileLoggerFormat.cs b/src/Cake.Issues.MsBuild/XmlFileLoggerFormat.cs
new file mode 100644
index 0000000..09238d7
--- /dev/null
+++ b/src/Cake.Issues.MsBuild/XmlFileLoggerFormat.cs
@@ -0,0 +1,178 @@
+namespace Cake.Issues.MsBuild
+{
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.IO;
+ using System.Xml.Linq;
+ using Core.Diagnostics;
+ using IssueProvider;
+
+ ///
+ /// MsBuild log format as written by the XmlFileLogger class from MSBuild Extension Pack.
+ ///
+ internal class XmlFileLoggerFormat : LogFileFormat
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Cake log instance.
+ public XmlFileLoggerFormat(ICakeLog log)
+ : base(log)
+ {
+ }
+
+ ///
+ public override IEnumerable ReadIssues(
+ RepositorySettings repositorySettings,
+ MsBuildIssuesSettings msBuildIssuesSettings)
+ {
+ repositorySettings.NotNull(nameof(repositorySettings));
+ msBuildIssuesSettings.NotNull(nameof(msBuildIssuesSettings));
+
+ var result = new List();
+
+ var logDocument = XDocument.Parse(msBuildIssuesSettings.LogFileContent);
+
+ // Loop through all warning tags.
+ foreach (var warning in logDocument.Descendants("warning"))
+ {
+ // Read affected file from the warning.
+ if (!this.TryGetFile(warning, repositorySettings, out string fileName))
+ {
+ continue;
+ }
+
+ // Read affected line from the warning.
+ if (!TryGetLine(warning, out var line))
+ {
+ continue;
+ }
+
+ // Read rule code from the warning.
+ if (!TryGetRule(warning, out string rule))
+ {
+ continue;
+ }
+
+ result.Add(new Issue(
+ fileName,
+ line,
+ warning.Value,
+ 0,
+ rule,
+ MsBuildRuleUrlResolver.Instance.ResolveRuleUrl(rule)));
+ }
+
+ return result;
+ }
+
+ ///
+ /// Reads the affected line from a warning logged in a MsBuild log.
+ ///
+ /// Warning element from MsBuild log.
+ /// Returns line.
+ /// True if the line could be parsed.
+ private static bool TryGetLine(XElement warning, out int? line)
+ {
+ line = null;
+
+ var lineAttr = warning.Attribute("line");
+
+ var lineValue = lineAttr?.Value;
+ if (string.IsNullOrWhiteSpace(lineValue))
+ {
+ return false;
+ }
+
+ line = int.Parse(lineValue, CultureInfo.InvariantCulture);
+
+ // Convert negative lines numbers to null
+ if (line < 0)
+ {
+ line = null;
+ }
+
+ return true;
+ }
+
+ ///
+ /// Reads the rule code from a warning logged in a MsBuild log.
+ ///
+ /// Warning element from MsBuild log.
+ /// Returns the code of the rule.
+ /// True if the rule code could be parsed.
+ private static bool TryGetRule(XElement warning, out string rule)
+ {
+ rule = string.Empty;
+
+ var codeAttr = warning.Attribute("code");
+ if (codeAttr == null)
+ {
+ return false;
+ }
+
+ rule = codeAttr.Value;
+ return !string.IsNullOrWhiteSpace(rule);
+ }
+
+ ///
+ /// Reads the affected file path from a warning logged in a MsBuild log.
+ ///
+ /// Warning element from MsBuild log.
+ /// Repository settings to use.
+ /// Returns the full path to the affected file.
+ /// True if the file path could be parsed.
+ private bool TryGetFile(
+ XElement warning,
+ RepositorySettings repositorySettings,
+ out string fileName)
+ {
+ fileName = string.Empty;
+
+ var fileAttr = warning.Attribute("file");
+ if (fileAttr == null)
+ {
+ return true;
+ }
+
+ fileName = fileAttr.Value;
+ if (string.IsNullOrWhiteSpace(fileName))
+ {
+ return true;
+ }
+
+ // If not absolute path, combine with file path from compile task.
+ if (!fileName.IsFullPath())
+ {
+ var parentFileAttr = warning.Parent?.Attribute("file");
+ if (parentFileAttr != null)
+ {
+ var compileTaskDirectory = Path.GetDirectoryName(parentFileAttr.Value);
+ fileName = Path.Combine(compileTaskDirectory, fileName);
+ }
+ }
+
+ // Ignore files from outside the repository.
+ if (!fileName.IsSubpathOf(repositorySettings.RepositoryRoot.FullPath))
+ {
+ this.Log.Warning(
+ "Ignored issue for file '{0}' since it is outside the repository folder at {1}.",
+ fileName,
+ repositorySettings.RepositoryRoot);
+
+ return false;
+ }
+
+ // Make path relative to repository root.
+ fileName = fileName.Substring(repositorySettings.RepositoryRoot.FullPath.Length);
+
+ // Remove leading directory separator.
+ if (fileName.StartsWith(Path.DirectorySeparatorChar.ToString()))
+ {
+ fileName = fileName.Substring(1);
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/src/Cake.Issues.MsBuild/packages.config b/src/Cake.Issues.MsBuild/packages.config
new file mode 100644
index 0000000..d7a63d1
--- /dev/null
+++ b/src/Cake.Issues.MsBuild/packages.config
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/packages.config b/tools/packages.config
new file mode 100644
index 0000000..3b95cb1
--- /dev/null
+++ b/tools/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file