Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
DataCodeGenerator.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 using System.Diagnostics;
6 using System.IO;
7 using System.Linq;
8 using System.Runtime.InteropServices;
9 using System.Text;
10 using System.Text.RegularExpressions;
11 using Microsoft.Build.Execution;
12 using Microsoft.Build.Framework;
13 using Microsoft.VisualStudio;
14 using Microsoft.VisualStudio.Shell;
15 using Microsoft.VisualStudio.Shell.Interop;
16 using SiliconStudio.Paradox.VisualStudio.CodeGenerator;
18 
19 namespace SiliconStudio.Paradox.VisualStudio.BuildEngine
20 {
21  [ComVisible(true)]
22  [ClassInterface(ClassInterfaceType.None)]
23  [Guid(GuidList.guidParadox_VisualStudio_DataCodeGenerator)]
24  [ProvideObject(typeof(DataCodeGenerator), RegisterUsing = RegistrationMethod.CodeBase)]
26  {
27  public const string DisplayName = "Paradox Data Code Generator";
28  public const string InternalName = "ParadoxDataCodeGenerator";
29 
30  protected override byte[] GenerateCode(string inputFileName, string inputFileContent)
31  {
32  // Get active project
33  // TODO: Instead of a custom code generator, we should have a context command or something like that.
34  // This should also allow generation of multiple files
35 
36  var lines = Regex.Split(inputFileContent, "\r\n|\r|\n");
37  if (lines.Length == 0 || lines[0].Length == 0)
38  {
39  throw new InvalidOperationException("Source should contain project filename.");
40  }
41 
42  var projectFullName = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(inputFileName), lines[0]));
43  if (!File.Exists(projectFullName))
44  {
45  throw new InvalidOperationException("Project file doesn't exist.");
46  }
47 
48  string assemblyOutput, intermediateAssembly;
49 
50  // Get Evaluation Project
51  Microsoft.Build.Evaluation.Project msbuildProject = Microsoft.Build.Evaluation.ProjectCollection.GlobalProjectCollection.GetLoadedProjects(projectFullName).First();
52 
53  // Set ParadoxBuildStep variable and change IntermediateOutputPath
54  var property1 = msbuildProject.SetProperty("ParadoxBuildStep", "StepData");
55  var property2 = msbuildProject.SetProperty("IntermediateOutputPath", @"obj\StepData\");
56 
57  // Reevaluate dependent properties
58  msbuildProject.ReevaluateIfNecessary();
59 
60  try
61  {
62  var outputPane = GetOutputPane();
63 
64  // Create logger
65  var buildLogger = new IDEBuildLogger(outputPane, new TaskProvider(GlobalServiceProvider), VsHelper.GetCurrentHierarchy(GlobalServiceProvider));
66  buildLogger.Verbosity = Microsoft.Build.Framework.LoggerVerbosity.Diagnostic;
67 
68  var evaluatedProperties = new Dictionary<string, Microsoft.Build.Evaluation.ProjectProperty>();
69  foreach (var evaluatedProperty in msbuildProject.AllEvaluatedProperties)
70  {
71  evaluatedProperties[evaluatedProperty.Name] = evaluatedProperty;
72  }
73 
74  // Output properties
75  foreach (var evaluatedProperty in evaluatedProperties)
76  {
77  outputPane.OutputStringThreadSafe(string.Format(
78  "$({0}) = {1} was evaluated as {2}\n",
79  evaluatedProperty.Key,
80  evaluatedProperty.Value.UnevaluatedValue,
81  evaluatedProperty.Value.EvaluatedValue));
82  }
83 
84  // Compile project (only intermediate assembly)
85  // Dependencies will be built as well
86  //var manager = BuildManager.DefaultBuildManager;
87  using (var manager = new BuildManager())
88  {
89  var pc = new Microsoft.Build.Evaluation.ProjectCollection();
90  var globalProperties = new Dictionary<string, string>();
91  globalProperties["SolutionName"] = evaluatedProperties["SolutionName"].EvaluatedValue;
92  globalProperties["SolutionDir"] = evaluatedProperties["SolutionDir"].EvaluatedValue;
93  var projectInstance = new ProjectInstance(projectFullName, globalProperties, null);
94  var buildResult = manager.Build(
95  new BuildParameters(pc)
96  {
97  Loggers = new[] {buildLogger},
98  DetailedSummary = true,
99  },
100  new BuildRequestData(projectInstance, new[] { "Compile" }, null));
101 
102  if (buildResult.OverallResult == BuildResultCode.Failure)
103  throw new InvalidOperationException(string.Format("Build of {0} failed.", projectFullName));
104  }
105 
106  // Get TargetPath and IntermediateAssembly
107  assemblyOutput = msbuildProject.AllEvaluatedProperties.Last(x => x.Name == "TargetPath").EvaluatedValue;
108  intermediateAssembly = msbuildProject.AllEvaluatedItems.First(x => x.ItemType == "IntermediateAssembly").EvaluatedInclude;
109  }
110  finally
111  {
112  msbuildProject.RemoveProperty(property1);
113  msbuildProject.RemoveProperty(property2);
114  }
115 
116  // Defer execution to current Paradox VS package plugin
118  {
119  try
120  {
121  var remoteCommands = ParadoxCommandsProxy.CreateProxy(domain);
122  return remoteCommands.GenerateDataClasses(assemblyOutput, projectFullName, intermediateAssembly);
123  }
124  catch (Exception ex)
125  {
126  GeneratorError(4, ex.ToString(), 0, 0);
127 
128  return new byte[0];
129  }
130  }
131  }
132 
133  protected override string GetDefaultExtension()
134  {
135  return ".cs";
136  }
137 
138  protected IVsOutputWindowPane GetOutputPane()
139  {
140  var outputWindow = (IVsOutputWindow)Package.GetGlobalService(typeof(SVsOutputWindow));
141 
142  // Get Output pane
143  IVsOutputWindowPane pane;
144  Guid generalPaneGuid = VSConstants.GUID_OutWindowGeneralPane;
145  outputWindow.CreatePane(ref generalPaneGuid, "General", 1, 0);
146  outputWindow.GetPane(ref generalPaneGuid, out pane);
147  return pane;
148  }
149  }
150 }
override string GetDefaultExtension()
Gets the default extension of the output file from the CodeDomProvider
Proxies commands to real IParadoxCommands implementation.
System.IO.File File
override byte[] GenerateCode(string inputFileName, string inputFileContent)
The method that does the actual work of generating code given the input file