Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFile.cs')
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFile.cs581
1 files changed, 581 insertions, 0 deletions
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFile.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFile.cs
new file mode 100644
index 0000000000..ba9c875b75
--- /dev/null
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFile.cs
@@ -0,0 +1,581 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.IO;
+using System.Collections;
+using MonoDevelop.Core;
+
+namespace MonoDevelop.Projects.Formats.MSBuild
+{
+ public class SlnFile
+ {
+ SlnProjectCollection projects = new SlnProjectCollection ();
+ SlnSectionCollection sections = new SlnSectionCollection ();
+ SlnPropertySet metadata = new SlnPropertySet (true);
+
+ public string FormatVersion { get; set; }
+ public string ProductDescription { get; set; }
+
+ public string VisualStudioVersion {
+ get { return metadata.GetValue ("VisualStudioVersion"); }
+ set { metadata.SetValue ("VisualStudioVersion", value); }
+ }
+
+ public string MinimumVisualStudioVersion {
+ get { return metadata.GetValue ("MinimumVisualStudioVersion"); }
+ set { metadata.SetValue ("MinimumVisualStudioVersion", value); }
+ }
+
+ public SlnFile ()
+ {
+ }
+
+ /// <summary>
+ /// The directory to be used as base for converting absolute paths to relative
+ /// </summary>
+ public FilePath BaseDirectory {
+ get;
+ set;
+ }
+
+ public SlnPropertySet SolutionConfigurationsSection {
+ get { return sections.GetOrCreateSection ("SolutionConfigurationPlatforms", "preSolution").Properties; }
+ }
+
+ public SlnPropertySetCollection ProjectConfigurationsSection {
+ get { return sections.GetOrCreateSection ("ProjectConfigurationPlatforms", "postSolution").NestedPropertySets; }
+ }
+
+ public SlnSectionCollection Sections {
+ get { return sections; }
+ }
+
+ public SlnProjectCollection Projects {
+ get { return projects; }
+ }
+
+ public void Read (string file)
+ {
+ using (var sr = new StreamReader (file))
+ Read (sr);
+ }
+
+ public void Read (TextReader reader)
+ {
+ string line;
+ int curLineNum = 0;
+ bool globalFound = false;
+ bool productRead = false;
+
+ while ((line = reader.ReadLine ()) != null) {
+ curLineNum++;
+ line = line.Trim ();
+ if (line.StartsWith ("Microsoft Visual Studio Solution File")) {
+ int i = line.LastIndexOf (' ');
+ if (i == -1)
+ throw new InvalidSolutionFormatException (curLineNum);
+ FormatVersion = line.Substring (i + 1);
+ }
+ if (line.StartsWith ("# ")) {
+ if (!productRead) {
+ productRead = true;
+ ProductDescription = line.Substring (2);
+ }
+ } else if (line.StartsWith ("Project")) {
+ SlnProject p = new SlnProject ();
+ p.Read (reader, line, ref curLineNum);
+ projects.Add (p);
+ } else if (line == "Global") {
+ if (globalFound)
+ throw new InvalidSolutionFormatException (curLineNum, "Global section specified more than once");
+ globalFound = true;
+ while ((line = reader.ReadLine ()) != null) {
+ curLineNum++;
+ line = line.Trim ();
+ if (line == "EndGlobal") {
+ break;
+ } else if (line.StartsWith ("GlobalSection")) {
+ var sec = new SlnSection ();
+ sec.Read (reader, line, ref curLineNum);
+ sections.Add (sec);
+ } else
+ throw new InvalidSolutionFormatException (curLineNum);
+ }
+ if (line == null)
+ throw new InvalidSolutionFormatException (curLineNum, "Global section not closed");
+ } else if (line.IndexOf ('=') != -1) {
+ metadata.ReadLine (line, curLineNum);
+ }
+ }
+ if (FormatVersion == null)
+ throw new InvalidSolutionFormatException (curLineNum, "File header is missing");
+ }
+
+ public void Write (string file)
+ {
+ using (var sw = new StreamWriter (file))
+ Write (sw);
+ }
+
+ public void Write (TextWriter writer)
+ {
+ writer.NewLine = "\r\n";
+ writer.WriteLine ("\r\nMicrosoft Visual Studio Solution File, Format Version " + FormatVersion);
+ writer.WriteLine ("# " + ProductDescription);
+
+ metadata.Write (writer);
+
+ foreach (var p in projects)
+ p.Write (writer);
+
+ writer.WriteLine ("Global");
+ foreach (SlnSection s in sections)
+ s.Write (writer, "GlobalSection");
+ writer.WriteLine ("EndGlobal");
+ }
+ }
+
+ public class SlnProject
+ {
+ SlnSectionCollection sections = new SlnSectionCollection ();
+
+ public string Id { get; set; }
+ public string TypeGuid { get; set; }
+ public string Name { get; set; }
+ public string FilePath { get; set; }
+ public int Line { get; private set; }
+ internal bool Processed { get; set; }
+
+ public SlnSectionCollection Sections {
+ get { return sections; }
+ }
+
+ internal void Read (TextReader reader, string line, ref int curLineNum)
+ {
+ Line = curLineNum;
+
+ int n = 0;
+ FindNext (curLineNum, line, ref n, '(');
+ n++;
+ FindNext (curLineNum, line, ref n, '"');
+ int n2 = n + 1;
+ FindNext (curLineNum, line, ref n2, '"');
+ TypeGuid = line.Substring (n + 1, n2 - n - 1);
+
+ n = n2 + 1;
+ FindNext (curLineNum, line, ref n, ')');
+ FindNext (curLineNum, line, ref n, '=');
+
+ FindNext (curLineNum, line, ref n, '"');
+ n2 = n + 1;
+ FindNext (curLineNum, line, ref n2, '"');
+ Name = line.Substring (n + 1, n2 - n - 1);
+
+ n = n2 + 1;
+ FindNext (curLineNum, line, ref n, ',');
+ FindNext (curLineNum, line, ref n, '"');
+ n2 = n + 1;
+ FindNext (curLineNum, line, ref n2, '"');
+ FilePath = line.Substring (n + 1, n2 - n - 1);
+
+ n = n2 + 1;
+ FindNext (curLineNum, line, ref n, ',');
+ FindNext (curLineNum, line, ref n, '"');
+ n2 = n + 1;
+ FindNext (curLineNum, line, ref n2, '"');
+ Id = line.Substring (n + 1, n2 - n - 1);
+
+ while ((line = reader.ReadLine ()) != null) {
+ curLineNum++;
+ line = line.Trim ();
+ if (line == "EndProject") {
+ return;
+ }
+ if (line.StartsWith ("ProjectSection")) {
+ if (sections == null)
+ sections = new SlnSectionCollection ();
+ var sec = new SlnSection ();
+ sections.Add (sec);
+ sec.Read (reader, line, ref curLineNum);
+ }
+ }
+
+ throw new InvalidSolutionFormatException (curLineNum, "Project section not closed");
+ }
+
+ void FindNext (int ln, string line, ref int i, char c)
+ {
+ i = line.IndexOf (c, i);
+ if (i == -1)
+ throw new InvalidSolutionFormatException (ln);
+ }
+
+ public void Write (TextWriter writer)
+ {
+ writer.Write ("Project(\"");
+ writer.Write (TypeGuid);
+ writer.Write ("\") = \"");
+ writer.Write (Name);
+ writer.Write ("\", \"");
+ writer.Write (FilePath);
+ writer.Write ("\", \"");
+ writer.Write (Id);
+ writer.WriteLine ("\"");
+ if (sections != null) {
+ foreach (SlnSection s in sections)
+ s.Write (writer, "ProjectSection");
+ }
+ writer.WriteLine ("EndProject");
+ }
+ }
+
+ public class SlnSection
+ {
+ SlnPropertySetCollection nestedPropertySets;
+ SlnPropertySet properties;
+ List<string> sectionLines;
+ int baseIndex;
+
+ public string Id { get; set; }
+ public int Line { get; private set; }
+ internal bool Processed { get; set; }
+
+ public SlnPropertySet Properties {
+ get {
+ if (properties == null) {
+ properties = new SlnPropertySet ();
+ if (sectionLines != null) {
+ foreach (var line in sectionLines)
+ properties.ReadLine (line, Line);
+ sectionLines = null;
+ }
+ }
+ return properties;
+ }
+ }
+
+ public SlnPropertySetCollection NestedPropertySets {
+ get {
+ if (nestedPropertySets == null) {
+ nestedPropertySets = new SlnPropertySetCollection ();
+ if (sectionLines != null)
+ LoadPropertySets ();
+ }
+ return nestedPropertySets;
+ }
+ }
+
+ public string SectionType { get; set; }
+
+ internal void Read (TextReader reader, string line, ref int curLineNum)
+ {
+ Line = curLineNum;
+ int k = line.IndexOf ('(');
+ if (k == -1)
+ throw new InvalidSolutionFormatException (curLineNum, "Section id missing");
+ var tag = line.Substring (0, k).Trim ();
+ var k2 = line.IndexOf (')', k);
+ if (k2 == -1)
+ throw new InvalidSolutionFormatException (curLineNum);
+ Id = line.Substring (k + 1, k2 - k - 1);
+
+ k = line.IndexOf ('=', k2);
+ SectionType = line.Substring (k + 1).Trim ();
+
+ var endTag = "End" + tag;
+
+ sectionLines = new List<string> ();
+ baseIndex = ++curLineNum;
+ while ((line = reader.ReadLine()) != null) {
+ curLineNum++;
+ line = line.Trim ();
+ if (line == endTag)
+ break;
+ sectionLines.Add (line);
+ }
+ if (line == null)
+ throw new InvalidSolutionFormatException (curLineNum, "Closing section tag not found");
+ }
+
+ void LoadPropertySets ()
+ {
+ if (sectionLines != null) {
+ SlnPropertySet curSet = null;
+ for (int n = 0; n < sectionLines.Count; n++) {
+ var line = sectionLines [n];
+ var i = line.IndexOf ('.');
+ if (i == -1)
+ throw new InvalidSolutionFormatException (baseIndex + i);
+ var id = line.Substring (0, i);
+ if (curSet == null || id != curSet.Id) {
+ curSet = new SlnPropertySet (id);
+ nestedPropertySets.Add (curSet);
+ }
+ curSet.ReadLine (line.Substring (i + 1), baseIndex + i);
+ }
+ sectionLines = null;
+ }
+ }
+
+ internal void Write (TextWriter writer, string sectionTag)
+ {
+ writer.Write ("\t");
+ writer.Write (sectionTag);
+ writer.Write ('(');
+ writer.Write (Id);
+ writer.Write (") = ");
+ writer.WriteLine (SectionType);
+ if (sectionLines != null) {
+ foreach (var l in sectionLines)
+ writer.WriteLine ("\t\t" + l);
+ } else if (properties != null)
+ properties.Write (writer);
+ else if (nestedPropertySets != null) {
+ foreach (var ps in nestedPropertySets)
+ ps.Write (writer);
+ }
+ writer.WriteLine ("\tEnd" + sectionTag);
+ }
+ }
+
+ public class SlnPropertySet: IDictionary<string,string>
+ {
+ OrderedDictionary values = new OrderedDictionary ();
+ bool isMetadata;
+
+ internal bool Processed { get; set; }
+ public int Line { get; private set; }
+
+ public SlnPropertySet ()
+ {
+ }
+
+ public SlnPropertySet (string id)
+ {
+ Id = id;
+ }
+
+ internal SlnPropertySet (bool isMetadata)
+ {
+ this.isMetadata = isMetadata;
+ }
+
+ internal void ReadLine (string line, int currentLine)
+ {
+ if (Line == 0)
+ Line = currentLine;
+ line = line.Trim ();
+ int k = line.IndexOf ('=');
+ if (k != -1) {
+ var name = line.Substring (0, k).Trim ();
+ var val = line.Substring (k + 1).Trim ();
+ values.Add (name, val);
+ } else {
+ values.Add (line, null);
+ }
+ }
+
+ internal void Write (TextWriter writer)
+ {
+ foreach (DictionaryEntry e in values) {
+ if (!isMetadata)
+ writer.Write ("\t\t");
+ if (Id != null)
+ writer.Write (Id + ".");
+ writer.WriteLine (e.Key + " = " + e.Value);
+ }
+ }
+
+ public string Id { get; private set; }
+
+ public string GetValue (string key)
+ {
+ return (string) values [key];
+ }
+
+ public void SetValue (string key, string value)
+ {
+ values [key] = value;
+ }
+
+ public void Add (string key, string value)
+ {
+ SetValue (key, value);
+ }
+
+ public bool ContainsKey (string key)
+ {
+ return values.Contains (key);
+ }
+
+ public bool Remove (string key)
+ {
+ var wasThere = values.Contains (key);
+ values.Remove (key);
+ return wasThere;
+ }
+
+ public bool TryGetValue (string key, out string value)
+ {
+ value = (string) values [key];
+ return value != null;
+ }
+
+ public string this [string index] {
+ get {
+ return (string) values [index];
+ }
+ set {
+ values [index] = value;
+ }
+ }
+
+ public ICollection<string> Values {
+ get {
+ return values.Values.Cast<string>().ToList ();
+ }
+ }
+
+ public ICollection<string> Keys {
+ get { return values.Keys.Cast<string> ().ToList (); }
+ }
+
+ public void Add (KeyValuePair<string, string> item)
+ {
+ SetValue (item.Key, item.Value);
+ }
+
+ public void Clear ()
+ {
+ values.Clear ();
+ }
+
+ internal void ClearExcept (HashSet<string> keys)
+ {
+ foreach (var k in values.Keys.Cast<string>().Except (keys).ToArray ())
+ values.Remove (k);
+ }
+
+ public bool Contains (KeyValuePair<string, string> item)
+ {
+ var val = GetValue (item.Key);
+ return val == item.Value;
+ }
+
+ public void CopyTo (KeyValuePair<string, string>[] array, int arrayIndex)
+ {
+ foreach (DictionaryEntry de in values)
+ array [arrayIndex++] = new KeyValuePair<string, string> ((string)de.Key, (string)de.Value);
+ }
+
+ public bool Remove (KeyValuePair<string, string> item)
+ {
+ if (Contains (item)) {
+ Remove (item.Key);
+ return true;
+ } else
+ return false;
+ }
+
+ public int Count {
+ get {
+ return values.Count;
+ }
+ }
+
+ public bool IsReadOnly {
+ get {
+ return false;
+ }
+ }
+
+ public IEnumerator<KeyValuePair<string, string>> GetEnumerator ()
+ {
+ foreach (DictionaryEntry de in values)
+ yield return new KeyValuePair<string,string> ((string)de.Key, (string)de.Value);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator ()
+ {
+ foreach (DictionaryEntry de in values)
+ yield return new KeyValuePair<string,string> ((string)de.Key, (string)de.Value);
+ }
+ }
+
+ public class SlnProjectCollection: Collection<SlnProject>
+ {
+ public SlnProject GetProject (string id)
+ {
+ return this.FirstOrDefault (s => s.Id == id);
+ }
+
+ public SlnProject GetOrCreateProject (string id)
+ {
+ var p = this.FirstOrDefault (s => s.Id.Equals (id, StringComparison.OrdinalIgnoreCase));
+ if (p == null) {
+ p = new SlnProject { Id = id };
+ Add (p);
+ }
+ return p;
+ }
+ }
+
+ public class SlnSectionCollection: Collection<SlnSection>
+ {
+ public SlnSection GetSection (string id)
+ {
+ return this.FirstOrDefault (s => s.Id == id);
+ }
+
+ public SlnSection GetOrCreateSection (string id, string sectionType)
+ {
+ var sec = this.FirstOrDefault (s => s.Id == id);
+ if (sec == null) {
+ sec = new SlnSection { Id = id };
+ sec.SectionType = sectionType;
+ Add (sec);
+ }
+ return sec;
+ }
+
+ public void RemoveSection (string id)
+ {
+ var s = GetSection (id);
+ if (s != null)
+ Remove (s);
+ }
+ }
+
+ public class SlnPropertySetCollection: Collection<SlnPropertySet>
+ {
+ public SlnPropertySet GetPropertySet (string id, bool ignoreCase = false)
+ {
+ var sc = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
+ return this.FirstOrDefault (s => s.Id.Equals (id, sc));
+ }
+
+ public SlnPropertySet GetOrCreatePropertySet (string id, bool ignoreCase = false)
+ {
+ var ps = GetPropertySet (id, ignoreCase);
+ if (ps == null) {
+ ps = new SlnPropertySet (id);
+ Add (ps);
+ }
+ return ps;
+ }
+ }
+
+ class InvalidSolutionFormatException: Exception
+ {
+ public InvalidSolutionFormatException (int line): base ("Invalid format in line " + line)
+ {
+ }
+
+ public InvalidSolutionFormatException (int line, string msg): base ("Invalid format in line " + line + ": " + msg)
+ {
+ }
+ }
+}
+