Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Scripting/3.3/Script.cs @ 10731

Last change on this file since 10731 was 10731, checked in by abeham, 10 years ago

#2136:

  • Split Script into Script and CSharpScript
  • Split ScriptView into ScriptView and CSharpScriptView
File size: 5.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2014 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 HeuristicLab.Common;
32using HeuristicLab.Common.Resources;
33using HeuristicLab.Core;
34using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
35using Microsoft.CSharp;
36
37namespace HeuristicLab.Scripting {
38  [StorableClass]
39  public class Script : NamedItem {
40    protected virtual string CodeTemplate {
41      get { return string.Empty; }
42    }
43
44    #region Fields & Properties
45    public static new Image StaticItemImage {
46      get { return VSImageLibrary.Script; }
47    }
48
49    [Storable]
50    private string code;
51    public virtual string Code {
52      get { return code; }
53      set {
54        if (value == code) return;
55        code = value;
56        OnCodeChanged();
57      }
58    }
59
60    private string compilationUnitCode;
61    public virtual string CompilationUnitCode {
62      get { return compilationUnitCode; }
63    }
64
65    private CompilerErrorCollection compileErrors;
66    public virtual CompilerErrorCollection CompileErrors {
67      get { return compileErrors; }
68      private set {
69        compileErrors = value;
70        OnCompileErrorsChanged();
71      }
72    }
73    #endregion
74
75    #region Construction & Initialization
76    [StorableConstructor]
77    protected Script(bool deserializing) : base(deserializing) { }
78    protected Script(Script original, Cloner cloner)
79      : base(original, cloner) {
80      code = original.code;
81      compilationUnitCode = original.compilationUnitCode;
82      if (original.compileErrors != null)
83        compileErrors = new CompilerErrorCollection(original.compileErrors);
84    }
85    public Script() {
86      name = ItemName;
87      description = ItemDescription;
88      code = CodeTemplate;
89    }
90    public Script(string code)
91      : this() {
92      this.code = code;
93    }
94
95    public override IDeepCloneable Clone(Cloner cloner) {
96      return new Script(this, cloner);
97    }
98    #endregion
99
100    #region Compilation
101    protected virtual CSharpCodeProvider CodeProvider {
102      get {
103        return new CSharpCodeProvider(
104          new Dictionary<string, string> {
105                {"CompilerVersion", "v4.0"}, // support C# 4.0 syntax
106              });
107      }
108    }
109
110    protected virtual CompilerResults DoCompile() {
111      var parameters = new CompilerParameters {
112        GenerateExecutable = false,
113        GenerateInMemory = true,
114        IncludeDebugInformation = true,
115        WarningLevel = 4
116      };
117      parameters.ReferencedAssemblies.AddRange(
118        GetAssemblies()
119        .Select(a => a.Location)
120        .ToArray());
121      var unit = CreateCompilationUnit();
122      var writer = new StringWriter();
123      CodeProvider.GenerateCodeFromCompileUnit(
124        unit,
125        writer,
126        new CodeGeneratorOptions {
127          ElseOnClosing = true,
128          IndentString = "  ",
129        });
130      compilationUnitCode = writer.ToString();
131      return CodeProvider.CompileAssemblyFromDom(parameters, unit);
132    }
133
134    public virtual Assembly Compile() {
135      var results = DoCompile();
136      CompileErrors = results.Errors;
137      if (results.Errors.HasErrors) {
138        var sb = new StringBuilder();
139        foreach (CompilerError error in results.Errors) {
140          sb.Append(error.Line).Append(':')
141            .Append(error.Column).Append(": ")
142            .AppendLine(error.ErrorText);
143        }
144        throw new Exception(string.Format("Compilation of \"{0}\" failed:{1}{2}",
145          Name, Environment.NewLine, sb.ToString()));
146      } else {
147        return results.CompiledAssembly;
148      }
149    }
150
151    public virtual IEnumerable<Assembly> GetAssemblies() {
152      var assemblies = new List<Assembly>();
153      foreach (var a in AppDomain.CurrentDomain.GetAssemblies()) {
154        try {
155          if (File.Exists(a.Location)) assemblies.Add(a);
156        } catch (NotSupportedException) {
157          // NotSupportedException is thrown while accessing
158          // the Location property of the anonymously hosted
159          // dynamic methods assembly, which is related to
160          // LINQ queries
161        }
162      }
163      assemblies.Add(typeof(Microsoft.CSharp.RuntimeBinder.Binder).Assembly); // for dlr functionality
164      return assemblies;
165    }
166
167    protected virtual CodeCompileUnit CreateCompilationUnit() {
168      var unit = new CodeSnippetCompileUnit(code);
169      return unit;
170    }
171    #endregion
172
173    public event EventHandler CodeChanged;
174    protected virtual void OnCodeChanged() {
175      var handler = CodeChanged;
176      if (handler != null) handler(this, EventArgs.Empty);
177    }
178
179    public event EventHandler CompileErrorsChanged;
180    protected virtual void OnCompileErrorsChanged() {
181      var handler = CompileErrorsChanged;
182      if (handler != null) handler(this, EventArgs.Empty);
183    }
184  }
185}
Note: See TracBrowser for help on using the repository browser.