diff options
Diffstat (limited to 'Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Project.cs')
| -rw-r--r-- | Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Project.cs | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Project.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Project.cs new file mode 100644 index 000000000..ddf61e124 --- /dev/null +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Project.cs @@ -0,0 +1,211 @@ +using Microsoft.CodeAnalysis.CSharp.Scripting; +using Microsoft.CodeAnalysis.Scripting; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using Tango.Core; +using Tango.Core.IO; +using Tango.Scripting.Core; +using System.IO; + +namespace Tango.Scripting.Basic +{ + public class Project : ExtendedObject + { + public String Name { get; set; } + + public ApartmentState ApartmentState { get; set; } + + public ObservableCollection<ReferenceAssembly> ReferenceAssemblies { get; set; } + + [JsonIgnore] + public ObservableCollection<Assembly> ReferenceAssembliesLoaded { get; set; } + + public ObservableCollection<Script> Scripts { get; set; } + + public ObservableCollection<IScriptSource> AdditionalScripts + { + get + { + return Scripts.Where(x => !x.IsEntryPoint).Cast<IScriptSource>().ToObservableCollection(); + } + } + + public Project() + { + ApartmentState = ApartmentState.MTA; + + ReferenceAssemblies = new ObservableCollection<ReferenceAssembly>(); + ReferenceAssemblies.CollectionChanged += ReferenceAssemblies_CollectionChanged; + + ReferenceAssembliesLoaded = new ObservableCollection<Assembly>(); + Scripts = new ObservableCollection<Script>(); + Scripts.CollectionChanged += (x, e) => { RaisePropertyChanged(nameof(AdditionalScripts)); }; + } + + private void ReferenceAssemblies_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + { + LoadReferenceAssemblies(); + } + + private void LoadReferenceAssemblies() + { + ReferenceAssembliesLoaded.Clear(); + + foreach (var type in ReferenceAssemblies) + { + ReferenceAssembliesLoaded.Add(type.FromType.Assembly); + } + } + + public static Project New(String name, String code) + { + Project p = new Project(); + + p.Name = name; + + p.ReferenceAssemblies.Add(new ReferenceAssembly() { FromType = typeof(String) }); + p.ReferenceAssemblies.Add(new ReferenceAssembly() { FromType = typeof(Enumerable) }); + p.ReferenceAssemblies.Add(new ReferenceAssembly() { FromType = typeof(Form) }); + p.ReferenceAssemblies.Add(new ReferenceAssembly() { FromType = typeof(Project) }); + + p.Scripts.Add(new Script() + { + Name = "main.csx", + IsEntryPoint = true, + Code = code, + }); + + return p; + } + + public Task<CompilationResult> Compile() + { + return Task.Factory.StartNew<CompilationResult>(() => + { + var result = new CompilationResult(); + var tempFolder = TemporaryManager.CreateFolder(Name); + result.TemporaryProjectPath = tempFolder; + + String mainScriptCode = String.Empty; + + foreach (var script in Scripts) + { + String code = script.Code; + String codeFile = Path.Combine(tempFolder, script.Name); + + String loadingString = String.Empty; + + foreach (var file in Scripts.Where(x => !x.IsEntryPoint && script != x).Select(x => Path.Combine(tempFolder, x.Name))) + { + loadingString = $"#load \"{file}\"\n"; + } + + code = loadingString + code; + + if (!script.IsEntryPoint) + { + + + //foreach (var match in Regex.Matches(code, "#load \".+\"").OfType<Match>()) + //{ + // String line = match.ToString(); + // var pathMatch = Regex.Match(line, "(?<=\")(.*?)(?=\")"); + // if (pathMatch.Success) + // { + // String path = pathMatch.ToString(); + + // if (!System.IO.Path.IsPathRooted(path)) + // { + // StringBuilder builder = new StringBuilder(code); + // builder.Insert(match.Index + pathMatch.Index, System.IO.Path.GetFullPath(tempFolder + "\\")); + // code = builder.ToString(); + // } + // } + //} + + + + File.WriteAllText(codeFile, code); + } + else + { + code += Environment.NewLine + Environment.NewLine + "return new Program().OnExecute(GlobalContext);"; + mainScriptCode = code; + } + } + + var scriptOptions = ScriptOptions.Default.WithReferences(ReferenceAssembliesLoaded); + + var s = CSharpScript.Create<object>(mainScriptCode, scriptOptions, typeof(GlobalObject)); + result.Script = s; + + var compileResults = s.Compile(); + + foreach (var error in compileResults.Where(x => x.Severity == Microsoft.CodeAnalysis.DiagnosticSeverity.Error || x.Severity == Microsoft.CodeAnalysis.DiagnosticSeverity.Warning)) + { + CompilationError cError = new CompilationError(); + cError.File = System.IO.Path.GetFileName(error.Location.SourceTree.FilePath); + cError.Message = error.GetMessage(); + cError.Severity = error.Severity; + var line = error.Location.GetMappedLineSpan(); + cError.Line = line.StartLinePosition.Line + 1; + cError.Column = line.StartLinePosition.Character + 1; + cError.Length = line.EndLinePosition.Character - line.StartLinePosition.Character; + result.Errors.Add(cError); + } + + return result; + }); + } + + public async Task<ProjectSession> Run(IContext context) + { + var result = await Compile(); + + if (result.Errors.Count > 0) + { + throw new InvalidOperationException("There were compilation errors."); + } + + Thread scriptThread = null; + ProjectSession session = null; + + session = new ProjectSession(this, () => + { + scriptThread.Abort(); + }); + + scriptThread = new Thread(() => + { + try + { + var runResult = result.Script.RunAsync(globals: new GlobalObject() { GlobalContext = context }).Result; + session.Completed(runResult.ReturnValue); + } + catch (ThreadAbortException) + { + + } + catch (Exception ex) + { + session.Failed(ex.InnerException); + } + }); + + scriptThread.SetApartmentState(ApartmentState); + scriptThread.IsBackground = true; + scriptThread.Start(); + + return session; + } + } +} |
