Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
Project.cs
Go to the documentation of this file.
1 #region License
2 // Copyright (c) 2012-2014 Silicon Studio Corporation (http://siliconstudio.co.jp)
3 // This file is distributed under MIT License. See LICENSE.md for details.
4 //
5 // SLNTools
6 // Copyright (c) 2009
7 // by Christian Warren
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
10 // documentation files (the "Software"), to deal in the Software without restriction, including without limitation
11 // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
12 // to permit persons to whom the Software is furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in all copies or substantial portions
15 // of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
18 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20 // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 // DEALINGS IN THE SOFTWARE.
22 #endregion
23 
24 using System;
25 using System.Collections.Generic;
26 using System.IO;
27 using System.Text.RegularExpressions;
28 using System.Xml;
29 
30 namespace SiliconStudio.Core.VisualStudio
31 {
32  /// <summary>
33  /// A project referenced by a VisualStudio solution.
34  /// </summary>
35  public class Project
36  {
37  private readonly Guid guid;
38  private readonly PropertyItemCollection platformProperties;
39  private readonly SectionCollection sections;
40  private readonly Solution solution;
41  private readonly PropertyItemCollection versionControlProperties;
42 
43  /// <summary>
44  /// Initializes a new instance of the <see cref="Project"/> class.
45  /// </summary>
46  /// <param name="solution">The solution.</param>
47  /// <param name="original">The original.</param>
48  public Project(Solution solution, Project original)
49  : this(
50  solution,
51  original.Guid,
52  original.TypeGuid,
53  original.Name,
54  original.RelativePath,
55  original.ParentGuid,
56  original.Sections,
57  original.VersionControlProperties,
58  original.PlatformProperties)
59  {
60  }
61 
62  /// <summary>
63  /// Initializes a new instance of the <see cref="Project"/> class.
64  /// </summary>
65  /// <param name="solution">The solution.</param>
66  /// <param name="guid">The unique identifier.</param>
67  /// <param name="typeGuid">The type unique identifier.</param>
68  /// <param name="name">The name.</param>
69  /// <param name="relativePath">The relative path.</param>
70  /// <param name="parentGuid">The parent unique identifier.</param>
71  /// <param name="projectSections">The project sections.</param>
72  /// <param name="versionControlLines">The version control lines.</param>
73  /// <param name="projectConfigurationPlatformsLines">The project configuration platforms lines.</param>
74  /// <exception cref="System.ArgumentNullException">
75  /// solution
76  /// or
77  /// guid
78  /// or
79  /// typeGuid
80  /// or
81  /// name
82  /// </exception>
83  public Project(
84  Solution solution,
85  Guid guid,
86  Guid typeGuid,
87  string name,
88  string relativePath,
89  Guid parentGuid,
90  IEnumerable<Section> projectSections,
91  IEnumerable<PropertyItem> versionControlLines,
92  IEnumerable<PropertyItem> projectConfigurationPlatformsLines)
93  {
94  if (solution == null) throw new ArgumentNullException("solution");
95  if (guid == null) throw new ArgumentNullException("guid");
96  if (typeGuid == null) throw new ArgumentNullException("typeGuid");
97  if (name == null) throw new ArgumentNullException("name");
98 
99  this.solution = solution;
100  this.guid = guid;
101  this.TypeGuid = typeGuid;
102  this.Name = name;
103  this.RelativePath = relativePath;
104  this.ParentGuid = parentGuid;
105  sections = new SectionCollection(projectSections);
106  versionControlProperties = new PropertyItemCollection(versionControlLines);
107  platformProperties = new PropertyItemCollection(projectConfigurationPlatformsLines);
108  }
109 
110  /// <summary>
111  /// Gets all descendants <see cref="Project"/>
112  /// </summary>
113  /// <value>All descendants.</value>
114  public IEnumerable<Project> AllDescendants
115  {
116  get
117  {
118  foreach (var child in Children)
119  {
120  yield return child;
121  foreach (var subchild in child.AllDescendants)
122  {
123  yield return subchild;
124  }
125  }
126  }
127  }
128 
129  /// <summary>
130  /// Gets a value indicating whether this instance is solution folder.
131  /// </summary>
132  /// <value><c>true</c> if this instance is solution folder; otherwise, <c>false</c>.</value>
133  public bool IsSolutionFolder
134  {
135  get
136  {
137  return TypeGuid == KnownProjectTypeGuid.SolutionFolder;
138  }
139  }
140 
141  /// <summary>
142  /// Gets all direct child <see cref="Project"/>
143  /// </summary>
144  /// <value>The children.</value>
145  public IEnumerable<Project> Children
146  {
147  get
148  {
149  if (IsSolutionFolder)
150  {
151  foreach (var project in solution.Projects)
152  {
153  if (project.ParentGuid == guid)
154  yield return project;
155  }
156  }
157  }
158  }
159 
160  /// <summary>
161  /// Gets all project dependencies.
162  /// </summary>
163  /// <value>The dependencies.</value>
164  /// <exception cref="SolutionFileException">
165  /// </exception>
166  public IEnumerable<Project> Dependencies
167  {
168  get
169  {
170  if (ParentProject != null)
171  {
172  yield return ParentProject;
173  }
174 
175  if (sections.Contains("ProjectDependencies"))
176  {
177  foreach (PropertyItem propertyLine in sections["ProjectDependencies"].Properties)
178  {
179  string dependencyGuid = propertyLine.Name;
180  yield return FindProjectInContainer(
181  dependencyGuid,
182  "Cannot find one of the dependency of project '{0}'.\nProject guid: {1}\nDependency guid: {2}\nReference found in: ProjectDependencies section of the solution file",
183  Name,
184  guid,
185  dependencyGuid);
186  }
187  }
188 
189 
190  if (TypeGuid == KnownProjectTypeGuid.VisualC)
191  {
192  if (!File.Exists(FullPath))
193  {
194  throw new SolutionFileException(string.Format(
195  "Cannot detect dependencies of projet '{0}' because the project file cannot be found.\nProject full path: '{1}'",
196  Name,
197  FullPath));
198  }
199 
200  var docVisualC = new XmlDocument();
201  docVisualC.Load(FullPath);
202 
203  foreach (XmlNode xmlNode in docVisualC.SelectNodes(@"//ProjectReference"))
204  {
205  string dependencyGuid = xmlNode.Attributes["ReferencedProjectIdentifier"].Value; // TODO handle null
206  string dependencyRelativePathToProject;
207  XmlNode relativePathToProjectNode = xmlNode.Attributes["RelativePathToProject"];
208  if (relativePathToProjectNode != null)
209  {
210  dependencyRelativePathToProject = relativePathToProjectNode.Value;
211  }
212  else
213  {
214  dependencyRelativePathToProject = "???";
215  }
216  yield return FindProjectInContainer(
217  dependencyGuid,
218  "Cannot find one of the dependency of project '{0}'.\nProject guid: {1}\nDependency guid: {2}\nDependency relative path: '{3}'\nReference found in: ProjectReference node of file '{4}'",
219  Name,
220  guid,
221  dependencyGuid,
222  dependencyRelativePathToProject,
223  FullPath);
224  }
225  }
226 
227  else if (TypeGuid == KnownProjectTypeGuid.Setup)
228  {
229  if (!File.Exists(FullPath))
230  {
231  throw new SolutionFileException(string.Format(
232  "Cannot detect dependencies of projet '{0}' because the project file cannot be found.\nProject full path: '{1}'",
233  Name,
234  FullPath));
235  }
236 
237  foreach (string line in File.ReadAllLines(FullPath))
238  {
239  var regex = new Regex("^\\s*\"OutputProjectGuid\" = \"\\d*\\:(?<PROJECTGUID>.*)\"$");
240  Match match = regex.Match(line);
241  if (match.Success)
242  {
243  string dependencyGuid = match.Groups["PROJECTGUID"].Value.Trim();
244  yield return FindProjectInContainer(
245  dependencyGuid,
246  "Cannot find one of the dependency of project '{0}'.\nProject guid: {1}\nDependency guid: {2}\nReference found in: OutputProjectGuid line of file '{3}'",
247  Name,
248  guid,
249  dependencyGuid,
250  FullPath);
251  }
252  }
253  }
254 
255  else if (TypeGuid == KnownProjectTypeGuid.WebProject)
256  {
257 
258  // Format is: "({GUID}|ProjectName;)*"
259  // Example: "{GUID}|Infra.dll;{GUID2}|Services.dll;"
260  PropertyItem propertyItem = sections["WebsiteProperties"].Properties["ProjectReferences"];
261  string value = propertyItem.Value;
262  if (value.StartsWith("\""))
263  value = value.Substring(1);
264  if (value.EndsWith("\""))
265  value = value.Substring(0, value.Length - 1);
266 
267  foreach (string dependency in value.Split(';'))
268  {
269  if (dependency.Trim().Length > 0)
270  {
271  string[] parts = dependency.Split('|');
272  string dependencyGuid = parts[0];
273  string dependencyName = parts[1]; // TODO handle null
274  yield return FindProjectInContainer(
275  dependencyGuid,
276  "Cannot find one of the dependency of project '{0}'.\nProject guid: {1}\nDependency guid: {2}\nDependency name: {3}\nReference found in: ProjectReferences line in WebsiteProperties section of the solution file",
277  Name,
278  guid,
279  dependencyGuid,
280  dependencyName);
281  }
282  }
283  }
284  else if (!IsSolutionFolder)
285  {
286  if (!File.Exists(FullPath))
287  {
288  throw new SolutionFileException(string.Format(
289  "Cannot detect dependencies of projet '{0}' because the project file cannot be found.\nProject full path: '{1}'",
290  Name,
291  FullPath));
292  }
293 
294  var docManaged = new XmlDocument();
295  docManaged.Load(FullPath);
296 
297  var xmlManager = new XmlNamespaceManager(docManaged.NameTable);
298  xmlManager.AddNamespace("prefix", "http://schemas.microsoft.com/developer/msbuild/2003");
299 
300  foreach (XmlNode xmlNode in docManaged.SelectNodes(@"//prefix:ProjectReference", xmlManager))
301  {
302  string dependencyGuid = xmlNode.SelectSingleNode(@"prefix:Project", xmlManager).InnerText.Trim(); // TODO handle null
303  string dependencyName = xmlNode.SelectSingleNode(@"prefix:Name", xmlManager).InnerText.Trim(); // TODO handle null
304  yield return FindProjectInContainer(
305  dependencyGuid,
306  "Cannot find one of the dependency of project '{0}'.\nProject guid: {1}\nDependency guid: {2}\nDependency name: {3}\nReference found in: ProjectReference node of file '{4}'",
307  Name,
308  guid,
309  dependencyGuid,
310  dependencyName,
311  FullPath);
312  }
313  }
314  }
315  }
316 
317  /// <summary>
318  /// Gets the solution.
319  /// </summary>
320  /// <value>The solution.</value>
321  public Solution Solution
322  {
323  get
324  {
325  return solution;
326  }
327  }
328 
329  /// <summary>
330  /// Gets the full path.
331  /// </summary>
332  /// <value>The full path.</value>
333  public string FullPath
334  {
335  get
336  {
337  return Path.Combine(Path.GetDirectoryName(solution.FullPath), RelativePath);
338  }
339  }
340 
341  /// <summary>
342  /// Gets the parent project.
343  /// </summary>
344  /// <value>The parent project.</value>
345  public Project ParentProject
346  {
347  get
348  {
349  if (ParentGuid == Guid.Empty)
350  return null;
351 
352  return FindProjectInContainer(
353  ParentGuid,
354  "Cannot find the parent folder of project '{0}'. \nProject guid: {1}\nParent folder guid: {2}",
355  Name,
356  guid,
357  ParentGuid);
358  }
359  }
360 
361  /// <summary>
362  /// Gets or sets the parent folder unique identifier.
363  /// </summary>
364  /// <value>The parent folder unique identifier.</value>
365  public Guid ParentGuid { get; set; }
366 
367  /// <summary>
368  /// Gets the full name of the project.
369  /// </summary>
370  /// <value>The full name of the project.</value>
371  public string FullName
372  {
373  get
374  {
375  if (ParentProject != null)
376  {
377  return ParentProject.FullName + @"\" + Name;
378  }
379  return Name;
380  }
381  }
382 
383  /// <summary>
384  /// Gets the project unique identifier.
385  /// </summary>
386  /// <value>The project unique identifier.</value>
387  public Guid Guid
388  {
389  get
390  {
391  return guid;
392  }
393  }
394 
395  /// <summary>
396  /// Gets or sets the name of the project.
397  /// </summary>
398  /// <value>The name of the project.</value>
399  public string Name { get; set; }
400 
401  /// <summary>
402  /// Gets the project platform properties.
403  /// </summary>
404  /// <value>The project platform properties.</value>
405  public PropertyItemCollection PlatformProperties
406  {
407  get
408  {
409  return platformProperties;
410  }
411  }
412 
413  /// <summary>
414  /// Gets the project sections.
415  /// </summary>
416  /// <value>The project sections.</value>
417  public SectionCollection Sections
418  {
419  get
420  {
421  return sections;
422  }
423  }
424 
425  /// <summary>
426  /// Gets or sets the type unique identifier.
427  /// </summary>
428  /// <value>The type unique identifier.</value>
429  public Guid TypeGuid { get; set; }
430 
431  /// <summary>
432  /// Gets or sets the relative path.
433  /// </summary>
434  /// <value>The relative path.</value>
435  public string RelativePath { get; set; }
436 
437  /// <summary>
438  /// Gets the version control properties.
439  /// </summary>
440  /// <value>The version control properties.</value>
441  public PropertyItemCollection VersionControlProperties
442  {
443  get
444  {
445  return versionControlProperties;
446  }
447  }
448 
449  public override string ToString()
450  {
451  return string.Format("Project '{0}'", FullName);
452  }
453 
454  private Project FindProjectInContainer(Guid projectGuidToFind, string errorMessageFormat, params object[] errorMessageParams)
455  {
456  Project project = solution.Projects.FindByGuid(projectGuidToFind);
457  if (project == null)
458  {
459  throw new SolutionFileException(string.Format(errorMessageFormat, errorMessageParams));
460  }
461  return project;
462  }
463 
464  private Project FindProjectInContainer(string projectGuidToFind, string errorMessageFormat, params object[] errorMessageParams)
465  {
466  return FindProjectInContainer(Guid.Parse(projectGuidToFind), errorMessageFormat, errorMessageParams);
467  }
468  }
469 }
Project(Solution solution, Project original)
Initializes a new instance of the Project class.
Definition: Project.cs:48
A project referenced by a VisualStudio solution.
Definition: Project.cs:35
A key/value pair used by PropertyItemCollection
Definition: PropertyItem.cs:33
System.IO.File File
A VisualStudio solution.
Definition: Solution.cs:37
EnvDTE.Project Project
Project(Solution solution, Guid guid, Guid typeGuid, string name, string relativePath, Guid parentGuid, IEnumerable< Section > projectSections, IEnumerable< PropertyItem > versionControlLines, IEnumerable< PropertyItem > projectConfigurationPlatformsLines)
Initializes a new instance of the Project class.
Definition: Project.cs:83