Created
May 31, 2016 14:05
-
-
Save george-polevoy/d1921e0b7ed45918057c8b44cf662e17 to your computer and use it in GitHub Desktop.
Code formatting inspections for line endings and unicode local alphabet for msbuild.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |
<PropertyGroup> | |
<TasksDllPath Condition="'$(MSBuildToolsVersion)' == '14'">$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll</TasksDllPath> | |
<TasksDllPath Condition="'$(MSBuildToolsVersion)' != '14'">$(MSBuildToolsPath)\Microsoft.Build.Tasks.v$(MSBuildToolsVersion).dll</TasksDllPath> | |
</PropertyGroup> | |
<UsingTask TaskName="InspectSourceCode" | |
TaskFactory="CodeTaskFactory" | |
AssemblyFile="$(TasksDllPath)"> | |
<ParameterGroup> | |
<Items ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" /> | |
</ParameterGroup> | |
<Task> | |
<Using Namespace="System.IO" /> | |
<Using Namespace="System.Text.RegularExpressions" /> | |
<Using Namespace="System.Linq" /> | |
<Using Namespace="Microsoft.Build.Framework" /> | |
<Code Type="Fragment" | |
Language="cs"> | |
<![CDATA[ | |
foreach(var item in Items) | |
{ | |
string fileName = item.GetMetadata("FullPath"); | |
if (!File.Exists(fileName)) | |
continue; | |
if (fileName.ToLower().Contains(".generated.")) | |
continue; | |
CheckLineEndings(fileName); | |
CheckEncodingForRussianLanguage(fileName); | |
//CheckEmptySpace(fileName); | |
} | |
// Hack https://badcorporatelogo.wordpress.com/2013/09/15/code-injection-with-msbuild-inline-tasks/ | |
return true; | |
} | |
private void CheckEmptySpace(string fileName) | |
{ | |
foreach(var item in File.ReadLines(fileName).Select((line, index) => new {line, index})) | |
{ | |
if (item.line.TrimEnd() != item.line) | |
Log.LogWarning( | |
subcategory : "Whitespace", | |
warningCode : "EX", | |
helpKeyword : "helpKeywordNone", | |
file : fileName, | |
lineNumber : item.index + 1, | |
columnNumber : 1, | |
endLineNumber : item.index + 1, | |
endColumnNumber : item.line.Length, | |
message : "Excess whitespace"); | |
} | |
} | |
private void CheckEncodingForRussianLanguage(string fileName) | |
{ | |
var byteOrderMark = new byte[]{0xEF, 0xBB, 0xBF}; | |
var russianCharsLower = "абвгдеёжзиклмнопрстуфхцчшщъьэюя"; | |
var russianAlphabet = new HashSet<char>(string.Concat(russianCharsLower, russianCharsLower.ToUpper())); | |
if (byteOrderMark.SequenceEqual(ReadBytes(fileName).Take(byteOrderMark.Length))) // Skip unicode files. | |
return; | |
var asWindows = File.ReadAllText(fileName, Encoding.GetEncoding(1251)); | |
if (!asWindows.Any(c => russianAlphabet.Contains(c))) | |
return; | |
var asUnicode = File.ReadAllText(fileName); | |
if (asWindows == asUnicode) | |
return; | |
Log.LogWarning( | |
subcategory : "Code Encoding", | |
warningCode : "EX", | |
helpKeyword : "helpKeywordNone", | |
file : fileName, | |
lineNumber : 1, | |
columnNumber : 1, | |
endLineNumber : 1, | |
endColumnNumber : 1, | |
message : "Inconsistent encoding found for russian alphabet"); | |
} | |
IEnumerable<byte> ReadBytes(string fileName) | |
{ | |
using (var stream = new FileStream(fileName, FileMode.Open)) | |
{ | |
var buffer = new byte[4096]; | |
var actuallyRead = 0; | |
while ((actuallyRead = stream.Read(buffer, 0, buffer.Length)) > 0) | |
{ | |
for (var i = 0; i < actuallyRead; i++) | |
yield return buffer[i]; | |
} | |
} | |
} | |
private void CheckLineEndings(string fileName) | |
{ | |
var soleNewLine = new Regex(@"([^\r]{1}\n)|(^\n)", RegexOptions.Multiline | RegexOptions.Compiled); | |
if(!File.Exists(fileName)) | |
{ | |
Log.LogCriticalMessage( | |
subcategory:"Code Formatting", | |
code:"IX", | |
helpKeyword:"MISSING", | |
file:fileName, | |
lineNumber:0, | |
columnNumber:0, | |
endLineNumber:0, | |
endColumnNumber:0, | |
message:"File is missing"); | |
return; | |
} | |
string content = File.ReadAllText(fileName); | |
if (soleNewLine.IsMatch(content)) | |
{ | |
Log.LogWarning( | |
subcategory : "Code Formatting", | |
warningCode : "WX", | |
helpKeyword : "helpKeywordNone", | |
file : fileName, | |
lineNumber : 1, | |
columnNumber : 1, | |
endLineNumber : 1, | |
endColumnNumber : 1, | |
message : "Inconsistent line endings found"); | |
} | |
} | |
// Hack https://badcorporatelogo.wordpress.com/2013/09/15/code-injection-with-msbuild-inline-tasks/ | |
private bool IgnoreThisInjectedFunction() { | |
// msbuild will complete this with: | |
// return _Success; | |
// } | |
]]> | |
</Code> | |
</Task> | |
</UsingTask> | |
<Target Name="RunSourceCodeInspections"> | |
<InspectSourceCode Items="@(Compile)" /> | |
</Target> | |
</Project> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment