diff --git a/.gitignore b/.gitignore
index b5ca78e..9e96a35 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
+tools/
+*.nupkg
+
#################
## Eclipse
#################
diff --git a/CSharpMinifier.GUI/App.config b/CSharpMinifier.GUI/App.config
index de68365..6de17de 100644
--- a/CSharpMinifier.GUI/App.config
+++ b/CSharpMinifier.GUI/App.config
@@ -1,12 +1,12 @@
-
+
-
-
+
+
@@ -72,36 +72,4 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/CSharpMinifier.GUI/CSharpMinifier.GUI.csproj b/CSharpMinifier.GUI/CSharpMinifier.GUI.csproj
index 3172442..110bea7 100644
--- a/CSharpMinifier.GUI/CSharpMinifier.GUI.csproj
+++ b/CSharpMinifier.GUI/CSharpMinifier.GUI.csproj
@@ -9,7 +9,7 @@
Properties
CSharpMinifier.GUI
CSharpMinifier.GUI
- v4.6
+ v4.6.1
512
@@ -35,6 +35,9 @@
4
false
+
+ true
+
@@ -76,20 +79,20 @@
-
-
- {a26c936c-846b-4165-9574-42c74075d4cd}
- CSharpMinifier
-
-
+
+
+ {a26c936c-846b-4165-9574-42c74075d4cd}
+ CSharpMinifier
+
+
-
-
\ No newline at end of file
+
+
diff --git a/CSharpMinifier.Tests/MinifierTests.cs b/CSharpMinifier.Tests/MinifierTests.cs
index 070fc7e..b33245c 100644
--- a/CSharpMinifier.Tests/MinifierTests.cs
+++ b/CSharpMinifier.Tests/MinifierTests.cs
@@ -10,16 +10,24 @@ public class MinifierTests
{
Dictionary Samples;
+ string _cscPath;
+
+ bool CanCompile(string program) =>
+ CompileUtils.CanCompile(program, _cscPath);
+
[SetUp]
public void Init()
{
+ var baseDirectory = System.AppDomain.CurrentDomain.BaseDirectory;
+ _cscPath = Path.Combine(baseDirectory, "..", "..", "..", "..", "tools", "Microsoft.Net.Compilers", "tools", "csc.exe");
+
Samples = new Dictionary();
- var sampleFiles = Directory.GetFiles($"{System.AppDomain.CurrentDomain.BaseDirectory}..\\..\\Samples");
+ var sampleFiles = Directory.GetFiles(Path.Combine(baseDirectory, "..", "..", "..", "Samples"));
foreach (var file in sampleFiles)
{
var code = File.ReadAllText(file);
Samples.Add(Path.GetFileNameWithoutExtension(file), code);
- if (!CompileUtils.CanCompile(code))
+ if (!CanCompile(code))
Assert.Inconclusive("All input code should be compilied");
}
}
@@ -35,7 +43,7 @@ public void RemoveSpaces()
foreach (var sample in Samples)
{
var minified = minifier.MinifyFromString(sample.Value);
- Assert.IsTrue(CompileUtils.CanCompile(minified));
+ Assert.IsTrue(CanCompile(minified));
if (sample.Key == "Test1")
Assert.IsFalse(minified.Contains(" /*"));
}
@@ -55,7 +63,7 @@ public void LineLengthConstraint()
foreach (var sample in Samples)
{
var minified = minifier.MinifyFromString(sample.Value);
- Assert.IsTrue(CompileUtils.CanCompile(minified));
+ Assert.IsTrue(CanCompile(minified));
}
}
@@ -73,7 +81,7 @@ public void RemoveComments()
if (!test.Contains("//") || !test.Contains("/*") || !test.Contains("*/"))
Assert.Inconclusive("Invalid test sample for RemoveComments test");
var minified = minifier.MinifyFromString(test);
- Assert.IsTrue(CompileUtils.CanCompile(minified));
+ Assert.IsTrue(CanCompile(minified));
Assert.IsFalse(minified.Contains("//"));
Assert.IsFalse(minified.Contains("/*"));
Assert.IsFalse(minified.Contains("*/"));
@@ -93,7 +101,7 @@ public void RemoveRegions()
if (!test.Contains("#region") || !test.Contains("#endregion"))
Assert.Inconclusive("Invalid test sample for RemoveRegions test");
var minified = minifier.MinifyFromString(test);
- Assert.IsTrue(CompileUtils.CanCompile(minified));
+ Assert.IsTrue(CanCompile(minified));
Assert.IsFalse(minified.Contains("#region"));
Assert.IsFalse(minified.Contains("#endregion"));
}
@@ -111,7 +119,7 @@ public void CompressIdentifiers()
foreach (var sample in Samples)
{
var minified = minifier.MinifyFromString(sample.Value);
- Assert.IsTrue(CompileUtils.CanCompile(minified));
+ Assert.IsTrue(CanCompile(minified));
}
}
@@ -199,7 +207,7 @@ public void ShouldProperlyConvertEnumWithoutInitializersToInt()
var minifier = new RoslynMinifier();
var minified = minifier.MinifyFromString(Samples["EnumToIntConversion"]);
- Assert.IsTrue(CompileUtils.CanCompile(minified));
+ Assert.IsTrue(CanCompile(minified));
Assert.AreEqual(
"using System.Collections.Generic;class c{static int a=5;static Dictionary>b=new Dictionary>{{5,new Dictionary{{' ',8}}},{6,new Dictionary{{' ',24}}}};}",
minified);
diff --git a/CSharpMinifier.Tests/Properties/AssemblyInfo.cs b/CSharpMinifier.Tests/Properties/AssemblyInfo.cs
deleted file mode 100644
index 5a918ca..0000000
--- a/CSharpMinifier.Tests/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-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("CSharpMinifier.Tests")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("CSharpMinifier.Tests")]
-[assembly: AssemblyCopyright("Copyright © 2013")]
-[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("8f63cfda-b2cf-4ab1-81e2-0c6c7e9ce794")]
-
-// 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/CSharpMinifier.sln b/CSharpMinifier.sln
index 01fcdfe..f2ea04f 100644
--- a/CSharpMinifier.sln
+++ b/CSharpMinifier.sln
@@ -1,13 +1,18 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2013
-VisualStudioVersion = 12.0.31101.0
+# Visual Studio 15
+VisualStudioVersion = 15.0.28307.168
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpMinifier", "CSharpMinifier\CSharpMinifier.csproj", "{A26C936C-846B-4165-9574-42C74075D4CD}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpMinifier", "CSharpMinifier\CSharpMinifier.csproj", "{A26C936C-846B-4165-9574-42C74075D4CD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpMinifier.GUI", "CSharpMinifier.GUI\CSharpMinifier.GUI.csproj", "{1E6C7AB5-3E2F-4F5E-B5BD-B24E2258D0E2}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpMinifier.Tests", "CSharpMinifier.Tests\CSharpMinifier.Tests.csproj", "{24A6BB34-4BE9-4504-926D-16D52FE5AC41}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpMinifier.Tests", "CSharpMinifier.Tests\CSharpMinifier.Tests.csproj", "{24A6BB34-4BE9-4504-926D-16D52FE5AC41}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D6B4D5F0-B989-40F3-9F60-0D96701A1103}"
+ ProjectSection(SolutionItems) = preProject
+ global.json = global.json
+ EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -31,4 +36,7 @@ Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {A1AE996D-FA41-4FA8-B2F4-5AA1AF1719F4}
+ EndGlobalSection
EndGlobal
diff --git a/CSharpMinifier/CSharpMinifier.csproj b/CSharpMinifier/CSharpMinifier.csproj
index 3f06b24..599c39f 100644
--- a/CSharpMinifier/CSharpMinifier.csproj
+++ b/CSharpMinifier/CSharpMinifier.csproj
@@ -1,192 +1,17 @@
-
-
-
+
+
- Debug
- AnyCPU
- {A26C936C-846B-4165-9574-42C74075D4CD}
- Library
- Properties
- CSharpMinifier
- CSharpMinifier
- v4.6
- 512
-
-
+ netstandard2.0;net461
+ true
+ ../dist
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
- false
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
- false
-
-
-
- ..\packages\Microsoft.CodeAnalysis.Common.2.7.0\lib\netstandard1.3\Microsoft.CodeAnalysis.dll
-
-
- ..\packages\Microsoft.CodeAnalysis.CSharp.2.7.0\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.dll
-
-
- ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.2.7.0\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.Workspaces.dll
-
-
- ..\packages\Microsoft.CodeAnalysis.VisualBasic.2.7.0\lib\netstandard1.3\Microsoft.CodeAnalysis.VisualBasic.dll
-
-
- ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.2.7.0\lib\netstandard1.3\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll
-
-
- ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.2.7.0\lib\net46\Microsoft.CodeAnalysis.Workspaces.dll
-
-
- ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.2.7.0\lib\net46\Microsoft.CodeAnalysis.Workspaces.Desktop.dll
-
-
- False
- ..\packages\Mono.Cecil.0.9.5.4\lib\net40\Mono.Cecil.dll
-
-
- False
- ..\packages\Mono.Cecil.0.9.5.4\lib\net40\Mono.Cecil.Mdb.dll
-
-
- False
- ..\packages\Mono.Cecil.0.9.5.4\lib\net40\Mono.Cecil.Pdb.dll
-
-
- False
- ..\packages\Mono.Cecil.0.9.5.4\lib\net40\Mono.Cecil.Rocks.dll
-
-
-
- ..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll
- True
-
-
- ..\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
- True
-
-
-
- ..\packages\System.Composition.AttributedModel.1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll
-
-
- ..\packages\System.Composition.Convention.1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.Convention.dll
-
-
- ..\packages\System.Composition.Hosting.1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.Hosting.dll
-
-
- ..\packages\System.Composition.Runtime.1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.Runtime.dll
-
-
- ..\packages\System.Composition.TypedParts.1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll
-
-
- ..\packages\System.Console.4.3.0\lib\net46\System.Console.dll
-
-
-
- ..\packages\System.Diagnostics.FileVersionInfo.4.3.0\lib\net46\System.Diagnostics.FileVersionInfo.dll
-
-
- ..\packages\System.Diagnostics.StackTrace.4.3.0\lib\net46\System.Diagnostics.StackTrace.dll
-
-
- ..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll
- True
-
-
- ..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll
-
-
- ..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll
-
-
-
- ..\packages\System.Reflection.Metadata.1.4.2\lib\portable-net45+win8\System.Reflection.Metadata.dll
-
-
- ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll
- True
-
-
- ..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net46\System.Security.Cryptography.Algorithms.dll
- True
-
-
- ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll
-
-
- ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll
-
-
- ..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net46\System.Security.Cryptography.X509Certificates.dll
- True
-
-
- ..\packages\System.Text.Encoding.CodePages.4.3.0\lib\net46\System.Text.Encoding.CodePages.dll
-
-
- ..\packages\System.Threading.Thread.4.3.0\lib\net46\System.Threading.Thread.dll
-
-
- ..\packages\System.ValueTuple.4.3.0\lib\netstandard1.0\System.ValueTuple.dll
-
-
-
-
- ..\packages\System.Xml.ReaderWriter.4.3.0\lib\net46\System.Xml.ReaderWriter.dll
-
-
- ..\packages\System.Xml.XmlDocument.4.3.0\lib\net46\System.Xml.XmlDocument.dll
-
-
- ..\packages\System.Xml.XPath.4.3.0\lib\net46\System.Xml.XPath.dll
-
-
- ..\packages\System.Xml.XPath.XDocument.4.3.0\lib\net46\System.Xml.XPath.XDocument.dll
-
-
-
-
-
-
-
-
-
-
-
+
-
-
- Designer
-
+
+
-
-
+
-
-
-
\ No newline at end of file
+
+
diff --git a/CSharpMinifier/CompileUtils.cs b/CSharpMinifier/CompileUtils.cs
index 8ed8029..900b7a1 100644
--- a/CSharpMinifier/CompileUtils.cs
+++ b/CSharpMinifier/CompileUtils.cs
@@ -1,27 +1,135 @@
-using Microsoft.CSharp;
-using System.CodeDom.Compiler;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
namespace CSharpMinifier
{
- public class CompileUtils
- {
- public static bool CanCompile(string program)
- {
- return !Compile(program).Errors.HasErrors;
- }
-
- public static CompilerResults Compile(string program)
- {
- CompilerResults compilerResults = null;
- using (CSharpCodeProvider provider = new CSharpCodeProvider())
- {
- compilerResults = provider.CompileAssemblyFromSource(new CompilerParameters(new string[]
- {
- "System.dll"
- }),
- new string[] { program });
- }
- return compilerResults;
- }
- }
+ using System;
+ using System.Collections.Generic;
+
+ ///
+ /// Emulates System.CodeDom.Compiler.CompilerError.
+ ///
+
+ public sealed class CompilerError
+ {
+ public string ErrorNumber { get; }
+ public string ErrorText { get; }
+ public string FileName { get; }
+ public bool IsWarning { get; }
+ public int Line { get; }
+ public int Column { get; }
+
+ public CompilerError(bool isWarning, string errorNumber, string errorText,
+ string fileName, int line, int column)
+ {
+ IsWarning = isWarning;
+ ErrorNumber = errorNumber;
+ ErrorText = errorText;
+ FileName = fileName;
+ Line = line;
+ Column = column;
+ }
+
+ public override string ToString() =>
+ $"{FileName}({Line},{Column}): {(IsWarning ? "warning" : "error")} {ErrorNumber}: {ErrorText}";
+ }
+
+ ///
+ /// Emulates System.CodeDom.Compiler.CompilerErrorCollection.
+ ///
+
+ public sealed class CompilerErrorCollection : Collection
+ {
+ public CompilerErrorCollection(IEnumerable errors) :
+ base(Array.AsReadOnly(errors.ToArray())) {}
+
+ public bool HasErrors => this.Any(e => !e.IsWarning);
+ public bool HasWarnings => this.Any(e => e.IsWarning);
+ }
+
+ ///
+ /// Emulates System.CodeDom.Compiler.CompilerResults.
+ ///
+
+ public class CompilerResults
+ {
+ internal CompilerResults(IEnumerable errors,
+ int nativeCompilerReturnValue,
+ IList output)
+ {
+ Errors = new CompilerErrorCollection(errors);
+ NativeCompilerReturnValue = nativeCompilerReturnValue;
+ Output = new ReadOnlyCollection(output);
+ }
+
+ public CompilerErrorCollection Errors { get; }
+ public int NativeCompilerReturnValue { get; }
+ public IReadOnlyCollection Output { get; }
+ }
+
+ public class CompileUtils
+ {
+ public static bool CanCompile(string program, string cscPath)
+ {
+ return !Compile(program, cscPath).Errors.HasErrors;
+ }
+
+ public static CompilerResults Compile(string program, string cscPath)
+ {
+ if (!File.Exists(cscPath))
+ throw new FileNotFoundException("C# compiler not found at: " + cscPath);
+
+ var path = Path.ChangeExtension(Path.GetTempFileName(), ".cs");
+ File.WriteAllText(path, program, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
+ using (var process = Process.Start(new ProcessStartInfo
+ {
+ FileName = cscPath,
+ Arguments = path,
+ CreateNoWindow = true,
+ UseShellExecute = false,
+ RedirectStandardError = true,
+ RedirectStandardOutput = true,
+ }))
+ {
+ var output = new List();
+
+ void OnData(object sender, DataReceivedEventArgs args)
+ {
+ if (args.Data == null)
+ return; // EOI
+ lock (output)
+ output.Add(args.Data);
+ }
+
+ process.OutputDataReceived += OnData;
+ process.ErrorDataReceived += OnData;
+
+ process.BeginErrorReadLine();
+ process.BeginOutputReadLine();
+ process.WaitForExit();
+
+ var errors =
+ from line in output
+ from Match m in Regex.Matches(line, @"^(.+) *\( *([0-9]+) *, *([0-9]+) *\) *: *(error|warning) +(CS[0-9]+) *: *(.+)$")
+ select m.Groups.Cast()
+ .Skip(1)
+ .Select(g => g.Value)
+ .ToArray()
+ into groups
+ select new CompilerError(fileName: groups[0].Trim(),
+ line: int.Parse(groups[1], NumberStyles.None, CultureInfo.InvariantCulture),
+ column: int.Parse(groups[2], NumberStyles.None, CultureInfo.InvariantCulture),
+ isWarning: groups[3] == "warning",
+ errorNumber: groups[4],
+ errorText: groups[5].Trim());
+
+ return new CompilerResults(errors, process.ExitCode, output);
+ }
+ }
+ }
}
diff --git a/CSharpMinifier/Properties/AssemblyInfo.cs b/CSharpMinifier/Properties/AssemblyInfo.cs
deleted file mode 100644
index 2635b8c..0000000
--- a/CSharpMinifier/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-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("CSharpMinifier")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("CSharpMinifier")]
-[assembly: AssemblyCopyright("Copyright © 2013")]
-[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("c10cd76d-98b2-43b5-9813-035afa0051b6")]
-
-// 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/CSharpMinifier/packages.config b/CSharpMinifier/packages.config
deleted file mode 100644
index d1da915..0000000
--- a/CSharpMinifier/packages.config
+++ /dev/null
@@ -1,59 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/global.json b/global.json
new file mode 100644
index 0000000..21e27ce
--- /dev/null
+++ b/global.json
@@ -0,0 +1,5 @@
+{
+ "sdk": {
+ "version": "2.1.500"
+ }
+}
\ No newline at end of file
diff --git a/install.cmd b/install.cmd
new file mode 100644
index 0000000..92c0e05
--- /dev/null
+++ b/install.cmd
@@ -0,0 +1,3 @@
+@echo off
+NuGet install Microsoft.Net.Compilers -Version 2.10.0 -OutputDirectory "%~dp0tools" ^
+ && ren "%~dp0tools\Microsoft.Net.Compilers.2.10.0" Microsoft.Net.Compilers