source: stable/HeuristicLab.Scripting/3.3/Script.cs @ 17158

Last change on this file since 17158 was 17158, checked in by gkronber, 2 months ago

#2435: merged r17037 and r17110 from trunk to stable

File size: 4.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.CodeDom;
24using System.CodeDom.Compiler;
25using System.Collections.Generic;
26using System.Drawing;
27using System.IO;
28using System.Linq;
29using System.Reflection;
30using System.Text;
31using System.Text.RegularExpressions;
32using HEAL.Attic;
33using HeuristicLab.Common;
34using HeuristicLab.Common.Resources;
35using HeuristicLab.Core;
36using Microsoft.CSharp;
37
38namespace HeuristicLab.Scripting {
39  [StorableType("0FA4F218-E1F5-4C09-9C2F-12B32D4EC373")]
40  public abstract class Script : NamedItem, IProgrammableItem {
41    #region Fields & Properties
42    public static new Image StaticItemImage {
43      get { return VSImageLibrary.Script; }
44    }
45
46    [Storable]
47    private string code;
48    public string Code {
49      get { return code; }
50      set {
51        if (value == code) return;
52        code = value;
53        OnCodeChanged();
54      }
55    }
56
57    private CompilerErrorCollection compileErrors;
58    public CompilerErrorCollection CompileErrors {
59      get { return compileErrors; }
60      private set {
61        compileErrors = value;
62        OnCompileErrorsChanged();
63      }
64    }
65    #endregion
66
67    #region Construction & Initialization
68    [StorableConstructor]
69    protected Script(StorableConstructorFlag _) : base(_) { }
70    protected Script(Script original, Cloner cloner)
71      : base(original, cloner) {
72      code = original.code;
73      if (original.compileErrors != null)
74        compileErrors = new CompilerErrorCollection(original.compileErrors);
75    }
76    protected Script()
77      : base("Script", "An empty script.") {
78    }
79    protected Script(string code)
80      : this() {
81      this.code = code;
82    }
83    #endregion
84
85    #region Compilation
86    protected virtual CompilerResults DoCompile() {
87      var parameters = new CompilerParameters {
88        GenerateExecutable = false,
89        GenerateInMemory = true,
90        IncludeDebugInformation = true,
91        WarningLevel = 4
92      };
93
94      parameters.ReferencedAssemblies.AddRange(
95        GetAssemblies()
96        .Select(a => a.Location)
97        .ToArray());
98
99      var codeProvider = new CSharpCodeProvider(
100        new Dictionary<string, string> {
101          { "CompilerVersion", "v4.0"} // support C# 4.0 syntax
102        });
103
104      return codeProvider.CompileAssemblyFromSource(parameters, code);
105    }
106
107    public virtual Assembly Compile() {
108      var results = DoCompile();
109      CompileErrors = results.Errors;
110      if (results.Errors.HasErrors) {
111        var sb = new StringBuilder();
112        foreach (CompilerError error in results.Errors) {
113          sb.Append(error.Line).Append(':')
114            .Append(error.Column).Append(": ")
115            .AppendLine(error.ErrorText);
116        }
117        throw new CompilationException(string.Format("Compilation of \"{0}\" failed:{1}{2}",
118          Name, Environment.NewLine, sb.ToString()));
119      } else {
120        return results.CompiledAssembly;
121      }
122    }
123
124    public virtual IEnumerable<Assembly> GetAssemblies() {
125      var assemblies = AppDomain.CurrentDomain.GetAssemblies()
126        .Where(a => !a.IsDynamic && File.Exists(a.Location))
127        .GroupBy(x => Regex.Replace(Path.GetFileName(x.Location), @"-[\d.]+\.dll$", ""))
128        .Select(x => x.OrderByDescending(y => y.GetName().Version).First())
129        .ToList();
130      assemblies.Add(typeof(Microsoft.CSharp.RuntimeBinder.Binder).Assembly); // for dlr functionality
131      return assemblies;
132    }
133
134    protected virtual CodeCompileUnit CreateCompilationUnit() {
135      var unit = new CodeSnippetCompileUnit(code);
136      return unit;
137    }
138    #endregion
139
140    public event EventHandler CodeChanged;
141    protected virtual void OnCodeChanged() {
142      var handler = CodeChanged;
143      if (handler != null) handler(this, EventArgs.Empty);
144    }
145
146    public event EventHandler CompileErrorsChanged;
147    protected virtual void OnCompileErrorsChanged() {
148      var handler = CompileErrorsChanged;
149      if (handler != null) handler(this, EventArgs.Empty);
150    }
151  }
152}
Note: See TracBrowser for help on using the repository browser.