├── .gitattributes ├── .gitignore ├── DotNetEditor.Tests ├── CodeRunnerTests.cs ├── DotNetEditor.Tests.csproj ├── Properties │ └── AssemblyInfo.cs ├── SkippableTest │ ├── SkipTestException.cs │ ├── SkippableFactAttribute.cs │ ├── SkippableTheoryAttribute.cs │ └── XunitExtensions │ │ ├── SkippableFactDiscoverer.cs │ │ ├── SkippableFactMessageBus.cs │ │ ├── SkippableFactTestCase.cs │ │ ├── SkippableTheoryDiscoverer.cs │ │ └── SkippableTheoryTestCase.cs ├── TestCodeRunnerOutput.cs ├── TextWriterWithConsoleColorTests.cs ├── app.config └── constants.cs ├── DotNetEditor.sln ├── DotNetEditor ├── AboutBox.Designer.cs ├── AboutBox.cs ├── AboutBox.resx ├── App.config ├── App.xaml ├── App.xaml.cs ├── AppCommands.cs ├── AvalonUtils │ ├── AvalonCodeRunnerOutput.cs │ └── PixelSnapper.cs ├── CodeRunner │ ├── CSCodeRunner.cs │ ├── CodeRunnerBase.cs │ ├── CodeRunnerException.cs │ ├── ICodeRunnerOutput.cs │ └── VBCodeRunner.cs ├── ConsoleColorScheme.cs ├── ConsoleUtil.cs ├── Converters.cs ├── DotNetEditor.GeneratedMSBuildEditorConfig.editorconfig ├── DotNetEditor.csproj ├── DotNetEditor.ico ├── DumpReader.cs ├── FileUtils │ └── FileHandler.cs ├── FodyWeavers.xml ├── GrayscaleEffect │ ├── GrayscaleEffect.cs │ ├── GrayscaleEffect.fx.ps │ └── GrayscaleEffect.hlsl ├── Icons.xaml ├── Images │ ├── about-30.png │ ├── cs-30.png │ ├── down_left-30.png │ ├── open_folder-30.png │ ├── save-30.png │ ├── save_as-30.png │ └── vb-30.png ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ ├── Settings.settings │ └── app.manifest ├── TextBuffer │ └── TextBuffer.cs ├── TextData │ ├── aboutbox.txt │ └── samplecode.txt └── TextWriterWithConsoleColor │ ├── ColorInfo.cs │ ├── IWithConsoleColor.cs │ ├── StringWriterBW.cs │ ├── StringWriterColor.cs │ └── TextWriterWithConsoleColor.cs ├── GPLv3 ├── LICENSE ├── README.md └── app_icon ├── DotNetEditor-16.svg ├── DotNetEditor-24.svg ├── DotNetEditor-256.svg ├── DotNetEditor-32.svg ├── DotNetEditor-40.svg ├── DotNetEditor-48.svg ├── DotNetEditor-64.svg └── build_app_icon.bat /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | 3 | *.jpg binary 4 | *.png binary 5 | *.gif binary 6 | *.ico binary 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Added by user 2 | 3 | # Costura.Fody 4 | FodyWeavers.xsd 5 | 6 | ## Ignore Visual Studio temporary files, build results, and 7 | ## files generated by popular Visual Studio add-ons. 8 | 9 | # User-specific files 10 | *.suo 11 | *.user 12 | *.userosscache 13 | *.sln.docstates 14 | 15 | # User-specific files (MonoDevelop/Xamarin Studio) 16 | *.userprefs 17 | 18 | # Build results 19 | [Dd]ebug/ 20 | [Dd]ebugPublic/ 21 | [Rr]elease/ 22 | [Rr]eleases/ 23 | x64/ 24 | x86/ 25 | bld/ 26 | [Bb]in/ 27 | [Oo]bj/ 28 | [Ll]og/ 29 | app_icon/*.png 30 | 31 | # Visual Studio 2015 cache/options directory 32 | .vs/ 33 | # Uncomment if you have tasks that create the project's static files in wwwroot 34 | #wwwroot/ 35 | 36 | # MSTest test Results 37 | [Tt]est[Rr]esult*/ 38 | [Bb]uild[Ll]og.* 39 | 40 | # NUNIT 41 | *.VisualState.xml 42 | TestResult.xml 43 | 44 | # Build Results of an ATL Project 45 | [Dd]ebugPS/ 46 | [Rr]eleasePS/ 47 | dlldata.c 48 | 49 | # DNX 50 | project.lock.json 51 | artifacts/ 52 | 53 | *_i.c 54 | *_p.c 55 | *_i.h 56 | *.ilk 57 | *.meta 58 | *.obj 59 | *.pch 60 | *.pdb 61 | *.pgc 62 | *.pgd 63 | *.rsp 64 | *.sbr 65 | *.tlb 66 | *.tli 67 | *.tlh 68 | *.tmp 69 | *.tmp_proj 70 | *.log 71 | *.vspscc 72 | *.vssscc 73 | .builds 74 | *.pidb 75 | *.svclog 76 | *.scc 77 | 78 | # Chutzpah Test files 79 | _Chutzpah* 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opendb 86 | *.opensdf 87 | *.sdf 88 | *.cachefile 89 | *.VC.db 90 | *.VC.VC.opendb 91 | 92 | # Visual Studio profiler 93 | *.psess 94 | *.vsp 95 | *.vspx 96 | *.sap 97 | 98 | # TFS 2012 Local Workspace 99 | $tf/ 100 | 101 | # Guidance Automation Toolkit 102 | *.gpState 103 | 104 | # ReSharper is a .NET coding add-in 105 | _ReSharper*/ 106 | *.[Rr]e[Ss]harper 107 | *.DotSettings.user 108 | 109 | # JustCode is a .NET coding add-in 110 | .JustCode 111 | 112 | # TeamCity is a build add-in 113 | _TeamCity* 114 | 115 | # DotCover is a Code Coverage Tool 116 | *.dotCover 117 | 118 | # NCrunch 119 | _NCrunch_* 120 | .*crunch*.local.xml 121 | nCrunchTemp_* 122 | 123 | # MightyMoose 124 | *.mm.* 125 | AutoTest.Net/ 126 | 127 | # Web workbench (sass) 128 | .sass-cache/ 129 | 130 | # Installshield output folder 131 | [Ee]xpress/ 132 | 133 | # DocProject is a documentation generator add-in 134 | DocProject/buildhelp/ 135 | DocProject/Help/*.HxT 136 | DocProject/Help/*.HxC 137 | DocProject/Help/*.hhc 138 | DocProject/Help/*.hhk 139 | DocProject/Help/*.hhp 140 | DocProject/Help/Html2 141 | DocProject/Help/html 142 | 143 | # Click-Once directory 144 | publish/ 145 | 146 | # Publish Web Output 147 | *.[Pp]ublish.xml 148 | *.azurePubxml 149 | # TODO: Comment the next line if you want to checkin your web deploy settings 150 | # but database connection strings (with potential passwords) will be unencrypted 151 | *.pubxml 152 | *.publishproj 153 | 154 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 155 | # checkin your Azure Web App publish settings, but sensitive information contained 156 | # in these scripts will be unencrypted 157 | PublishScripts/ 158 | 159 | # NuGet Packages 160 | *.nupkg 161 | # The packages folder can be ignored because of Package Restore 162 | **/packages/* 163 | # except build/, which is used as an MSBuild target. 164 | !**/packages/build/ 165 | # Uncomment if necessary however generally it will be regenerated when needed 166 | #!**/packages/repositories.config 167 | # NuGet v3's project.json files produces more ignoreable files 168 | *.nuget.props 169 | *.nuget.targets 170 | 171 | # Microsoft Azure Build Output 172 | csx/ 173 | *.build.csdef 174 | 175 | # Microsoft Azure Emulator 176 | ecf/ 177 | rcf/ 178 | 179 | # Windows Store app package directories and files 180 | AppPackages/ 181 | BundleArtifacts/ 182 | Package.StoreAssociation.xml 183 | _pkginfo.txt 184 | 185 | # Visual Studio cache files 186 | # files ending in .cache can be ignored 187 | *.[Cc]ache 188 | # but keep track of directories ending in .cache 189 | !*.[Cc]ache/ 190 | 191 | # Others 192 | ClientBin/ 193 | ~$* 194 | *~ 195 | *.dbmdl 196 | *.dbproj.schemaview 197 | *.pfx 198 | *.publishsettings 199 | node_modules/ 200 | orleans.codegen.cs 201 | 202 | # Since there are multiple workflows, uncomment next line to ignore bower_components 203 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 204 | #bower_components/ 205 | 206 | # RIA/Silverlight projects 207 | Generated_Code/ 208 | 209 | # Backup & report files from converting an old project file 210 | # to a newer Visual Studio version. Backup files are not needed, 211 | # because we have git ;-) 212 | _UpgradeReport_Files/ 213 | Backup*/ 214 | UpgradeLog*.XML 215 | UpgradeLog*.htm 216 | 217 | # SQL Server files 218 | *.mdf 219 | *.ldf 220 | 221 | # Business Intelligence projects 222 | *.rdl.data 223 | *.bim.layout 224 | *.bim_*.settings 225 | 226 | # Microsoft Fakes 227 | FakesAssemblies/ 228 | 229 | # GhostDoc plugin setting file 230 | *.GhostDoc.xml 231 | 232 | # Node.js Tools for Visual Studio 233 | .ntvs_analysis.dat 234 | 235 | # Visual Studio 6 build log 236 | *.plg 237 | 238 | # Visual Studio 6 workspace options file 239 | *.opt 240 | 241 | # Visual Studio LightSwitch build output 242 | **/*.HTMLClient/GeneratedArtifacts 243 | **/*.DesktopClient/GeneratedArtifacts 244 | **/*.DesktopClient/ModelManifest.xml 245 | **/*.Server/GeneratedArtifacts 246 | **/*.Server/ModelManifest.xml 247 | _Pvt_Extensions 248 | 249 | # Paket dependency manager 250 | .paket/paket.exe 251 | paket-files/ 252 | 253 | # FAKE - F# Make 254 | .fake/ 255 | 256 | # JetBrains Rider 257 | .idea/ 258 | *.sln.iml 259 | -------------------------------------------------------------------------------- /DotNetEditor.Tests/CodeRunnerTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Leung Wing-chung. All rights reserved. 2 | // Use of this source code is governed by a GPLv3 license that can be found in 3 | // the LICENSE file. 4 | 5 | using DotNetEditor.CodeRunner; 6 | using System.Threading.Tasks; 7 | using Xunit; 8 | 9 | namespace DotNetEditor.Tests 10 | { 11 | // Tests writing and/or capturing console output must not be run in parallel 12 | // because they use the same console. 13 | [Collection("Tests using the console")] 14 | public class CodeRunnerTests 15 | { 16 | const string ConsoleOutputLine = Constants.ConsoleOutputLine; 17 | const string DebugTraceLine = Constants.DebugTraceLine; 18 | const string ReturnValueLine = Constants.ReturnValueLine; 19 | const string AbortLine = Constants.AbortLine; 20 | const string Separator = Constants.Separator; 21 | 22 | [Fact] 23 | public async void RunVBCodeInsideSubMain() 24 | { 25 | const string code = "Console.WriteLine(123)"; 26 | 27 | TestCodeRunnerOutput output = new TestCodeRunnerOutput(); 28 | CodeRunnerBase runner = new VBCodeRunner(code, "", output); 29 | Assert.True(await runner.Run(), output.GetText()); 30 | Assert.Equal(ConsoleOutputLine + "123\r\n", output.GetText()); 31 | } 32 | 33 | [Fact] 34 | public async void RunCSCodeInsideSubMain() 35 | { 36 | const string code = "Console.WriteLine(123);"; 37 | 38 | TestCodeRunnerOutput output = new TestCodeRunnerOutput(); 39 | CodeRunnerBase runner = new CSCodeRunner(code, "", output); 40 | Assert.True(await runner.Run(), output.GetText()); 41 | Assert.Equal(ConsoleOutputLine + "123\r\n", output.GetText()); 42 | } 43 | 44 | [Fact] 45 | public async void RunVBCodeInModule() 46 | { 47 | const string code = 48 | "Sub Main() \n Console.WriteLine(123) \n End Sub"; 49 | 50 | TestCodeRunnerOutput output = new TestCodeRunnerOutput(); 51 | CodeRunnerBase runner = new VBCodeRunner(code, "", output); 52 | Assert.True(await runner.Run(), output.GetText()); 53 | Assert.Equal(ConsoleOutputLine + "123\r\n", output.GetText()); 54 | } 55 | 56 | [Fact] 57 | public async void RunCSCodeInClass() 58 | { 59 | const string code = 60 | "static void Main() { Console.WriteLine(123); }"; 61 | 62 | TestCodeRunnerOutput output = new TestCodeRunnerOutput(); 63 | CodeRunnerBase runner = new CSCodeRunner(code, "", output); 64 | Assert.True(await runner.Run(), output.GetText()); 65 | Assert.Equal(ConsoleOutputLine + "123\r\n", output.GetText()); 66 | } 67 | 68 | [Fact] 69 | public async void RunVBCodeAsFullFile() 70 | { 71 | const string code = 72 | "Module Module1 \n Sub Main() \n Console.WriteLine(123) \n End Sub \n End Module"; 73 | 74 | TestCodeRunnerOutput output = new TestCodeRunnerOutput(); 75 | CodeRunnerBase runner = new VBCodeRunner(code, "", output); 76 | Assert.True(await runner.Run(), output.GetText()); 77 | Assert.Equal(ConsoleOutputLine + "123\r\n", output.GetText()); 78 | } 79 | 80 | [Fact] 81 | public async void RunCSCodeAsFullFile() 82 | { 83 | const string code = 84 | "using System; class Class1 { static void Main() { Console.WriteLine(123); } }"; 85 | 86 | TestCodeRunnerOutput output = new TestCodeRunnerOutput(); 87 | CodeRunnerBase runner = new CSCodeRunner(code, "", output); 88 | Assert.True(await runner.Run(), output.GetText()); 89 | Assert.Equal(ConsoleOutputLine + "123\r\n", output.GetText()); 90 | } 91 | 92 | [Fact] 93 | public async void RunVBCodeWithDebugOutput() 94 | { 95 | const string code = "Debug.WriteLine(456) : Console.WriteLine(123)"; 96 | 97 | TestCodeRunnerOutput output = new TestCodeRunnerOutput(); 98 | CodeRunnerBase runner = new VBCodeRunner(code, "", output); 99 | Assert.True(await runner.Run(), output.GetText()); 100 | Assert.Equal( 101 | ConsoleOutputLine + "123\r\n" + Separator + DebugTraceLine + "456\r\n", 102 | output.GetText()); 103 | } 104 | 105 | [Fact] 106 | public async void RunCSCodeWithDebugOutput() 107 | { 108 | const string code = "Debug.WriteLine(456); Console.WriteLine(123);"; 109 | 110 | TestCodeRunnerOutput output = new TestCodeRunnerOutput(); 111 | CodeRunnerBase runner = new CSCodeRunner(code, "", output); 112 | Assert.True(await runner.Run(), output.GetText()); 113 | Assert.Equal( 114 | ConsoleOutputLine + "123\r\n" + Separator + DebugTraceLine + "456\r\n", 115 | output.GetText()); 116 | } 117 | 118 | [Fact] 119 | public async void RunVBCodeWithTraceOutput() 120 | { 121 | const string code = "Debug.WriteLine(456) : Console.WriteLine(123)"; 122 | 123 | TestCodeRunnerOutput output = new TestCodeRunnerOutput(); 124 | CodeRunnerBase runner = new VBCodeRunner(code, "", output); 125 | Assert.True(await runner.Run(), output.GetText()); 126 | Assert.Equal( 127 | ConsoleOutputLine + "123\r\n" + Separator + DebugTraceLine + "456\r\n", 128 | output.GetText()); 129 | } 130 | 131 | [Fact] 132 | public async void RunCSCodeWithTraceOutput() 133 | { 134 | const string code = "Trace.WriteLine(456); Console.WriteLine(123);"; 135 | 136 | TestCodeRunnerOutput output = new TestCodeRunnerOutput(); 137 | CodeRunnerBase runner = new CSCodeRunner(code, "", output); 138 | Assert.True(await runner.Run(), output.GetText()); 139 | Assert.Equal( 140 | ConsoleOutputLine + "123\r\n" + Separator + DebugTraceLine + "456\r\n", 141 | output.GetText()); 142 | } 143 | 144 | [Fact] 145 | public async void ReturnCodeVB() 146 | { 147 | const string code = "Function Main() As Integer \n Return 2 \nEnd Function"; 148 | 149 | TestCodeRunnerOutput output = new TestCodeRunnerOutput(); 150 | CodeRunnerBase runner = new VBCodeRunner(code, "", output); 151 | 152 | Assert.True(await runner.Run(), output.GetText()); 153 | Assert.Equal(ConsoleOutputLine + Separator + ReturnValueLine + "2\n", output.GetText()); 154 | } 155 | 156 | [Fact] 157 | public async void ReturnCodeCS() 158 | { 159 | const string code = "static int Main() { return 2; }"; 160 | 161 | TestCodeRunnerOutput output = new TestCodeRunnerOutput(); 162 | CodeRunnerBase runner = new CSCodeRunner(code, "", output); 163 | 164 | Assert.True(await runner.Run(), output.GetText()); 165 | Assert.Equal(ConsoleOutputLine + Separator + ReturnValueLine + "2\n", output.GetText()); 166 | } 167 | 168 | [Fact] 169 | public async void TerminateVBCodeAtStart() 170 | { 171 | const string code = "Console.WriteLine(123)"; 172 | 173 | TestCodeRunnerOutput output = new TestCodeRunnerOutput(); 174 | CodeRunnerBase runner = new VBCodeRunner(code, "", output); 175 | Task task = runner.Run(); 176 | runner.Terminate(); 177 | 178 | Assert.False(await task, output.GetText()); 179 | Assert.True(output.GetText().Contains(AbortLine), output.GetText()); 180 | } 181 | 182 | [Fact] 183 | public async void TerminateVBCodeAtMiddle() 184 | { 185 | const string code = "Console.WriteLine(123) : DO : LOOP"; 186 | 187 | TestCodeRunnerOutput output = new TestCodeRunnerOutput(); 188 | CodeRunnerBase runner = new VBCodeRunner(code, "", output); 189 | Task task = runner.Run(); 190 | await Task.Delay(100); 191 | runner.Terminate(); 192 | 193 | Assert.False(await task, output.GetText()); 194 | Assert.Equal(ConsoleOutputLine + "123\r\n" + Separator + AbortLine, output.GetText()); 195 | } 196 | 197 | [Fact] 198 | public async void TerminateCSCodeAtStart() 199 | { 200 | const string code = "Console.WriteLine(123);"; 201 | 202 | TestCodeRunnerOutput output = new TestCodeRunnerOutput(); 203 | CodeRunnerBase runner = new CSCodeRunner(code, "", output); 204 | Task task = runner.Run(); 205 | runner.Terminate(); 206 | 207 | Assert.False(await task, output.GetText()); 208 | Assert.True(output.GetText().Contains(AbortLine), output.GetText()); 209 | } 210 | 211 | [Fact] 212 | public async void TerminateCSCodeAtMiddle() 213 | { 214 | const string code = "Console.WriteLine(123); while (true) ;"; 215 | 216 | TestCodeRunnerOutput output = new TestCodeRunnerOutput(); 217 | CodeRunnerBase runner = new CSCodeRunner(code, "", output); 218 | Task task = runner.Run(); 219 | await Task.Delay(100); 220 | runner.Terminate(); 221 | 222 | Assert.False(await task, output.GetText()); 223 | Assert.Equal(ConsoleOutputLine + "123\r\n" + Separator + AbortLine, output.GetText()); 224 | } 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /DotNetEditor.Tests/DotNetEditor.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {683BCD42-80C6-4D29-B204-1BBF871CB42B} 8 | Library 9 | Properties 10 | DotNetEditor.Tests 11 | DotNetEditor.Tests 12 | v4.6.1 13 | 512 14 | 15 | 16 | 17 | 18 | 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | {e54077c3-703e-4a13-9d01-382b30e8aaee} 73 | DotNetEditor 74 | 75 | 76 | 77 | 78 | 6.1.2.30 79 | 80 | 81 | 4.5.0 82 | 83 | 84 | 2.4.1 85 | 86 | 87 | 2.4.1 88 | runtime; build; native; contentfiles; analyzers; buildtransitive 89 | all 90 | 91 | 92 | 2.4.1 93 | 94 | 95 | 2.4.3 96 | runtime; build; native; contentfiles; analyzers; buildtransitive 97 | all 98 | 99 | 100 | 101 | 108 | -------------------------------------------------------------------------------- /DotNetEditor.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("DotNetEditor.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("DotNetEditor.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("683bcd42-80c6-4d29-b204-1bbf871cb42b")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /DotNetEditor.Tests/SkippableTest/SkipTestException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SkippableTest 4 | { 5 | public class SkipTestException : Exception 6 | { 7 | public SkipTestException(string reason) 8 | : base(reason) { } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /DotNetEditor.Tests/SkippableTest/SkippableFactAttribute.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | using Xunit.Sdk; 3 | 4 | namespace SkippableTest 5 | { 6 | [XunitTestCaseDiscoverer("SkippableTest.XunitExtensions.SkippableFactDiscoverer", 7 | "DotNetEditor.Tests")] 8 | public class SkippableFactAttribute : FactAttribute { } 9 | } 10 | -------------------------------------------------------------------------------- /DotNetEditor.Tests/SkippableTest/SkippableTheoryAttribute.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | using Xunit.Sdk; 3 | 4 | namespace SkippableTest 5 | { 6 | [XunitTestCaseDiscoverer("SkippableTest.XunitExtensions.SkippableTheoryDiscoverer", 7 | "DotNetEditor.Tests")] 8 | public class SkippableTheoryAttribute : TheoryAttribute { } 9 | } 10 | -------------------------------------------------------------------------------- /DotNetEditor.Tests/SkippableTest/XunitExtensions/SkippableFactDiscoverer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Xunit.Abstractions; 3 | using Xunit.Sdk; 4 | 5 | namespace SkippableTest.XunitExtensions 6 | { 7 | public class SkippableFactDiscoverer : IXunitTestCaseDiscoverer 8 | { 9 | readonly IMessageSink diagnosticMessageSink; 10 | 11 | public SkippableFactDiscoverer(IMessageSink diagnosticMessageSink) 12 | { 13 | this.diagnosticMessageSink = diagnosticMessageSink; 14 | } 15 | 16 | public IEnumerable Discover(ITestFrameworkDiscoveryOptions discoveryOptions, 17 | ITestMethod testMethod, 18 | IAttributeInfo factAttribute) 19 | { 20 | yield return new SkippableFactTestCase( 21 | diagnosticMessageSink, 22 | discoveryOptions.MethodDisplayOrDefault(), 23 | discoveryOptions.MethodDisplayOptionsOrDefault(), 24 | testMethod); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /DotNetEditor.Tests/SkippableTest/XunitExtensions/SkippableFactMessageBus.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Xunit.Abstractions; 3 | using Xunit.Sdk; 4 | 5 | namespace SkippableTest.XunitExtensions 6 | { 7 | public class SkippableFactMessageBus : IMessageBus 8 | { 9 | readonly IMessageBus innerBus; 10 | 11 | public SkippableFactMessageBus(IMessageBus innerBus) 12 | { 13 | this.innerBus = innerBus; 14 | } 15 | 16 | public int DynamicallySkippedTestCount { get; private set; } 17 | 18 | public void Dispose() { } 19 | 20 | public bool QueueMessage(IMessageSinkMessage message) 21 | { 22 | var testFailed = message as ITestFailed; 23 | if (testFailed != null) 24 | { 25 | var exceptionType = testFailed.ExceptionTypes.FirstOrDefault(); 26 | if (exceptionType == typeof(SkipTestException).FullName) 27 | { 28 | DynamicallySkippedTestCount++; 29 | return innerBus.QueueMessage(new TestSkipped(testFailed.Test, testFailed.Messages.FirstOrDefault())); 30 | } 31 | } 32 | 33 | // Nothing we care about, send it on its way 34 | return innerBus.QueueMessage(message); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /DotNetEditor.Tests/SkippableTest/XunitExtensions/SkippableFactTestCase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Xunit.Abstractions; 5 | using Xunit.Sdk; 6 | 7 | namespace SkippableTest.XunitExtensions 8 | { 9 | public class SkippableFactTestCase : XunitTestCase 10 | { 11 | [Obsolete("Called by the de-serializer; should only be called by deriving classes for de-serialization purposes")] 12 | public SkippableFactTestCase() { } 13 | 14 | public SkippableFactTestCase(IMessageSink diagnosticMessageSink, 15 | TestMethodDisplay defaultMethodDisplay, 16 | TestMethodDisplayOptions defaultMethodDisplayOptions, 17 | ITestMethod testMethod, 18 | object[] testMethodArguments = null) 19 | : base(diagnosticMessageSink, defaultMethodDisplay, defaultMethodDisplayOptions, 20 | testMethod, testMethodArguments) { } 21 | 22 | public override async Task 23 | RunAsync(IMessageSink diagnosticMessageSink, 24 | IMessageBus messageBus, 25 | object[] constructorArguments, 26 | ExceptionAggregator aggregator, 27 | CancellationTokenSource cancellationTokenSource) 28 | { 29 | var skipMessageBus = new SkippableFactMessageBus(messageBus); 30 | var result = await base.RunAsync(diagnosticMessageSink, skipMessageBus, 31 | constructorArguments, aggregator, 32 | cancellationTokenSource); 33 | if (skipMessageBus.DynamicallySkippedTestCount > 0) 34 | { 35 | result.Failed -= skipMessageBus.DynamicallySkippedTestCount; 36 | result.Skipped += skipMessageBus.DynamicallySkippedTestCount; 37 | } 38 | 39 | return result; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /DotNetEditor.Tests/SkippableTest/XunitExtensions/SkippableTheoryDiscoverer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Xunit.Abstractions; 4 | using Xunit.Sdk; 5 | 6 | namespace SkippableTest.XunitExtensions 7 | { 8 | public class SkippableTheoryDiscoverer : IXunitTestCaseDiscoverer 9 | { 10 | readonly IMessageSink diagnosticMessageSink; 11 | readonly TheoryDiscoverer theoryDiscoverer; 12 | 13 | public SkippableTheoryDiscoverer(IMessageSink diagnosticMessageSink) 14 | { 15 | this.diagnosticMessageSink = diagnosticMessageSink; 16 | 17 | theoryDiscoverer = new TheoryDiscoverer(diagnosticMessageSink); 18 | } 19 | 20 | public IEnumerable Discover(ITestFrameworkDiscoveryOptions discoveryOptions, 21 | ITestMethod testMethod, 22 | IAttributeInfo factAttribute) 23 | { 24 | var defaultMethodDisplay = discoveryOptions.MethodDisplayOrDefault(); 25 | var defaultMethodDisplayOptions = discoveryOptions.MethodDisplayOptionsOrDefault(); 26 | 27 | // Unlike fact discovery, the underlying algorithm for theories is complex, so we let 28 | // the theory discoverer do its work, and do a little on-the-fly conversion into our own 29 | // test cases. 30 | return theoryDiscoverer 31 | .Discover(discoveryOptions, testMethod, factAttribute) 32 | .Select(testCase => ( 33 | testCase is XunitTheoryTestCase 34 | ? (IXunitTestCase)new SkippableTheoryTestCase( 35 | diagnosticMessageSink, defaultMethodDisplay, 36 | defaultMethodDisplayOptions, testCase.TestMethod) 37 | : new SkippableFactTestCase( 38 | diagnosticMessageSink, defaultMethodDisplay, 39 | defaultMethodDisplayOptions, testCase.TestMethod, 40 | testCase.TestMethodArguments)) 41 | ); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /DotNetEditor.Tests/SkippableTest/XunitExtensions/SkippableTheoryTestCase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Xunit.Abstractions; 5 | using Xunit.Sdk; 6 | 7 | namespace SkippableTest.XunitExtensions 8 | { 9 | public class SkippableTheoryTestCase : XunitTheoryTestCase 10 | { 11 | [Obsolete("Called by the de-serializer; should only be called by deriving classes for de-serialization purposes")] 12 | public SkippableTheoryTestCase() { } 13 | 14 | public SkippableTheoryTestCase(IMessageSink diagnosticMessageSink, 15 | TestMethodDisplay defaultMethodDisplay, 16 | TestMethodDisplayOptions defaultMethodDisplayOptions, 17 | ITestMethod testMethod) 18 | : base(diagnosticMessageSink, defaultMethodDisplay, defaultMethodDisplayOptions, 19 | testMethod) { } 20 | 21 | public override async Task 22 | RunAsync(IMessageSink diagnosticMessageSink, 23 | IMessageBus messageBus, 24 | object[] constructorArguments, 25 | ExceptionAggregator aggregator, 26 | CancellationTokenSource cancellationTokenSource) 27 | { 28 | // Duplicated code from SkippableFactTestCase. I'm sure we could find a way to de-dup 29 | // with some thought. 30 | var skipMessageBus = new SkippableFactMessageBus(messageBus); 31 | var result = await base.RunAsync(diagnosticMessageSink, skipMessageBus, 32 | constructorArguments, aggregator, 33 | cancellationTokenSource); 34 | if (skipMessageBus.DynamicallySkippedTestCount > 0) 35 | { 36 | result.Failed -= skipMessageBus.DynamicallySkippedTestCount; 37 | result.Skipped += skipMessageBus.DynamicallySkippedTestCount; 38 | } 39 | 40 | return result; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /DotNetEditor.Tests/TestCodeRunnerOutput.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Leung Wing-chung. All rights reserved. 2 | // Use of this source code is governed by a GPLv3 license that can be found in 3 | // the LICENSE file. 4 | 5 | using ICSharpCode.AvalonEdit.Document; 6 | using System.Text; 7 | using System.Windows.Media; 8 | using Xunit; 9 | 10 | namespace DotNetEditor.Tests 11 | { 12 | public class TestCodeRunnerOutput : CodeRunner.ICodeRunnerOutput 13 | { 14 | public TestCodeRunnerOutput() 15 | { 16 | _text = new StringBuilder(); 17 | _format = new TextSegmentCollection(); 18 | } 19 | 20 | public void AppendText(string text) 21 | { 22 | _text.Append(text); 23 | } 24 | 25 | public void AppendTextWithStyle(string text, Color foregroundColor, Color backgroundColor, 26 | bool? isBold, bool? isItalic) 27 | { 28 | int startOffset = _text.Length; 29 | _text.Append(text); 30 | int endOffset = _text.Length; 31 | AddFormatData(startOffset, endOffset, foregroundColor, backgroundColor, isBold, isItalic); 32 | } 33 | 34 | public string GetText() 35 | { 36 | return _text.ToString(); 37 | } 38 | 39 | public void AssertTextFormat(int offset, Color? foregroundColor, Color? backgroundColor, 40 | bool? IsBold, bool? IsItalic) 41 | { 42 | Color? actualForegroundColor = null; 43 | Color? actualBackgroundColor = null; 44 | bool actualIsBold = false; 45 | bool actualIsItalic = false; 46 | foreach (var segment in _format.FindSegmentsContaining(offset)) 47 | { 48 | actualForegroundColor = segment.ForegroundColor; 49 | actualBackgroundColor = segment.BackgroundColor; 50 | actualIsBold = segment.IsBold ?? actualIsBold; 51 | actualIsItalic = segment.IsItalic ?? actualIsItalic; 52 | } 53 | 54 | if (foregroundColor.HasValue) 55 | { 56 | Assert.Equal(foregroundColor, actualForegroundColor); 57 | } 58 | if (backgroundColor.HasValue) 59 | { 60 | Assert.Equal(backgroundColor, actualBackgroundColor); 61 | } 62 | if (IsBold.HasValue) 63 | { 64 | Assert.Equal(IsBold, actualIsBold); 65 | } 66 | if (IsItalic.HasValue) 67 | { 68 | Assert.Equal(IsItalic, actualIsItalic); 69 | } 70 | return; 71 | } 72 | 73 | public void ClearOutput() 74 | { 75 | _text.Clear(); 76 | _format.Clear(); 77 | } 78 | 79 | public bool IsEmpty() 80 | { 81 | return _text.Length == 0; 82 | } 83 | 84 | private void AddFormatData(int startOffset, int endOffset, 85 | Color foregroundColor, Color backgroundColor, bool? IsBold, bool? IsItalic) 86 | { 87 | AvalonCodeRunnerOutput.TextFormat fmt = new AvalonCodeRunnerOutput.TextFormat(); 88 | fmt.StartOffset = startOffset; 89 | fmt.EndOffset = endOffset; 90 | fmt.ForegroundColor = foregroundColor; 91 | fmt.BackgroundColor = backgroundColor; 92 | fmt.IsBold = IsBold; 93 | fmt.IsItalic = IsItalic; 94 | 95 | _format.Add(fmt); 96 | } 97 | 98 | private StringBuilder _text; 99 | private TextSegmentCollection _format; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /DotNetEditor.Tests/TextWriterWithConsoleColorTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Leung Wing-chung. All rights reserved. 2 | // Use of this source code is governed by a GPLv3 license that can be found in 3 | // the LICENSE file. 4 | 5 | using DotNetEditor.CodeRunner; 6 | using SkippableTest; 7 | using System; 8 | using System.Windows.Media; 9 | using Xunit; 10 | 11 | namespace DotNetEditor.Tests 12 | { 13 | // Tests writing and/or capturing console output must not be run in parallel 14 | // because they use the same console. 15 | [Collection("Tests using the console")] 16 | public class TextWriterWithConsoleColorTests 17 | { 18 | const string ConsoleOutputLine = Constants.ConsoleOutputLine; 19 | 20 | private void SkipTestIfNoConsoleColor() 21 | { 22 | const string noConsoleColor = "Console color not available."; 23 | 24 | ConsoleColor[] colorList = (ConsoleColor[]) Enum.GetValues(typeof(ConsoleColor)); 25 | foreach (var color in colorList) 26 | { 27 | Console.ForegroundColor = color; 28 | if (Console.ForegroundColor != color) 29 | { 30 | throw new SkipTestException(noConsoleColor); 31 | } 32 | 33 | Console.BackgroundColor = color; 34 | if (Console.BackgroundColor != color) 35 | { 36 | throw new SkipTestException(noConsoleColor); 37 | } 38 | } 39 | 40 | Console.ResetColor(); 41 | } 42 | 43 | [SkippableFact] 44 | public async void TextWriterWithConsoleColor() 45 | { 46 | SkipTestIfNoConsoleColor(); 47 | 48 | const string code = @" 49 | Console.ForegroundColor = ConsoleColor.Red; 50 | Console.Write(12); 51 | Console.BackgroundColor = ConsoleColor.Green; 52 | Console.Write(34); 53 | Console.ForegroundColor = ConsoleColor.Blue; 54 | Console.Write(56); 55 | Console.BackgroundColor = ConsoleColor.White; 56 | Console.Write(78); 57 | "; 58 | 59 | TestCodeRunnerOutput output = new TestCodeRunnerOutput(); 60 | CodeRunnerBase runner = new CSCodeRunner(code, "", output); 61 | Assert.True(await runner.Run(), output.GetText()); 62 | Assert.Equal(ConsoleOutputLine + "12345678", output.GetText()); 63 | 64 | Color red = ConsoleColorScheme.DefaultColorScheme.Colors[12]; 65 | Color green = ConsoleColorScheme.DefaultColorScheme.Colors[10]; 66 | Color blue = ConsoleColorScheme.DefaultColorScheme.Colors[9]; 67 | Color white = ConsoleColorScheme.DefaultColorScheme.Colors[15]; 68 | 69 | int basePos = ConsoleOutputLine.Length; 70 | output.AssertTextFormat(basePos, red, null, null, null); 71 | output.AssertTextFormat(basePos + 1, red, null, null, null); 72 | output.AssertTextFormat(basePos + 2, red, green, null, null); 73 | output.AssertTextFormat(basePos + 3, red, green, null, null); 74 | output.AssertTextFormat(basePos + 4, blue, green, null, null); 75 | output.AssertTextFormat(basePos + 5, blue, green, null, null); 76 | output.AssertTextFormat(basePos + 6, blue, white, null, null); 77 | output.AssertTextFormat(basePos + 7, blue, white, null, null); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /DotNetEditor.Tests/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /DotNetEditor.Tests/constants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DotNetEditor.Tests 8 | { 9 | static class Constants 10 | { 11 | public const string ConsoleOutputLine = " --- Console output --- \n"; 12 | public const string DebugTraceLine = " --- Debug/trace output --- \n"; 13 | public const string ReturnValueLine = " --- Return value --- \n"; 14 | public const string AbortLine = " --- Execution aborted --- \n"; 15 | public const string Separator = "\n\n"; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /DotNetEditor.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetEditor", "DotNetEditor\DotNetEditor.csproj", "{E54077C3-703E-4A13-9D01-382B30E8AAEE}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetEditor.Tests", "DotNetEditor.Tests\DotNetEditor.Tests.csproj", "{683BCD42-80C6-4D29-B204-1BBF871CB42B}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {E54077C3-703E-4A13-9D01-382B30E8AAEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {E54077C3-703E-4A13-9D01-382B30E8AAEE}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {E54077C3-703E-4A13-9D01-382B30E8AAEE}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {E54077C3-703E-4A13-9D01-382B30E8AAEE}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {683BCD42-80C6-4D29-B204-1BBF871CB42B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {683BCD42-80C6-4D29-B204-1BBF871CB42B}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {683BCD42-80C6-4D29-B204-1BBF871CB42B}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {683BCD42-80C6-4D29-B204-1BBF871CB42B}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /DotNetEditor/AboutBox.Designer.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Leung Wing-chung. All rights reserved. 2 | // Use of this source code is governed by a GPLv3 license that can be found in 3 | // the LICENSE file. 4 | 5 | namespace DotNetEditor 6 | { 7 | partial class AboutBox 8 | { 9 | /// 10 | /// Required designer variable. 11 | /// 12 | private System.ComponentModel.IContainer components = null; 13 | 14 | /// 15 | /// Clean up any resources being used. 16 | /// 17 | protected override void Dispose(bool disposing) 18 | { 19 | if (disposing && (components != null)) 20 | { 21 | components.Dispose(); 22 | } 23 | base.Dispose(disposing); 24 | } 25 | 26 | #region Windows Form Designer generated code 27 | 28 | /// 29 | /// Required method for Designer support - do not modify 30 | /// the contents of this method with the code editor. 31 | /// 32 | private void InitializeComponent() 33 | { 34 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutBox)); 35 | this.tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel(); 36 | this.logoPictureBox = new System.Windows.Forms.PictureBox(); 37 | this.labelProductName = new System.Windows.Forms.Label(); 38 | this.labelVersion = new System.Windows.Forms.Label(); 39 | this.labelCopyright = new System.Windows.Forms.Label(); 40 | this.labelLicense = new System.Windows.Forms.Label(); 41 | this.textBoxDescription = new System.Windows.Forms.TextBox(); 42 | this.okButton = new System.Windows.Forms.Button(); 43 | this.tableLayoutPanel.SuspendLayout(); 44 | ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).BeginInit(); 45 | this.SuspendLayout(); 46 | // 47 | // tableLayoutPanel 48 | // 49 | this.tableLayoutPanel.ColumnCount = 2; 50 | this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 20F)); 51 | this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 80F)); 52 | this.tableLayoutPanel.Controls.Add(this.logoPictureBox, 0, 0); 53 | this.tableLayoutPanel.Controls.Add(this.labelProductName, 1, 0); 54 | this.tableLayoutPanel.Controls.Add(this.labelVersion, 1, 1); 55 | this.tableLayoutPanel.Controls.Add(this.labelCopyright, 1, 2); 56 | this.tableLayoutPanel.Controls.Add(this.labelLicense, 1, 3); 57 | this.tableLayoutPanel.Controls.Add(this.textBoxDescription, 1, 4); 58 | this.tableLayoutPanel.Controls.Add(this.okButton, 1, 5); 59 | this.tableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; 60 | this.tableLayoutPanel.Location = new System.Drawing.Point(9, 9); 61 | this.tableLayoutPanel.Name = "tableLayoutPanel"; 62 | this.tableLayoutPanel.RowCount = 6; 63 | this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); 64 | this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); 65 | this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); 66 | this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); 67 | this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); 68 | this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); 69 | this.tableLayoutPanel.Size = new System.Drawing.Size(417, 265); 70 | this.tableLayoutPanel.TabIndex = 0; 71 | // 72 | // logoPictureBox 73 | // 74 | this.logoPictureBox.Dock = System.Windows.Forms.DockStyle.Fill; 75 | this.logoPictureBox.Image = ((System.Drawing.Image)(resources.GetObject("logoPictureBox.Image"))); 76 | this.logoPictureBox.Location = new System.Drawing.Point(3, 3); 77 | this.logoPictureBox.Name = "logoPictureBox"; 78 | this.tableLayoutPanel.SetRowSpan(this.logoPictureBox, 6); 79 | this.logoPictureBox.Size = new System.Drawing.Size(77, 259); 80 | this.logoPictureBox.TabIndex = 12; 81 | this.logoPictureBox.TabStop = false; 82 | // 83 | // labelProductName 84 | // 85 | this.labelProductName.Dock = System.Windows.Forms.DockStyle.Fill; 86 | this.labelProductName.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 87 | this.labelProductName.Location = new System.Drawing.Point(89, 0); 88 | this.labelProductName.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0); 89 | this.labelProductName.MaximumSize = new System.Drawing.Size(0, 17); 90 | this.labelProductName.Name = "labelProductName"; 91 | this.labelProductName.Size = new System.Drawing.Size(325, 17); 92 | this.labelProductName.TabIndex = 19; 93 | this.labelProductName.Text = "Product Name"; 94 | this.labelProductName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; 95 | // 96 | // labelVersion 97 | // 98 | this.labelVersion.Dock = System.Windows.Forms.DockStyle.Fill; 99 | this.labelVersion.Location = new System.Drawing.Point(89, 17); 100 | this.labelVersion.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0); 101 | this.labelVersion.MaximumSize = new System.Drawing.Size(0, 17); 102 | this.labelVersion.Name = "labelVersion"; 103 | this.labelVersion.Size = new System.Drawing.Size(325, 17); 104 | this.labelVersion.TabIndex = 0; 105 | this.labelVersion.Text = "Version"; 106 | this.labelVersion.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; 107 | // 108 | // labelCopyright 109 | // 110 | this.labelCopyright.Dock = System.Windows.Forms.DockStyle.Fill; 111 | this.labelCopyright.Location = new System.Drawing.Point(89, 34); 112 | this.labelCopyright.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0); 113 | this.labelCopyright.MaximumSize = new System.Drawing.Size(0, 17); 114 | this.labelCopyright.Name = "labelCopyright"; 115 | this.labelCopyright.Size = new System.Drawing.Size(325, 17); 116 | this.labelCopyright.TabIndex = 21; 117 | this.labelCopyright.Text = "Copyright"; 118 | this.labelCopyright.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; 119 | // 120 | // labelLicense 121 | // 122 | this.labelLicense.Dock = System.Windows.Forms.DockStyle.Fill; 123 | this.labelLicense.Location = new System.Drawing.Point(89, 51); 124 | this.labelLicense.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0); 125 | this.labelLicense.MaximumSize = new System.Drawing.Size(0, 17); 126 | this.labelLicense.Name = "labelLicense"; 127 | this.labelLicense.Size = new System.Drawing.Size(325, 17); 128 | this.labelLicense.TabIndex = 22; 129 | this.labelLicense.Text = "License"; 130 | this.labelLicense.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; 131 | // 132 | // textBoxDescription 133 | // 134 | this.textBoxDescription.Dock = System.Windows.Forms.DockStyle.Fill; 135 | this.textBoxDescription.Location = new System.Drawing.Point(89, 71); 136 | this.textBoxDescription.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3); 137 | this.textBoxDescription.Multiline = true; 138 | this.textBoxDescription.Name = "textBoxDescription"; 139 | this.textBoxDescription.ReadOnly = true; 140 | this.textBoxDescription.ScrollBars = System.Windows.Forms.ScrollBars.Both; 141 | this.textBoxDescription.Size = new System.Drawing.Size(325, 162); 142 | this.textBoxDescription.TabIndex = 23; 143 | this.textBoxDescription.TabStop = false; 144 | this.textBoxDescription.Text = "Description"; 145 | // 146 | // okButton 147 | // 148 | this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 149 | this.okButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; 150 | this.okButton.Location = new System.Drawing.Point(339, 239); 151 | this.okButton.Name = "okButton"; 152 | this.okButton.Size = new System.Drawing.Size(75, 23); 153 | this.okButton.TabIndex = 24; 154 | this.okButton.Text = "&OK"; 155 | // 156 | // AboutBox 157 | // 158 | this.AcceptButton = this.okButton; 159 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 160 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 161 | this.ClientSize = new System.Drawing.Size(435, 283); 162 | this.Controls.Add(this.tableLayoutPanel); 163 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 164 | this.MaximizeBox = false; 165 | this.MinimizeBox = false; 166 | this.Name = "AboutBox"; 167 | this.Padding = new System.Windows.Forms.Padding(9); 168 | this.ShowIcon = false; 169 | this.ShowInTaskbar = false; 170 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 171 | this.Text = "AboutBox"; 172 | this.tableLayoutPanel.ResumeLayout(false); 173 | this.tableLayoutPanel.PerformLayout(); 174 | ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).EndInit(); 175 | this.ResumeLayout(false); 176 | 177 | } 178 | 179 | #endregion 180 | 181 | private System.Windows.Forms.TableLayoutPanel tableLayoutPanel; 182 | private System.Windows.Forms.PictureBox logoPictureBox; 183 | private System.Windows.Forms.Label labelProductName; 184 | private System.Windows.Forms.Label labelVersion; 185 | private System.Windows.Forms.Label labelCopyright; 186 | private System.Windows.Forms.Label labelLicense; 187 | private System.Windows.Forms.TextBox textBoxDescription; 188 | private System.Windows.Forms.Button okButton; 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /DotNetEditor/AboutBox.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Threading.Tasks; 8 | using System.Windows.Forms; 9 | 10 | namespace DotNetEditor 11 | { 12 | // TODO: remake the dialog box in WPF. 13 | partial class AboutBox : Form 14 | { 15 | public AboutBox() 16 | { 17 | InitializeComponent(); 18 | this.Text = String.Format("About {0}", AssemblyTitle); 19 | this.labelProductName.Text = AssemblyProduct; 20 | this.labelVersion.Text = String.Format("Version {0}", AssemblyVersion); 21 | this.labelCopyright.Text = AssemblyCopyright; 22 | this.labelLicense.Text = "Released under GPLv3 with exceptions."; 23 | this.textBoxDescription.Text = 24 | Properties.Resources.aboutbox 25 | .Replace("\n", Environment.NewLine) 26 | .Replace("{app}", AssemblyProduct); 27 | } 28 | 29 | #region Assembly Attribute Accessors 30 | 31 | public string AssemblyTitle 32 | { 33 | get 34 | { 35 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false); 36 | if (attributes.Length > 0) 37 | { 38 | AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0]; 39 | if (titleAttribute.Title != "") 40 | { 41 | return titleAttribute.Title; 42 | } 43 | } 44 | return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase); 45 | } 46 | } 47 | 48 | public string AssemblyVersion 49 | { 50 | get 51 | { 52 | return Assembly.GetExecutingAssembly().GetName().Version.ToString(); 53 | } 54 | } 55 | 56 | public string AssemblyDescription 57 | { 58 | get 59 | { 60 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false); 61 | if (attributes.Length == 0) 62 | { 63 | return ""; 64 | } 65 | return ((AssemblyDescriptionAttribute)attributes[0]).Description; 66 | } 67 | } 68 | 69 | public string AssemblyProduct 70 | { 71 | get 72 | { 73 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false); 74 | if (attributes.Length == 0) 75 | { 76 | return ""; 77 | } 78 | return ((AssemblyProductAttribute)attributes[0]).Product; 79 | } 80 | } 81 | 82 | public string AssemblyCopyright 83 | { 84 | get 85 | { 86 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false); 87 | if (attributes.Length == 0) 88 | { 89 | return ""; 90 | } 91 | return ((AssemblyCopyrightAttribute)attributes[0]).Copyright; 92 | } 93 | } 94 | 95 | public string AssemblyCompany 96 | { 97 | get 98 | { 99 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false); 100 | if (attributes.Length == 0) 101 | { 102 | return ""; 103 | } 104 | return ((AssemblyCompanyAttribute)attributes[0]).Company; 105 | } 106 | } 107 | #endregion 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /DotNetEditor/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /DotNetEditor/App.xaml: -------------------------------------------------------------------------------- 1 |  7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /DotNetEditor/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace DotNetEditor 10 | { 11 | /// 12 | /// Interaction logic for App.xaml 13 | /// 14 | public partial class App : Application 15 | { 16 | public const string AppName = "Dot Net Editor"; 17 | public static Bugsnag.Client client; 18 | 19 | private void OnStartup(object sender, StartupEventArgs e) 20 | { 21 | // Colored output only works if this is an console app. We do not want the console 22 | // anyway, so hide it. 23 | ConsoleUtil.HideConsoleWindow(); 24 | 25 | if (client == null) 26 | client = new Bugsnag.Client(Bugsnag.ConfigurationSection.Configuration.Settings); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /DotNetEditor/AppCommands.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Leung Wing-chung. All rights reserved. 2 | // Use of this source code is governed by a GPLv3 license that can be found in 3 | // the LICENSE file. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows.Input; 11 | 12 | namespace DotNetEditor 13 | { 14 | public static class AppCommands 15 | { 16 | public static readonly RoutedUICommand Run = new RoutedUICommand( 17 | "Run", "Run", typeof(MainWindow), 18 | new InputGestureCollection{new KeyGesture(Key.F5)}); 19 | 20 | public static readonly RoutedUICommand Stop = new RoutedUICommand( 21 | "Stop", "Stop", typeof(MainWindow), 22 | new InputGestureCollection { new KeyGesture(Key.F5, ModifierKeys.Shift) }); 23 | 24 | public static readonly RoutedUICommand About = new RoutedUICommand( 25 | "About", "About", typeof(MainWindow)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /DotNetEditor/AvalonUtils/AvalonCodeRunnerOutput.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Leung Wing-chung. All rights reserved. 2 | // Use of this source code is governed by a GPLv3 license that can be found in 3 | // the LICENSE file. 4 | 5 | using ICSharpCode.AvalonEdit.Document; 6 | using ICSharpCode.AvalonEdit.Rendering; 7 | using System; 8 | using System.Linq; 9 | using System.Runtime.CompilerServices; 10 | using System.Windows; 11 | using System.Windows.Media; 12 | 13 | [assembly: InternalsVisibleToAttribute("DotNetEditor.Tests")] 14 | 15 | namespace DotNetEditor 16 | { 17 | // This is the output area of a code runner, which is a customized AvalonEdit.TextEditor control 18 | // with the ability to store formatting information with text. 19 | class AvalonCodeRunnerOutput : 20 | ICSharpCode.AvalonEdit.TextEditor, CodeRunner.ICodeRunnerOutput 21 | { 22 | internal class TextFormat : TextSegment 23 | { 24 | public Color ForegroundColor = Brushes.LightGray.Color; 25 | public Color BackgroundColor = Brushes.Black.Color; 26 | public bool? IsBold; 27 | public bool? IsItalic; 28 | } 29 | 30 | private class RTBBackgroundRenderer : IBackgroundRenderer 31 | { 32 | private readonly TextSegmentCollection _formatData; 33 | 34 | public KnownLayer Layer { get; } = KnownLayer.Background; 35 | 36 | public RTBBackgroundRenderer(TextSegmentCollection formatData) 37 | { 38 | _formatData = formatData; 39 | } 40 | 41 | public void Draw(TextView textView, DrawingContext drawingContext) 42 | { 43 | if (textView == null) 44 | { 45 | throw new ArgumentNullException(nameof(textView)); 46 | } 47 | if (drawingContext == null) 48 | { 49 | throw new ArgumentNullException(nameof(drawingContext)); 50 | } 51 | 52 | if (_formatData == null || !textView.VisualLinesValid) 53 | { 54 | return; 55 | } 56 | 57 | var visualLines = textView.VisualLines; 58 | if (visualLines.Count == 0) 59 | { 60 | return; 61 | } 62 | 63 | int viewStart = visualLines.First().FirstDocumentLine.Offset; 64 | int viewEnd = visualLines.Last().LastDocumentLine.EndOffset; 65 | 66 | Size pixelSize = AvalonUtils.PixelSnappers.GetPixelSize(textView); 67 | 68 | foreach (var segment in 69 | _formatData.FindOverlappingSegments(viewStart, viewEnd - viewStart)) 70 | { 71 | Brush brush = new SolidColorBrush(segment.BackgroundColor); 72 | 73 | foreach (Rect r in 74 | BackgroundGeometryBuilder.GetRectsForSegment(textView, segment, false)) 75 | { 76 | // Skip rectangles with width less than two pixels. 77 | // These rectangles shouldn't be there. 78 | if (r.Width < 2) 79 | { 80 | continue; 81 | } 82 | drawingContext.DrawRectangle(brush, null, 83 | AvalonUtils.PixelSnappers.AlignRectToWholePixel(r, pixelSize)); 84 | } 85 | } 86 | } 87 | } 88 | 89 | class RTBColorizer : DocumentColorizingTransformer 90 | { 91 | private readonly TextSegmentCollection _formatData; 92 | 93 | public RTBColorizer(TextSegmentCollection formatData) 94 | { 95 | _formatData = formatData; 96 | } 97 | 98 | private static void FormatVisualLineElement(TextFormat seg, VisualLineElement element) 99 | { 100 | element.TextRunProperties.SetForegroundBrush( 101 | new SolidColorBrush(seg.ForegroundColor)); 102 | 103 | if (!seg.IsBold.HasValue && !seg.IsItalic.HasValue) 104 | { 105 | return; 106 | } 107 | 108 | Typeface tf = element.TextRunProperties.Typeface; 109 | 110 | FontStyle style = 111 | seg.IsItalic.HasValue 112 | ? (seg.IsItalic == true ? FontStyles.Italic : FontStyles.Normal) 113 | : tf.Style; 114 | 115 | FontWeight weight = 116 | seg.IsBold.HasValue 117 | ? (seg.IsBold == true ? FontWeights.Bold : FontWeights.Regular) 118 | : tf.Weight; 119 | 120 | element.TextRunProperties.SetTypeface( 121 | new Typeface(tf.FontFamily, style, weight, tf.Stretch)); 122 | } 123 | 124 | protected override void ColorizeLine(DocumentLine line) 125 | { 126 | TextSegment segment = new TextSegment(); 127 | segment.StartOffset = line.Offset; 128 | segment.EndOffset = line.EndOffset; 129 | 130 | var segments = _formatData.FindOverlappingSegments(segment); 131 | foreach (var seg in segments) 132 | { 133 | base.ChangeLinePart(Math.Max(seg.StartOffset, line.Offset), 134 | Math.Min(seg.EndOffset, line.EndOffset), 135 | (element) => FormatVisualLineElement(seg, element)); 136 | } 137 | } 138 | } 139 | 140 | private TextSegmentCollection formatInfo; 141 | 142 | public AvalonCodeRunnerOutput() 143 | { 144 | formatInfo = new TextSegmentCollection(Document); 145 | TextArea.TextView.LineTransformers.Add(new RTBColorizer(formatInfo)); 146 | TextArea.TextView.BackgroundRenderers.Add(new RTBBackgroundRenderer(formatInfo)); 147 | } 148 | 149 | private void SetStyle(int startOffset, int endOffset, 150 | Color foregroundColor, Color backgroundColor, bool? IsBold, bool? IsItalic) 151 | { 152 | TextFormat fmt = new TextFormat(); 153 | fmt.StartOffset = startOffset; 154 | fmt.EndOffset = endOffset; 155 | fmt.ForegroundColor = foregroundColor; 156 | fmt.BackgroundColor = backgroundColor; 157 | fmt.IsBold = IsBold; 158 | fmt.IsItalic = IsItalic; 159 | 160 | formatInfo.Add(fmt); 161 | } 162 | 163 | #region ICodeRunnerOutput 164 | public void AppendTextWithStyle(string text, Color foregroundColor, Color backgroundColor, 165 | bool? isBold, bool? isItalic) 166 | { 167 | int start = Text.Length; 168 | AppendText(text); 169 | SetStyle(start, Text.Length, foregroundColor, backgroundColor, isBold, isItalic); 170 | } 171 | 172 | // void AppendText(string text); (already implemented by AvalonEdit.TextEditor) 173 | 174 | public void ClearOutput() 175 | { 176 | Clear(); 177 | formatInfo.Clear(); 178 | } 179 | 180 | public bool IsEmpty() 181 | { 182 | return !(Document?.TextLength > 0); 183 | } 184 | #endregion 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /DotNetEditor/AvalonUtils/PixelSnapper.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Leung Wing-chung. All rights reserved. 2 | // Use of this source code is governed by a GPLv3 license that can be found in 3 | // the LICENSE file. 4 | 5 | using System.Windows; 6 | using System.Windows.Media; 7 | 8 | using PixelSnapHelpers = ICSharpCode.AvalonEdit.Utils.PixelSnapHelpers; 9 | 10 | namespace DotNetEditor.AvalonUtils { 11 | 12 | public static class PixelSnappers 13 | { 14 | // Wraps around ICSharpCode.AvalonEdit.Utils.PixelSnapHelpers 15 | public static Size GetPixelSize(Visual visual) 16 | { 17 | return PixelSnapHelpers.GetPixelSize(visual); 18 | } 19 | 20 | // Aligns the borders of rect to whole pixels. 21 | public static Rect AlignRectToWholePixel(Rect rect, Size pixelSize) 22 | { 23 | return new Rect(PixelSnapHelpers.Round(rect.TopLeft, pixelSize), 24 | PixelSnapHelpers.Round(rect.BottomRight, pixelSize)); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /DotNetEditor/CodeRunner/CSCodeRunner.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Leung Wing-chung. All rights reserved. 2 | // Use of this source code is governed by a GPLv3 license that can be found in 3 | // the LICENSE file. 4 | 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using System.Runtime.CompilerServices; 11 | 12 | [assembly: InternalsVisibleToAttribute("DotNetEditor.Tests")] 13 | 14 | namespace DotNetEditor.CodeRunner 15 | { 16 | class CSCodeRunner : CodeRunnerBase 17 | { 18 | public CSCodeRunner(string code, string inputData, ICodeRunnerOutput outputArea) 19 | : base(code, inputData, outputArea) 20 | { 21 | } 22 | 23 | protected override Compilation GetCompilation() 24 | { 25 | var parseOptions = new CSharpParseOptions( 26 | preprocessorSymbols: new[] { "DEBUG", "TRACE" }); 27 | 28 | SyntaxTree tree = GetSyntaxTree(parseOptions); 29 | 30 | SortedSet uniqueImports = new SortedSet(AssemblyImports) 31 | { 32 | "mscorlib.dll", 33 | "Microsoft.CSharp.dll" 34 | }; 35 | 36 | List references = new List(); 37 | try 38 | { 39 | string dllPath = GetReferenceAssembliesPath(); 40 | foreach (string import in uniqueImports) 41 | { 42 | references.Add(MetadataReference.CreateFromFile(System.IO.Path.Combine( 43 | dllPath, import))); 44 | } 45 | } 46 | catch (Exception e) 47 | { 48 | throw new CodeRunnerException(e.Message, e); 49 | } 50 | 51 | var options = new CSharpCompilationOptions(OutputKind.ConsoleApplication); 52 | 53 | return CSharpCompilation.Create( 54 | "DotNetEditor_Script", new[] { tree }, references, options); 55 | } 56 | 57 | private SyntaxTree GetSyntaxTree(CSharpParseOptions options) 58 | { 59 | string[] templates = 60 | { 61 | // the program put inside a class 62 | "{1} class Program {{ {0} }}", 63 | // the program put inside Main function 64 | "{1} class Program {{ static void Main(string[] args) {{ {0} }} }}", 65 | // the raw program 66 | "{0}", 67 | }; 68 | 69 | SyntaxTree tree = null; 70 | int errorCount = int.MaxValue; 71 | 72 | // Select the template with the least number of parsing errors. For ties, select the 73 | // first template that has the least number of errors. 74 | foreach (string template in templates) 75 | { 76 | string parsedCode = String.Format(template, Code, GetUsings(NSImports)); 77 | SyntaxTree newTree = CSharpSyntaxTree.ParseText(parsedCode, options); 78 | int newErrorCount = newTree.GetDiagnostics().Count(); 79 | if (newErrorCount < errorCount) 80 | { 81 | errorCount = newErrorCount; 82 | tree = newTree; 83 | if (errorCount == 0) 84 | { 85 | break; 86 | } 87 | } 88 | } 89 | 90 | return tree; 91 | } 92 | 93 | private string GetUsings(string[] usings) 94 | { 95 | System.Text.StringBuilder str = new System.Text.StringBuilder(); 96 | foreach (string s in usings) 97 | { 98 | str.Append("using "); 99 | str.Append(s); 100 | str.Append("; "); 101 | } 102 | return str.ToString(); 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /DotNetEditor/CodeRunner/CodeRunnerException.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Leung Wing-chung. All rights reserved. 2 | // Use of this source code is governed by a GPLv3 license that can be found in 3 | // the LICENSE file. 4 | 5 | using System; 6 | 7 | namespace DotNetEditor.CodeRunner 8 | { 9 | [Serializable] 10 | class CodeRunnerException : Exception 11 | { 12 | public CodeRunnerException() { } 13 | public CodeRunnerException(string message) : base(message) { } 14 | public CodeRunnerException(string message, Exception e) : base(message, e) { } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /DotNetEditor/CodeRunner/ICodeRunnerOutput.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Leung Wing-chung. All rights reserved. 2 | // Use of this source code is governed by a GPLv3 license that can be found in 3 | // the LICENSE file. 4 | 5 | using System.Runtime.CompilerServices; 6 | using System.Windows.Media; 7 | 8 | [assembly: InternalsVisibleToAttribute("DotNetEditor.Tests")] 9 | 10 | namespace DotNetEditor.CodeRunner 11 | { 12 | interface ICodeRunnerOutput 13 | { 14 | // Append text to the output with the specified style. 15 | void AppendTextWithStyle(string text, Color foregroundColor, Color backgroundColor, 16 | bool? isBold, bool? isItalic); 17 | 18 | // Append text to the output with the default style. 19 | void AppendText(string text); 20 | 21 | // Remove all text and style from the output. 22 | void ClearOutput(); 23 | 24 | // Return if the output is empty. 25 | bool IsEmpty(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /DotNetEditor/CodeRunner/VBCodeRunner.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Leung Wing-chung. All rights reserved. 2 | // Use of this source code is governed by a GPLv3 license that can be found in 3 | // the LICENSE file. 4 | 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.VisualBasic; 7 | using Microsoft.CodeAnalysis.VisualBasic.Syntax; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Linq; 11 | using System.Runtime.CompilerServices; 12 | 13 | [assembly: InternalsVisibleToAttribute("DotNetEditor.Tests")] 14 | 15 | namespace DotNetEditor.CodeRunner 16 | { 17 | class VBCodeRunner : CodeRunnerBase 18 | { 19 | public VBCodeRunner(string code, string inputData, ICodeRunnerOutput outputArea) 20 | : base(code, inputData, outputArea) 21 | { 22 | } 23 | 24 | protected override Compilation GetCompilation() 25 | { 26 | var preprocessorSymbols = 27 | new Dictionary { { "DEBUG", true}, { "TRACE", true} }; 28 | 29 | var parseOptions = new VisualBasicParseOptions( 30 | preprocessorSymbols: preprocessorSymbols); 31 | 32 | SyntaxTree tree = GetSyntaxTree(parseOptions); 33 | 34 | SortedSet uniqueImports = new SortedSet(AssemblyImports); 35 | uniqueImports.Add("mscorlib.dll"); 36 | uniqueImports.Add("Microsoft.VisualBasic.dll"); 37 | 38 | List references = new List(); 39 | try 40 | { 41 | string dllPath = GetReferenceAssembliesPath(); 42 | foreach (string import in uniqueImports) 43 | { 44 | references.Add(MetadataReference.CreateFromFile(System.IO.Path.Combine( 45 | dllPath, import))); 46 | } 47 | } 48 | catch (Exception e) 49 | { 50 | throw new CodeRunnerException(e.Message, e); 51 | } 52 | 53 | var compilationOptions = new VisualBasicCompilationOptions( 54 | OutputKind.ConsoleApplication, 55 | globalImports: GlobalImport.Parse(NSImports), 56 | parseOptions: parseOptions); 57 | 58 | return VisualBasicCompilation.Create( 59 | "DotNetEditor_Script", new[] { tree }, references, compilationOptions); 60 | } 61 | 62 | private SyntaxTree GetSyntaxTree(VisualBasicParseOptions options) 63 | { 64 | SyntaxTree tree = VisualBasicSyntaxTree.ParseText(Code, options); 65 | 66 | if (IsInsideOfSubMain(tree)) 67 | { 68 | string parsedCode = String.Format( 69 | "Module Module1\nSub Main\n{0}\nEnd Sub\nEnd Module", Code); 70 | return VisualBasicSyntaxTree.ParseText(parsedCode, options); 71 | } 72 | else if (IsInsideOfClass(tree)) 73 | { 74 | string parsedCode = String.Format( 75 | "Module Module1\n{0}\nEnd Module", Code); 76 | return VisualBasicSyntaxTree.ParseText(parsedCode, options); 77 | } 78 | else 79 | { 80 | return tree; 81 | } 82 | } 83 | 84 | private bool IsInsideOfSubMain(SyntaxTree tree) 85 | { 86 | return tree.GetRoot().ChildNodes().All( 87 | (node) => node is StatementSyntax && 88 | !(node is ClassBlockSyntax) && 89 | !(node is InterfaceBlockSyntax) && 90 | !(node is MethodBlockSyntax) && 91 | !(node is ModuleBlockSyntax) && 92 | !(node is NamespaceBlockSyntax) 93 | ); 94 | } 95 | 96 | private bool IsInsideOfClass(SyntaxTree tree) 97 | { 98 | return tree.GetRoot().ChildNodes().All( 99 | (node) => node is StatementSyntax && 100 | !(node is ClassBlockSyntax) && 101 | !(node is InterfaceBlockSyntax) && 102 | !(node is ModuleBlockSyntax) && 103 | !(node is NamespaceBlockSyntax) 104 | ); 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /DotNetEditor/ConsoleColorScheme.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Leung Wing-chung. All rights reserved. 2 | // Use of this source code is governed by a GPLv3 license that can be found in 3 | // the LICENSE file. 4 | 5 | using System; 6 | using System.Runtime.CompilerServices; 7 | using System.Windows.Media; 8 | 9 | [assembly: InternalsVisibleToAttribute("DotNetEditor.Tests")] 10 | 11 | namespace DotNetEditor 12 | { 13 | class ConsoleColorScheme 14 | { 15 | private static readonly Color[] DefaultColors = { 16 | Brushes.Black.Color, 17 | Brushes.Navy.Color, 18 | Brushes.Green.Color, 19 | Brushes.Teal.Color, 20 | Brushes.Maroon.Color, 21 | Brushes.Purple.Color, 22 | Brushes.Olive.Color, 23 | Brushes.Silver.Color, 24 | Brushes.Gray.Color, 25 | Brushes.Blue.Color, 26 | Brushes.Lime.Color, 27 | Brushes.Cyan.Color, 28 | Brushes.Red.Color, 29 | Brushes.Magenta.Color, 30 | Brushes.Yellow.Color, 31 | Brushes.White.Color 32 | }; 33 | 34 | [Serializable] 35 | public class ColorCountException : Exception 36 | { 37 | public ColorCountException() 38 | : base("The color scheme must have exactly 16 colors.") {} 39 | 40 | public ColorCountException(string message) 41 | : base(message) {} 42 | 43 | public ColorCountException(string message, Exception inner) 44 | : base(message, inner) {} 45 | } 46 | 47 | private Color[] _colors; 48 | public Color[] Colors { 49 | get { return _colors; } 50 | set 51 | { 52 | if (value.Length != 16) 53 | { 54 | throw new ColorCountException(); 55 | } 56 | 57 | _colors = value; 58 | } 59 | } 60 | 61 | public ConsoleColorScheme(Color[] colors) 62 | { 63 | Colors = colors; 64 | } 65 | 66 | public static readonly ConsoleColorScheme DefaultColorScheme = 67 | new ConsoleColorScheme(DefaultColors); 68 | 69 | public Color ConvertColor(ConsoleColor color) 70 | { 71 | return Colors[Convert.ToInt32(color)]; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /DotNetEditor/ConsoleUtil.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Leung Wing-chung. All rights reserved. 2 | // Use of this source code is governed by a GPLv3 license that can be found in 3 | // the LICENSE file. 4 | 5 | using System; 6 | using System.Runtime.InteropServices; 7 | 8 | namespace DotNetEditor 9 | { 10 | static class ConsoleUtil 11 | { 12 | [DllImport("Kernel32.dll", EntryPoint = "AllocConsole", ExactSpelling = false, 13 | CharSet = CharSet.Unicode, SetLastError = true)] 14 | private static extern bool AllocConsole(); 15 | 16 | [DllImport("Kernel32.dll", EntryPoint = "GetConsoleWindow", ExactSpelling = false, 17 | CharSet = CharSet.Unicode)] 18 | private static extern IntPtr GetConsoleWindow(); 19 | 20 | [DllImport("user32.dll", EntryPoint = "ShowWindow", ExactSpelling = false, 21 | CharSet = CharSet.Unicode)] 22 | private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); 23 | 24 | public static void HideConsoleWindow() 25 | { 26 | IntPtr handle = GetConsoleWindow(); 27 | if (handle == IntPtr.Zero) 28 | { 29 | AllocConsole(); 30 | handle = GetConsoleWindow(); 31 | } 32 | ShowWindow(handle, 0); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /DotNetEditor/Converters.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Leung Wing-chung. All rights reserved. 2 | // Use of this source code is governed by a GPLv3 license that can be found in 3 | // the LICENSE file. 4 | 5 | using System; 6 | using System.Globalization; 7 | using System.Windows.Data; 8 | using System.Windows.Input; 9 | 10 | namespace DotNetEditor.Converters 11 | { 12 | class InputGestureConverter : IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | if (targetType != typeof(string)) 17 | { 18 | throw new ArgumentException("Can only convert to string."); 19 | } 20 | 21 | string s = ((KeyGesture) value).DisplayString; 22 | if (String.IsNullOrEmpty(s)) 23 | { 24 | s = new KeyGestureConverter().ConvertToString(value); 25 | } 26 | return s; 27 | } 28 | 29 | public object ConvertBack(object value, Type targetType, object parameter, 30 | CultureInfo culture) 31 | { 32 | throw new NotSupportedException("Conversion is one-way."); 33 | } 34 | } 35 | 36 | class CommandConverter : IValueConverter 37 | { 38 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 39 | { 40 | RoutedCommand cmd = (RoutedCommand)value; 41 | RoutedUICommand uiCmd = cmd as RoutedUICommand; 42 | string s = uiCmd != null ? uiCmd.Text : cmd.Name; 43 | if (cmd.InputGestures.Count > 0) 44 | { 45 | s += " (" + new InputGestureConverter().Convert(cmd.InputGestures[0], 46 | typeof(string), null, System.Globalization.CultureInfo.CurrentUICulture) + ")"; 47 | } 48 | return s; 49 | } 50 | 51 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 52 | { 53 | throw new NotSupportedException("Conversion is one-way."); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /DotNetEditor/DotNetEditor.GeneratedMSBuildEditorConfig.editorconfig: -------------------------------------------------------------------------------- 1 | is_global = true 2 | build_property.TargetFramework = 3 | build_property.TargetPlatformMinVersion = 4 | build_property.UsingMicrosoftNETSdkWeb = 5 | build_property.ProjectTypeGuids = {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 6 | build_property.PublishSingleFile = 7 | build_property.IncludeAllContentForSelfExtract = 8 | build_property._SupportedPlatformList = 9 | -------------------------------------------------------------------------------- /DotNetEditor/DotNetEditor.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lwchkg/DotNetEditor/bd22359523a93617635950c24708357b925543d1/DotNetEditor/DotNetEditor.ico -------------------------------------------------------------------------------- /DotNetEditor/DumpReader.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Leung Wing-chung. All rights reserved. 2 | // Use of this source code is governed by a GPLv3 license that can be found in 3 | // the LICENSE file. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | using System.IO; 12 | 13 | namespace DotNetEditor 14 | { 15 | // DumpReader is a TextReader that dumps input into the output 16 | 17 | // Initialization: New DumpReader(reader, writer) 18 | // reader: the TextReader to read from 19 | // writer: the TextWriter that the read operations dump to 20 | class DumpReader : TextReader 21 | { 22 | const ConsoleColor DumpForegroundColor = System.ConsoleColor.Black; 23 | const ConsoleColor DumpBackgroundColor = System.ConsoleColor.Gray; 24 | 25 | TextReader _reader; 26 | TextWriter _writer; 27 | 28 | public DumpReader(TextReader reader, TextWriter writer) 29 | { 30 | _reader = reader; 31 | _writer = writer; 32 | } 33 | 34 | public override int Peek() 35 | { 36 | return _reader.Peek(); 37 | } 38 | 39 | public override int Read() 40 | { 41 | ConsoleColor fg = Console.ForegroundColor; 42 | ConsoleColor bg = Console.BackgroundColor; 43 | 44 | Console.ForegroundColor = DumpForegroundColor; 45 | Console.BackgroundColor = DumpBackgroundColor; 46 | 47 | int c = _reader.Read(); 48 | if (c >= 0) 49 | _writer.Write(Convert.ToChar(c)); 50 | 51 | Console.ForegroundColor = fg; 52 | Console.BackgroundColor = bg; 53 | 54 | return c; 55 | } 56 | 57 | public override string ReadLine() 58 | { 59 | ConsoleColor fg = Console.ForegroundColor; 60 | ConsoleColor bg = Console.BackgroundColor; 61 | 62 | Console.ForegroundColor = DumpForegroundColor; 63 | Console.BackgroundColor = DumpBackgroundColor; 64 | 65 | string s = _reader.ReadLine(); 66 | _writer.WriteLine(s); 67 | 68 | Console.ForegroundColor = fg; 69 | Console.BackgroundColor = bg; 70 | 71 | return s; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /DotNetEditor/FileUtils/FileHandler.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Leung Wing-chung. All rights reserved. 2 | // Use of this source code is governed by a GPLv3 license that can be found in 3 | // the LICENSE file. 4 | 5 | using System; 6 | using System.IO; 7 | 8 | namespace DotNetEditor.FileUtils 9 | { 10 | // Handles file loading and saving actions. A load and a save action is required to instantiate 11 | // the class. If file operation fails, the action should throw an System.IO.IOException for this 12 | // class to catch. 13 | class FileHandler 14 | { 15 | public delegate void FileOperation(Stream stream); 16 | 17 | System.Windows.Window _window; 18 | FileOperation _load; 19 | FileOperation _save; 20 | 21 | public struct FileOperationResult 22 | { 23 | public bool Success; 24 | public string Filename; 25 | 26 | public FileOperationResult(bool success, string filename) 27 | { 28 | this.Success = success; 29 | this.Filename = filename; 30 | } 31 | } 32 | 33 | // Return for cancelled or failed file operations. 34 | private static readonly FileOperationResult _fileOperationNotSucceed = 35 | new FileOperationResult(false, ""); 36 | 37 | public FileHandler(System.Windows.Window window, 38 | FileOperation loadAction, FileOperation saveAction) 39 | { 40 | _window = window; 41 | _load = loadAction; 42 | _save = saveAction; 43 | } 44 | 45 | public FileOperationResult Load(string filename) 46 | { 47 | try 48 | { 49 | _load(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read)); 50 | } 51 | catch (IOException) 52 | { 53 | // TODO: display dialog for failure. 54 | return _fileOperationNotSucceed; 55 | } 56 | catch (UnauthorizedAccessException) 57 | { 58 | return _fileOperationNotSucceed; 59 | } 60 | return new FileOperationResult(true, filename); 61 | } 62 | 63 | public FileOperationResult LoadWithDialog(string filter) 64 | { 65 | var dialog = new Microsoft.Win32.OpenFileDialog(); 66 | dialog.Filter = filter; 67 | 68 | if (dialog.ShowDialog(_window) == true) 69 | { 70 | return Load(dialog.FileName); 71 | } 72 | else 73 | { 74 | return _fileOperationNotSucceed; 75 | } 76 | } 77 | 78 | public FileOperationResult Save(string filename) 79 | { 80 | try 81 | { 82 | _save(new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.Write)); 83 | } 84 | catch (System.IO.IOException) 85 | { 86 | // TODO: display dialog for failure. 87 | return _fileOperationNotSucceed; 88 | } 89 | return new FileOperationResult(true, filename); 90 | } 91 | 92 | 93 | public FileOperationResult SaveAs(string filter) 94 | { 95 | var dialog = new Microsoft.Win32.SaveFileDialog(); 96 | dialog.Filter = filter; 97 | 98 | if (dialog.ShowDialog(_window) == true) 99 | { 100 | return Save(dialog.FileName); 101 | } 102 | else 103 | { 104 | return _fileOperationNotSucceed; 105 | } 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /DotNetEditor/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /DotNetEditor/GrayscaleEffect/GrayscaleEffect.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Windows.Media; 4 | using System.Windows.Media.Effects; 5 | using System.Reflection; 6 | 7 | namespace GrayscaleEffect 8 | { 9 | 10 | public class GrayscaleEffect : ShaderEffect 11 | { 12 | private static PixelShader _pixelShader = 13 | new PixelShader() { UriSource = MakePackUri("GrayscaleEffect/GrayscaleEffect.fx.ps") }; 14 | 15 | public GrayscaleEffect() 16 | { 17 | PixelShader = _pixelShader; 18 | UpdateShaderValue(InputProperty); 19 | } 20 | 21 | // MakePackUri is a utility method for computing a pack uri 22 | // for the given resource. 23 | public static Uri MakePackUri(string relativeFile) 24 | { 25 | Assembly a = typeof(GrayscaleEffect).Assembly; 26 | 27 | // Extract the short name. 28 | string assemblyShortName = a.ToString().Split(',')[0]; 29 | 30 | string uriString = "pack://application:,,,/" + 31 | assemblyShortName + 32 | ";component/" + 33 | relativeFile; 34 | 35 | return new Uri(uriString); 36 | } 37 | 38 | /////////////////////////////////////////////////////////////////////// 39 | #region Input dependency property 40 | 41 | public Brush Input 42 | { 43 | get { return (Brush)GetValue(InputProperty); } 44 | set { SetValue(InputProperty, value); } 45 | } 46 | 47 | public static readonly DependencyProperty InputProperty = 48 | ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(GrayscaleEffect), 0); 49 | 50 | #endregion 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /DotNetEditor/GrayscaleEffect/GrayscaleEffect.fx.ps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lwchkg/DotNetEditor/bd22359523a93617635950c24708357b925543d1/DotNetEditor/GrayscaleEffect/GrayscaleEffect.fx.ps -------------------------------------------------------------------------------- /DotNetEditor/GrayscaleEffect/GrayscaleEffect.hlsl: -------------------------------------------------------------------------------- 1 | // Grayscale shader 2 | 3 | sampler2D implicitInput : register(s0); 4 | 5 | float4 main(float2 uv : TEXCOORD) : COLOR 6 | { 7 | float4 color = tex2D(implicitInput, uv); 8 | float gray = color.r * 0.3 + color.g * 0.59 + color.b * 0.11; 9 | 10 | float4 result; 11 | result.r = gray; 12 | result.g = gray; 13 | result.b = gray; 14 | result.a = color.a; 15 | 16 | return result; 17 | } 18 | -------------------------------------------------------------------------------- /DotNetEditor/Icons.xaml: -------------------------------------------------------------------------------- 1 |  3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /DotNetEditor/Images/about-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lwchkg/DotNetEditor/bd22359523a93617635950c24708357b925543d1/DotNetEditor/Images/about-30.png -------------------------------------------------------------------------------- /DotNetEditor/Images/cs-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lwchkg/DotNetEditor/bd22359523a93617635950c24708357b925543d1/DotNetEditor/Images/cs-30.png -------------------------------------------------------------------------------- /DotNetEditor/Images/down_left-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lwchkg/DotNetEditor/bd22359523a93617635950c24708357b925543d1/DotNetEditor/Images/down_left-30.png -------------------------------------------------------------------------------- /DotNetEditor/Images/open_folder-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lwchkg/DotNetEditor/bd22359523a93617635950c24708357b925543d1/DotNetEditor/Images/open_folder-30.png -------------------------------------------------------------------------------- /DotNetEditor/Images/save-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lwchkg/DotNetEditor/bd22359523a93617635950c24708357b925543d1/DotNetEditor/Images/save-30.png -------------------------------------------------------------------------------- /DotNetEditor/Images/save_as-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lwchkg/DotNetEditor/bd22359523a93617635950c24708357b925543d1/DotNetEditor/Images/save_as-30.png -------------------------------------------------------------------------------- /DotNetEditor/Images/vb-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lwchkg/DotNetEditor/bd22359523a93617635950c24708357b925543d1/DotNetEditor/Images/vb-30.png -------------------------------------------------------------------------------- /DotNetEditor/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  12 | 13 | 14 | 15 | 16 | 17 | 18 | 25 | 26 | 37 | 38 | 39 | 40 | 41 | 45 | 49 | 53 | 57 | 61 | 65 | 66 | 67 | 68 | 70 | 71 | 77 | 86 | 97 |