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/SlnFileFormat.cs')
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFileFormat.cs1017
1 files changed, 372 insertions, 645 deletions
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFileFormat.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFileFormat.cs
index 27baad33c5..f1f4fb5522 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFileFormat.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFileFormat.cs
@@ -27,10 +27,7 @@
//
using System;
-using System.Collections;
using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.Globalization;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
@@ -41,11 +38,19 @@ using MonoDevelop.Projects.Extensions;
using MonoDevelop.Core;
using System.Reflection;
using System.Linq;
+using System.Threading.Tasks;
namespace MonoDevelop.Projects.Formats.MSBuild
{
- public class SlnFileFormat
+ class SlnFileFormat
{
+ MSBuildFileFormat format;
+
+ public SlnFileFormat (MSBuildFileFormat format)
+ {
+ this.format = format;
+ }
+
public string GetValidFormatName (object obj, string fileName, MSBuildFileFormat format)
{
return Path.ChangeExtension (fileName, ".sln");
@@ -71,372 +76,299 @@ namespace MonoDevelop.Projects.Formats.MSBuild
return null;
}
- public void WriteFile (string file, object obj, MSBuildFileFormat format, bool saveProjects, IProgressMonitor monitor)
+ public Task WriteFile (string file, object obj, bool saveProjects, ProgressMonitor monitor)
{
- Solution sol = (Solution) obj;
+ return Task.Factory.StartNew (delegate {
+ Solution sol = (Solution)obj;
- string tmpfilename = String.Empty;
- try {
- monitor.BeginTask (GettextCatalog.GetString ("Saving solution: {0}", file), 1);
+ string tmpfilename = String.Empty;
try {
- if (File.Exists (file))
- tmpfilename = Path.GetTempFileName ();
- } catch (IOException) {
- }
+ monitor.BeginTask (GettextCatalog.GetString ("Saving solution: {0}", file), 1);
+ try {
+ if (File.Exists (file))
+ tmpfilename = Path.GetTempFileName ();
+ } catch (IOException) {
+ }
- string baseDir = Path.GetDirectoryName (file);
- if (tmpfilename == String.Empty) {
- WriteFileInternal (file, sol, baseDir, format, saveProjects, monitor);
- } else {
- WriteFileInternal (tmpfilename, sol, baseDir, format, saveProjects, monitor);
- File.Delete (file);
- File.Move (tmpfilename, file);
+ if (tmpfilename == String.Empty) {
+ WriteFileInternal (file, file, sol, saveProjects, monitor);
+ } else {
+ WriteFileInternal (tmpfilename, file, sol, saveProjects, monitor);
+ File.Delete (file);
+ File.Move (tmpfilename, file);
+ }
+ } catch (Exception ex) {
+ monitor.ReportError (GettextCatalog.GetString ("Could not save solution: {0}", file), ex);
+ LoggingService.LogError (GettextCatalog.GetString ("Could not save solution: {0}", file), ex);
+
+ if (!String.IsNullOrEmpty (tmpfilename))
+ File.Delete (tmpfilename);
+ throw;
+ } finally {
+ monitor.EndTask ();
}
- } catch (Exception ex) {
- monitor.ReportError (GettextCatalog.GetString ("Could not save solution: {0}", file), ex);
- LoggingService.LogError (GettextCatalog.GetString ("Could not save solution: {0}", file), ex);
-
- if (!String.IsNullOrEmpty (tmpfilename))
- File.Delete (tmpfilename);
- throw;
- } finally {
- monitor.EndTask ();
- }
+ });
}
- void WriteFileInternal (string file, Solution solution, string baseDir, MSBuildFileFormat format, bool saveProjects, IProgressMonitor monitor)
+ void WriteFileInternal (string file, string sourceFile, Solution solution, bool saveProjects, ProgressMonitor monitor)
{
- SolutionFolder c = solution.RootFolder;
-
- using (StreamWriter sw = new StreamWriter (file, false, Encoding.UTF8)) {
- sw.NewLine = "\r\n";
-
- SlnData slnData = GetSlnData (c);
- if (slnData == null) {
- // If a non-msbuild project is being converted by just
- // changing the fileformat, then create the SlnData for it
- slnData = new SlnData ();
- c.ExtendedProperties [typeof (SlnFileFormat)] = slnData;
+ string baseDir = Path.GetDirectoryName (sourceFile);
+
+ if (saveProjects) {
+ var items = solution.GetAllSolutionItems ().ToArray ();
+ monitor.BeginTask (items.Length + 1);
+ foreach (var item in items) {
+ try {
+ monitor.BeginStep ();
+ item.SavingSolution = true;
+ item.Save (monitor);
+ } finally {
+ item.SavingSolution = false;
+ }
}
+ } else {
+ monitor.BeginTask (1);
+ monitor.BeginStep ();
+ }
- slnData.UpdateVersion (format);
-
- sw.WriteLine ();
-
- //Write Header
- sw.WriteLine ("Microsoft Visual Studio Solution File, Format Version " + slnData.VersionString);
- sw.WriteLine (slnData.HeaderComment);
- if (slnData.VisualStudioVersion != null)
- sw.WriteLine ("VisualStudioVersion = {0}", slnData.VisualStudioVersion);
- if (slnData.MinimumVisualStudioVersion != null)
- sw.WriteLine ("MinimumVisualStudioVersion = {0}", slnData.MinimumVisualStudioVersion);
-
- //Write the projects
- monitor.BeginTask (GettextCatalog.GetString ("Saving projects"), 1);
- WriteProjects (c, baseDir, sw, saveProjects, monitor);
- monitor.EndTask ();
+ SlnFile sln = new SlnFile ();
+ sln.BaseDirectory = baseDir;
+ if (File.Exists (sourceFile)) {
+ try {
+ sln.Read (sourceFile);
+ } catch (Exception ex) {
+ LoggingService.LogError ("Existing solution can't be updated since it can't be read", ex);
+ }
+ }
- //Write the lines for unknownProjects
- foreach (string l in slnData.UnknownProjects)
- sw.WriteLine (l);
+ sln.FormatVersion = format.SlnVersion;
+ sln.ProductDescription = format.ProductDescription;
- //Write the Globals
- sw.WriteLine ("Global");
+ solution.WriteSolution (monitor, sln);
- //Write SolutionConfigurationPlatforms
- //FIXME: SolutionConfigurations?
- sw.WriteLine ("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution");
+ sln.Write (file);
+ monitor.EndTask ();
+ }
- foreach (SolutionConfiguration config in solution.Configurations)
- sw.WriteLine ("\t\t{0} = {0}", ToSlnConfigurationId (config));
+ internal void WriteFileInternal (SlnFile sln, Solution solution, ProgressMonitor monitor)
+ {
+ SolutionFolder c = solution.RootFolder;
- sw.WriteLine ("\tEndGlobalSection");
+ // Delete data for projects that have been removed from the solution
+
+ var currentProjects = new HashSet<string> (solution.GetAllItems<SolutionFolderItem> ().Select (it => it.ItemId));
+ var removedProjects = new HashSet<string> ();
+ if (solution.LoadedProjects != null)
+ removedProjects.UnionWith (solution.LoadedProjects.Except (currentProjects));
+ var unknownProjects = new HashSet<string> (sln.Projects.Select (p => p.Id).Except (removedProjects).Except (currentProjects));
+
+ foreach (var p in removedProjects) {
+ var ps = sln.Projects.GetProject (p);
+ if (ps != null)
+ sln.Projects.Remove (ps);
+ var pc = sln.ProjectConfigurationsSection.GetPropertySet (p, true);
+ if (pc != null)
+ sln.ProjectConfigurationsSection.Remove (pc);
+ }
+ var secNested = sln.Sections.GetSection ("NestedProjects");
+ if (secNested != null) {
+ foreach (var np in secNested.Properties.ToArray ()) {
+ if (removedProjects.Contains (np.Key) || removedProjects.Contains (np.Value))
+ secNested.Properties.Remove (np.Key);
+ }
+ }
+ solution.LoadedProjects = currentProjects;
- //Write ProjectConfigurationPlatforms
- sw.WriteLine ("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution");
+ //Write the projects
+ using (monitor.BeginTask (GettextCatalog.GetString ("Saving projects"), 1)) {
+ monitor.BeginStep ();
+ WriteProjects (c, sln, monitor, unknownProjects);
+ }
- List<string> list = new List<string> ();
- WriteProjectConfigurations (solution, list);
+ //FIXME: SolutionConfigurations?
- list.Sort (StringComparer.Create (CultureInfo.InvariantCulture, true));
- foreach (string s in list)
- sw.WriteLine (s);
+ var pset = sln.SolutionConfigurationsSection;
+ foreach (SolutionConfiguration config in solution.Configurations) {
+ var cid = ToSlnConfigurationId (config);
+ pset.SetValue (cid, cid);
+ }
- //Write lines for projects we couldn't load
- if (slnData.SectionExtras.ContainsKey ("ProjectConfigurationPlatforms")) {
- foreach (string s in slnData.SectionExtras ["ProjectConfigurationPlatforms"])
- sw.WriteLine ("\t\t{0}", s);
- }
+ WriteProjectConfigurations (solution, sln);
- sw.WriteLine ("\tEndGlobalSection");
-
- //Write Nested Projects
- ICollection<SolutionFolder> folders = solution.RootFolder.GetAllItems<SolutionFolder> ();
- if (folders.Count > 1) {
- // If folders ==1, that's the root folder
- sw.WriteLine ("\tGlobalSection(NestedProjects) = preSolution");
- foreach (SolutionFolder folder in folders) {
- if (folder.IsRoot)
- continue;
- WriteNestedProjects (folder, solution.RootFolder, sw);
- }
- sw.WriteLine ("\tEndGlobalSection");
+ //Write Nested Projects
+ ICollection<SolutionFolder> folders = solution.RootFolder.GetAllItems<SolutionFolder> ().ToList ();
+ if (folders.Count > 1) {
+ // If folders ==1, that's the root folder
+ var sec = sln.Sections.GetOrCreateSection ("NestedProjects", "preSolution");
+ foreach (SolutionFolder folder in folders) {
+ if (folder.IsRoot)
+ continue;
+ WriteNestedProjects (folder, solution.RootFolder, sec);
}
-
- //Write custom properties
- MSBuildSerializer ser = new MSBuildSerializer (solution.FileName);
- DataItem data = (DataItem) ser.Serialize (solution, typeof(Solution));
+ // Remove items which don't have a parent folder
+ var toRemove = solution.GetAllItems<SolutionFolderItem> ().Where (it => it.ParentFolder == solution.RootFolder);
+ foreach (var it in toRemove)
+ sec.Properties.Remove (it.ItemId);
+ }
+
+ //Write custom properties
+ MSBuildSerializer ser = new MSBuildSerializer (solution.FileName);
+ DataItem data = (DataItem) ser.Serialize (solution, typeof(Solution));
+ if (data.HasItemData) {
+ var sec = sln.Sections.GetOrCreateSection ("MonoDevelopProperties", "preSolution");
+ WriteDataItem (sec.Properties, data);
+ } else
+ sln.Sections.RemoveSection ("MonoDevelopProperties");
+
+ // Write custom properties for configurations
+ foreach (SolutionConfiguration conf in solution.Configurations) {
+ data = (DataItem) ser.Serialize (conf);
+ string secId = "MonoDevelopProperties." + conf.Id;
if (data.HasItemData) {
- sw.WriteLine ("\tGlobalSection(MonoDevelopProperties) = preSolution");
- WriteDataItem (sw, data);
- sw.WriteLine ("\tEndGlobalSection");
- }
-
- // Write custom properties for configurations
- foreach (SolutionConfiguration conf in solution.Configurations) {
- data = (DataItem) ser.Serialize (conf);
- if (data.HasItemData) {
- sw.WriteLine ("\tGlobalSection(MonoDevelopProperties." + conf.Id + ") = preSolution");
- WriteDataItem (sw, data);
- sw.WriteLine ("\tEndGlobalSection");
- }
- }
-
- //Write 'others'
- if (slnData.GlobalExtra != null) {
- foreach (string s in slnData.GlobalExtra)
- sw.WriteLine (s);
+ var sec = sln.Sections.GetOrCreateSection (secId, "preSolution");
+ WriteDataItem (sec.Properties, data);
+ } else {
+ sln.Sections.RemoveSection (secId);
}
-
- sw.WriteLine ("EndGlobal");
}
}
- void WriteProjects (SolutionFolder folder, string baseDirectory, StreamWriter writer, bool saveProjects, IProgressMonitor monitor)
+ void WriteProjects (SolutionFolder folder, SlnFile sln, ProgressMonitor monitor, HashSet<string> unknownProjects)
{
- monitor.BeginStepTask (GettextCatalog.GetString ("Saving projects"), folder.Items.Count, 1);
- foreach (SolutionItem ce in folder.Items)
+ monitor.BeginTask (folder.Items.Count);
+ foreach (SolutionFolderItem ce in folder.Items)
{
- string[] l = null;
- if (ce is SolutionEntityItem) {
+ monitor.BeginStep ();
+ if (ce is SolutionItem) {
- SolutionEntityItem item = (SolutionEntityItem) ce;
- MSBuildHandler handler = MSBuildProjectService.GetItemHandler (item);
-
- if (saveProjects) {
- try {
- handler.SavingSolution = true;
- item.Save (monitor);
- } finally {
- handler.SavingSolution = false;
- }
- }
+ SolutionItem item = (SolutionItem) ce;
- l = handler.SlnProjectContent;
+ var proj = sln.Projects.GetOrCreateProject (ce.ItemId);
+ proj.TypeGuid = item.TypeGuid;
+ proj.Name = item.Name;
+ proj.FilePath = FileService.NormalizeRelativePath (FileService.AbsoluteToRelativePath (sln.BaseDirectory, item.FileName)).Replace ('/', '\\');
- writer.WriteLine (@"Project(""{0}"") = ""{1}"", ""{2}"", ""{3}""",
- handler.TypeGuid,
- item.Name,
- FileService.NormalizeRelativePath (FileService.AbsoluteToRelativePath (
- baseDirectory, item.FileName)).Replace ('/', '\\'),
- ce.ItemId);
- DataItem data = handler.WriteSlnData ();
+ DataItem data = item.WriteSlnData ();
if (data != null && data.HasItemData) {
- writer.WriteLine ("\tProjectSection(MonoDevelopProperties) = preProject");
- WriteDataItem (writer, data);
- writer.WriteLine ("\tEndProjectSection");
- }
+ var sec = proj.Sections.GetOrCreateSection ("MonoDevelopProperties", "preProject");
+ WriteDataItem (sec.Properties, data);
+ } else
+ proj.Sections.RemoveSection ("MonoDevelopProperties");
+
if (item.ItemDependencies.Count > 0) {
- writer.WriteLine ("\tProjectSection(ProjectDependencies) = postProject");
+ var sec = proj.Sections.GetOrCreateSection ("ProjectDependencies", "postProject");
+ sec.Properties.ClearExcept (unknownProjects);
foreach (var dep in item.ItemDependencies)
- writer.WriteLine ("\t\t{0} = {0}", dep.ItemId);
- if (handler.UnresolvedProjectDependencies != null) {
- foreach (var dep in handler.UnresolvedProjectDependencies)
- writer.WriteLine ("\t\t{0} = {0}", dep);
- }
- writer.WriteLine ("\tEndProjectSection");
- }
+ sec.Properties.SetValue (dep.ItemId, dep.ItemId);
+ } else
+ proj.Sections.RemoveSection ("ProjectDependencies");
} else if (ce is SolutionFolder) {
- //Solution
- SlnData slnData = GetSlnData (ce);
- if (slnData == null) {
- // Solution folder
- slnData = new SlnData ();
- ce.ExtendedProperties [typeof (SlnFileFormat)] = slnData;
- }
+ var proj = sln.Projects.GetOrCreateProject (ce.ItemId);
+ proj.TypeGuid = MSBuildProjectService.FolderTypeGuid;
+ proj.Name = ce.Name;
+ proj.FilePath = ce.Name;
- l = slnData.Extra;
-
- writer.WriteLine (@"Project(""{0}"") = ""{1}"", ""{2}"", ""{3}""",
- MSBuildProjectService.FolderTypeGuid,
- ce.Name,
- ce.Name,
- ce.ItemId);
-
// Folder files
- WriteFolderFiles (writer, (SolutionFolder) ce);
+ WriteFolderFiles (proj, (SolutionFolder) ce);
//Write custom properties
MSBuildSerializer ser = new MSBuildSerializer (folder.ParentSolution.FileName);
DataItem data = (DataItem) ser.Serialize (ce, typeof(SolutionFolder));
if (data.HasItemData) {
- writer.WriteLine ("\tProjectSection(MonoDevelopProperties) = preProject");
- WriteDataItem (writer, data);
- writer.WriteLine ("\tEndProjectSection");
+ var sec = proj.Sections.GetOrCreateSection ("MonoDevelopProperties", "preProject");
+ WriteDataItem (sec.Properties, data);
}
}
-
- if (l != null) {
- foreach (string s in l)
- writer.WriteLine (s);
- }
-
- writer.WriteLine ("EndProject");
if (ce is SolutionFolder)
- WriteProjects (ce as SolutionFolder, baseDirectory, writer, saveProjects, monitor);
- monitor.Step (1);
+ WriteProjects (ce as SolutionFolder, sln, monitor, unknownProjects);
}
monitor.EndTask ();
}
- void WriteFolderFiles (StreamWriter writer, SolutionFolder folder)
+ void WriteFolderFiles (SlnProject proj, SolutionFolder folder)
{
if (folder.Files.Count > 0) {
- writer.WriteLine ("\tProjectSection(SolutionItems) = preProject");
+ var sec = proj.Sections.GetOrCreateSection ("SolutionItems", "preProject");
+ sec.Properties.Clear ();
foreach (FilePath f in folder.Files) {
string relFile = MSBuildProjectService.ToMSBuildPathRelative (folder.ParentSolution.ItemDirectory, f);
- writer.WriteLine ("\t\t" + relFile + " = " + relFile);
+ sec.Properties.SetValue (relFile, relFile);
}
- writer.WriteLine ("\tEndProjectSection");
- }
+ } else
+ proj.Sections.RemoveSection ("SolutionItems");
}
- void WriteProjectConfigurations (Solution sol, List<string> list)
+ void WriteProjectConfigurations (Solution sol, SlnFile sln)
{
- foreach (SolutionConfiguration cc in sol.Configurations) {
+ var col = sln.ProjectConfigurationsSection;
+
+ foreach (var item in sol.GetAllSolutionItems ()) {
+ // Don't save configurations for shared projects
+ if (!item.SupportsConfigurations ())
+ continue;
- foreach (SolutionConfigurationEntry cce in cc.Configurations) {
- SolutionEntityItem p = cce.Item;
+ // <ProjectGuid>...</ProjectGuid> in some Visual Studio generated F# project files
+ // are missing "{"..."}" in their guid. This is not generally a problem since it
+ // is a valid GUID format. However the solution file format requires that these are present.
+ string itemGuid = item.ItemId;
+ if (!itemGuid.StartsWith ("{") && !itemGuid.EndsWith ("}"))
+ itemGuid = "{" + itemGuid + "}";
- // Don't save configurations for shared projects
- if (!p.SupportsBuild () && !(p is UnloadedSolutionItem))
+ var pset = col.GetOrCreatePropertySet (itemGuid, ignoreCase:true);
+ pset.Clear ();
+
+ foreach (SolutionConfiguration cc in sol.Configurations) {
+ var cce = cc.GetEntryForItem (item);
+ if (cce == null)
continue;
-
- // <ProjectGuid>...</ProjectGuid> in some Visual Studio generated F# project files
- // are missing "{"..."}" in their guid. This is not generally a problem since it
- // is a valid GUID format. However the solution file format requires that these are present.
- string itemGuid = p.ItemId;
- if (!itemGuid.StartsWith("{") && !itemGuid.EndsWith("}"))
- itemGuid = "{" + itemGuid + "}";
+ var configId = ToSlnConfigurationId (cc);
+ var itemConfigId = ToSlnConfigurationId (cce.ItemConfiguration);
- list.Add (String.Format (
- "\t\t{0}.{1}.ActiveCfg = {2}", itemGuid, ToSlnConfigurationId (cc), ToSlnConfigurationId (cce.ItemConfiguration)));
+ pset.SetValue (configId + ".ActiveCfg", itemConfigId);
if (cce.Build)
- list.Add (String.Format (
- "\t\t{0}.{1}.Build.0 = {2}", itemGuid, ToSlnConfigurationId (cc), ToSlnConfigurationId (cce.ItemConfiguration)));
-
+ pset.SetValue (configId + ".Build.0", itemConfigId);
+
if (cce.Deploy)
- list.Add (String.Format (
- "\t\t{0}.{1}.Deploy.0 = {2}", itemGuid, ToSlnConfigurationId (cc), ToSlnConfigurationId (cce.ItemConfiguration)));
+ pset.SetValue (configId + ".Deploy.0", itemConfigId);
}
}
-
}
- void WriteNestedProjects (SolutionFolder folder, SolutionFolder root, StreamWriter writer)
+ void WriteNestedProjects (SolutionFolder folder, SolutionFolder root, SlnSection sec)
{
- foreach (SolutionItem ce in folder.Items)
- writer.WriteLine (@"{0}{1} = {2}", "\t\t", ce.ItemId, folder.ItemId);
+ foreach (SolutionFolderItem ce in folder.Items)
+ sec.Properties.SetValue (ce.ItemId, folder.ItemId);
}
- DataItem GetSolutionItemData (List<string> lines)
+ List<string> ReadSolutionItemDependencies (SlnProject proj)
{
- // Find a project section of type MonoDevelopProperties
- int start, end;
- if (!FindSection (lines, "MonoDevelopProperties", true, out start, out end))
- return null;
-
- // Deserialize the object
- DataItem it = ReadDataItem (start, end - start + 1, lines);
-
- // Remove the lines, since they have already been preocessed
- lines.RemoveRange (start, end - start + 1);
- return it;
- }
-
- List<string> ReadSolutionItemDependencies (List<string> lines)
- {
- // Find a project section of type MonoDevelopProperties
- int start, end;
- if (!FindSection (lines, "ProjectDependencies", false, out start, out end))
+ // Find a project section of type ProjectDependencies
+ var sec = proj.Sections.GetSection ("ProjectDependencies");
+ if (sec == null)
return null;
- var ids = new List<string> ();
- for (int n=start + 1; n < end; n++) {
- string line = lines [n];
- int i = line.IndexOf ('=');
- if (i != -1)
- ids.Add (line.Substring (0, i).Trim ());
- }
-
- // Remove the lines, since they have already been preocessed
- lines.RemoveRange (start, end - start + 1);
- return ids;
+ return sec.Properties.Keys.ToList ();
}
- List<string> ReadFolderFiles (List<string> lines)
+ IEnumerable<string> ReadFolderFiles (SlnProject proj)
{
// Find a solution item section of type SolutionItems
+ var sec = proj.Sections.GetSection ("SolutionItems");
+ if (sec == null)
+ return new string[0];
- List<string> list = new List<string> ();
- int start, end;
- if (!FindSection (lines, "SolutionItems", true, out start, out end))
- return list;
-
- for (int n=start + 1; n < end; n++) {
- string file = lines [n];
- int i = file.IndexOf ('=');
- if (i == -1)
- continue;
- file = file.Substring (0, i).Trim (' ','\t');
- if (file.Length > 0)
- list.Add (file);
- }
-
- // Remove the lines, since they have already been preocessed
- lines.RemoveRange (start, end - start + 1);
- return list;
+ return sec.Properties.Keys.ToList ();
}
-
- bool FindSection (List<string> lines, string name, bool preProject, out int start, out int end)
- {
- start = -1;
- end = -1;
- string prePost = preProject ? "preProject" : "postProject";
- var sectionLine = "ProjectSection(" + name + ")=" + prePost;
-
- for (int n=0; n<lines.Count && start == -1; n++) {
- string line = lines [n].Replace ("\t","").Replace (" ", "");
- if (line == sectionLine)
- start = n;
- }
- if (start == -1)
- return false;
-
- for (int n=start+1; n<lines.Count && end == -1; n++) {
- string line = lines [n].Replace ("\t","").Replace (" ", "");
- if (line == "EndProjectSection")
- end = n;
- }
- return end != -1;
- }
-
- void DeserializeSolutionItem (Solution sln, SolutionItem item, List<string> lines)
+ void DeserializeSolutionItem (Solution sln, SolutionFolderItem item, SlnProject proj)
{
// Deserialize the object
- DataItem it = GetSolutionItemData (lines);
+ var sec = proj.Sections.GetSection ("MonoDevelopProperties");
+ if (sec == null)
+ return;
+
+ DataItem it = ReadDataItem (sec);
if (it == null)
return;
@@ -445,14 +377,15 @@ namespace MonoDevelop.Projects.Formats.MSBuild
ser.Deserialize (item, it);
}
- void WriteDataItem (StreamWriter sw, DataItem item)
+ void WriteDataItem (SlnPropertySet pset, DataItem item)
{
+ pset.Clear ();
int id = 0;
foreach (DataNode val in item.ItemData)
- WriteDataNode (sw, "", val, ref id);
+ WriteDataNode (pset, "", val, ref id);
}
- void WriteDataNode (StreamWriter sw, string prefix, DataNode node, ref int id)
+ void WriteDataNode (SlnPropertySet pset, string prefix, DataNode node, ref int id)
{
string name = node.Name;
string newPrefix = prefix.Length > 0 ? prefix + "." + name: name;
@@ -460,15 +393,15 @@ namespace MonoDevelop.Projects.Formats.MSBuild
if (node is DataValue) {
DataValue val = (DataValue) node;
string value = EncodeString (val.Value);
- sw.WriteLine ("\t\t" + newPrefix + " = " + value);
+ pset.SetValue (newPrefix, value);
}
else {
DataItem it = (DataItem) node;
- sw.WriteLine ("\t\t" + newPrefix + " = $" + id);
+ pset.SetValue (newPrefix, "$" + id);
newPrefix = "$" + id;
id ++;
foreach (DataNode cn in it.ItemData)
- WriteDataNode (sw, newPrefix, cn, ref id);
+ WriteDataNode (pset, newPrefix, cn, ref id);
}
}
@@ -533,16 +466,14 @@ namespace MonoDevelop.Projects.Formats.MSBuild
return val;
}
- DataItem ReadDataItem (Section sec, List<string> lines)
- {
- return ReadDataItem (sec.Start, sec.Count, lines);
- }
-
- DataItem ReadDataItem (int start, int count, List<string> lines)
+ DataItem ReadDataItem (SlnSection sec)
{
DataItem it = new DataItem ();
- int lineNum = start + 1;
- int lastLine = start + count - 2;
+
+ var lines = sec.Properties.ToArray ();
+
+ int lineNum = 0;
+ int lastLine = lines.Length - 1;
while (lineNum <= lastLine) {
if (!ReadDataNode (it, lines, lastLine, "", ref lineNum))
lineNum++;
@@ -550,38 +481,26 @@ namespace MonoDevelop.Projects.Formats.MSBuild
return it;
}
- bool ReadDataNode (DataItem item, List<string> lines, int lastLine, string prefix, ref int lineNum)
+ bool ReadDataNode (DataItem item, KeyValuePair<string,string>[] lines, int lastLine, string prefix, ref int lineNum)
{
- string s = lines [lineNum].Trim (' ','\t');
-
- if (s.Length == 0) {
- lineNum++;
- return true;
- }
+ var s = lines [lineNum];
// Check if the line belongs to the current item
if (prefix.Length > 0) {
- if (!s.StartsWith (prefix + "."))
+ if (!s.Key.StartsWith (prefix + "."))
return false;
- s = s.Substring (prefix.Length + 1);
} else {
- if (s.StartsWith ("$"))
+ if (s.Key.StartsWith ("$"))
return false;
}
- int i = s.IndexOf ('=');
- if (i == -1) {
- lineNum++;
- return true;
- }
-
- string name = s.Substring (0, i).Trim (' ','\t');
+ string name = s.Key;
if (name.Length == 0) {
lineNum++;
return true;
}
- string value = s.Substring (i+1).Trim (' ','\t');
+ string value = s.Value;
if (value.StartsWith ("$")) {
// New item
DataItem child = new DataItem ();
@@ -629,7 +548,7 @@ namespace MonoDevelop.Projects.Formats.MSBuild
}
//Reader
- public object ReadFile (string fileName, MSBuildFileFormat format, IProgressMonitor monitor)
+ public async Task<object> ReadFile (string fileName, ProgressMonitor monitor)
{
if (fileName == null || monitor == null)
return null;
@@ -639,10 +558,10 @@ namespace MonoDevelop.Projects.Formats.MSBuild
ProjectExtensionUtil.BeginLoadOperation ();
sol = new Solution ();
monitor.BeginTask (string.Format (GettextCatalog.GetString ("Loading solution: {0}"), fileName), 1);
- var projectLoadMonitor = monitor as IProjectLoadProgressMonitor;
+ var projectLoadMonitor = monitor as ProjectLoadProgressMonitor;
if (projectLoadMonitor != null)
projectLoadMonitor.CurrentSolution = sol;
- LoadSolution (sol, fileName, format, monitor);
+ await Task.Factory.StartNew (() => LoadSolution (sol, fileName, monitor));
} catch (Exception ex) {
monitor.ReportError (GettextCatalog.GetString ("Could not load solution: {0}", fileName), ex);
throw;
@@ -653,129 +572,63 @@ namespace MonoDevelop.Projects.Formats.MSBuild
return sol;
}
- //ExtendedProperties
- // Per config
- // Platform : Eg. Any CPU
- // SolutionConfigurationPlatforms
- //
- SolutionFolder LoadSolution (Solution sol, string fileName, MSBuildFileFormat format, IProgressMonitor monitor)
+ SolutionFolder LoadSolution (Solution sol, string fileName, ProgressMonitor monitor)
{
- string headerComment;
- string version = GetSlnFileVersion (fileName, out headerComment);
-
- ListDictionary globals = null;
- SolutionFolder folder = null;
- SlnData data = null;
- List<Section> projectSections = null;
- List<string> lines = null;
-
FileFormat projectFormat = Services.ProjectService.FileFormats.GetFileFormat (format);
monitor.BeginTask (GettextCatalog.GetString ("Loading solution: {0}", fileName), 1);
- //Parse the .sln file
- using (StreamReader reader = new StreamReader(fileName)) {
- sol.FileName = fileName;
- sol.ConvertToFormat (projectFormat, false);
- folder = sol.RootFolder;
- sol.Version = "0.1"; //FIXME:
- data = new SlnData ();
- folder.ExtendedProperties [typeof (SlnFileFormat)] = data;
- data.VersionString = version;
- data.HeaderComment = headerComment;
-
- string s = null;
- projectSections = new List<Section> ();
- lines = new List<string> ();
- globals = new ListDictionary ();
- //Parse
- while (reader.Peek () >= 0) {
- s = GetNextLine (reader, lines).Trim ();
-
- if (String.Compare (s, "Global", StringComparison.OrdinalIgnoreCase) == 0) {
- ParseGlobal (reader, lines, globals);
- continue;
- }
-
- if (s.StartsWith ("Project", StringComparison.Ordinal)) {
- Section sec = new Section ();
- projectSections.Add (sec);
- sec.Start = lines.Count - 1;
+ var sln = new SlnFile ();
+ sln.Read (fileName);
- int e = ReadUntil ("EndProject", reader, lines);
- sec.Count = (e < 0) ? 1 : (e - sec.Start + 1);
+ sol.FileName = fileName;
+ sol.ConvertToFormat (projectFormat, false);
- continue;
- }
+ sol.ReadSolution (monitor, sln);
+ return sol.RootFolder;
+ }
- if (s.StartsWith ("VisualStudioVersion = ", StringComparison.Ordinal)) {
- Version v;
- if (Version.TryParse (s.Substring ("VisualStudioVersion = ".Length), out v))
- data.VisualStudioVersion = v;
- else
- monitor.Log.WriteLine ("Ignoring unparseable VisualStudioVersion value in sln file");
- }
+ internal void LoadSolution (Solution sol, SlnFile sln, ProgressMonitor monitor)
+ {
+ var version = sln.FormatVersion;
- if (s.StartsWith ("MinimumVisualStudioVersion = ", StringComparison.Ordinal)) {
- Version v;
- if (Version.TryParse (s.Substring ("MinimumVisualStudioVersion = ".Length), out v))
- data.MinimumVisualStudioVersion = v;
- else
- monitor.Log.WriteLine ("Ignoring unparseable MinimumVisualStudioVersion value in sln file");
- }
- }
- }
+ //Parse the .sln file
+ var folder = sol.RootFolder;
+ sol.Version = "0.1"; //FIXME:
- monitor.BeginTask("Loading projects ..", projectSections.Count + 1);
- Dictionary<string, SolutionItem> items = new Dictionary<string, SolutionItem> ();
- List<SolutionItem> sortedList = new List<SolutionItem> ();
- foreach (Section sec in projectSections) {
+ monitor.BeginTask("Loading projects ..", sln.Projects.Count + 1);
+ Dictionary<string, SolutionFolderItem> items = new Dictionary<string, SolutionFolderItem> ();
+ List<SolutionFolderItem> sortedList = new List<SolutionFolderItem> ();
+ foreach (SlnProject sec in sln.Projects) {
monitor.Step (1);
- Match match = ProjectRegex.Match (lines [sec.Start]);
- if (!match.Success) {
- LoggingService.LogDebug (GettextCatalog.GetString (
- "Invalid Project definition on line number #{0} in file '{1}'. Ignoring.",
- sec.Start + 1,
- fileName));
-
- continue;
- }
-
try {
// Valid guid?
- new Guid (match.Groups [1].Value);
+ new Guid (sec.TypeGuid);
} catch (FormatException) {
//Use default guid as projectGuid
LoggingService.LogDebug (GettextCatalog.GetString (
"Invalid Project type guid '{0}' on line #{1}. Ignoring.",
- match.Groups [1].Value,
- sec.Start + 1));
+ sec.Id,
+ sec.Line));
continue;
}
- string projTypeGuid = match.Groups [1].Value.ToUpper ();
- string projectName = match.Groups [2].Value;
- string projectPath = match.Groups [3].Value;
- string projectGuid = match.Groups [4].Value.ToUpper ();
- List<string> projLines;
+ string projTypeGuid = sec.TypeGuid.ToUpper ();
+ string projectName = sec.Name;
+ string projectPath = sec.FilePath;
+ string projectGuid = sec.Id;
if (projTypeGuid == MSBuildProjectService.FolderTypeGuid) {
//Solution folder
SolutionFolder sfolder = new SolutionFolder ();
sfolder.Name = projectName;
- MSBuildProjectService.InitializeItemHandler (sfolder);
- MSBuildProjectService.SetId (sfolder, projectGuid);
+ sfolder.ItemId = projectGuid;
- projLines = lines.GetRange (sec.Start + 1, sec.Count - 2);
- DeserializeSolutionItem (sol, sfolder, projLines);
+ DeserializeSolutionItem (sol, sfolder, sec);
- foreach (string f in ReadFolderFiles (projLines))
- sfolder.Files.Add (MSBuildProjectService.FromMSBuildPath (Path.GetDirectoryName (fileName), f));
+ foreach (string f in ReadFolderFiles (sec))
+ sfolder.Files.Add (MSBuildProjectService.FromMSBuildPath (Path.GetDirectoryName (sol.FileName), f));
- SlnData slnData = new SlnData ();
- slnData.Extra = projLines.ToArray ();
- sfolder.ExtendedProperties [typeof (SlnFileFormat)] = slnData;
-
items.Add (projectGuid, sfolder);
sortedList.Add (sfolder);
@@ -785,42 +638,38 @@ namespace MonoDevelop.Projects.Formats.MSBuild
if (projectPath.StartsWith("http://")) {
monitor.ReportWarning (GettextCatalog.GetString (
"{0}({1}): Projects with non-local source (http://...) not supported. '{2}'.",
- fileName, sec.Start + 1, projectPath));
- data.UnknownProjects.AddRange (lines.GetRange (sec.Start, sec.Count));
+ sol.FileName, sec.Line, projectPath));
continue;
}
- string path = MSBuildProjectService.FromMSBuildPath (Path.GetDirectoryName (fileName), projectPath);
+ string path = MSBuildProjectService.FromMSBuildPath (Path.GetDirectoryName (sol.FileName), projectPath);
if (String.IsNullOrEmpty (path)) {
monitor.ReportWarning (GettextCatalog.GetString (
- "Invalid project path found in {0} : {1}", fileName, projectPath));
+ "Invalid project path found in {0} : {1}", sol.FileName, projectPath));
LoggingService.LogWarning (GettextCatalog.GetString (
- "Invalid project path found in {0} : {1}", fileName, projectPath));
+ "Invalid project path found in {0} : {1}", sol.FileName, projectPath));
continue;
}
projectPath = Path.GetFullPath (path);
- SolutionEntityItem item = null;
+ SolutionItem item = null;
try {
if (sol.IsSolutionItemEnabled (projectPath)) {
- item = ProjectExtensionUtil.LoadSolutionItem (monitor, projectPath, delegate {
+ var t = ProjectExtensionUtil.LoadSolutionItem (monitor, projectPath, delegate {
return MSBuildProjectService.LoadItem (monitor, projectPath, format, projTypeGuid, projectGuid);
});
+ t.Wait ();
+ item = t.Result;
if (item == null) {
throw new UnknownSolutionItemTypeException (projTypeGuid);
}
} else {
- var uitem = new UnloadedSolutionItem () {
+ item = new UnloadedSolutionItem () {
FileName = projectPath
};
- var h = new MSBuildHandler (projTypeGuid, projectGuid) {
- Item = uitem,
- };
- uitem.SetItemHandler (h);
- item = uitem;
}
} catch (Exception e) {
@@ -837,7 +686,7 @@ namespace MonoDevelop.Projects.Formats.MSBuild
var relPath = new FilePath (path).ToRelative (sol.BaseDirectory);
if (!string.IsNullOrEmpty (name)) {
var guids = name.Split (';');
- var projectInfo = MSBuildProjectService.GetUnknownProjectTypeInfo (guids, fileName);
+ var projectInfo = MSBuildProjectService.GetUnknownProjectTypeInfo (guids, sol.FileName);
if (projectInfo != null) {
loadAsProject = projectInfo.LoadFiles;
LoggingService.LogWarning (string.Format ("Could not load {0} project '{1}'. {2}", projectInfo.Name, relPath, projectInfo.GetInstructions ()));
@@ -861,218 +710,143 @@ namespace MonoDevelop.Projects.Formats.MSBuild
"Error while trying to load the project '{0}': {1}", projectPath, e.Message));
}
- SolutionEntityItem uitem;
+ SolutionItem uitem;
if (loadAsProject) {
uitem = new UnknownProject () {
FileName = projectPath,
- LoadError = e.Message,
+ UnsupportedProjectMessage = e.Message,
};
} else {
uitem = new UnknownSolutionItem () {
FileName = projectPath,
- LoadError = e.Message,
+ UnsupportedProjectMessage = e.Message,
};
}
-
- var h = new MSBuildHandler (projTypeGuid, projectGuid) {
- Item = uitem,
- };
- uitem.SetItemHandler (h);
item = uitem;
}
- MSBuildHandler handler = (MSBuildHandler) item.ItemHandler;
- projLines = lines.GetRange (sec.Start + 1, sec.Count - 2);
- DataItem it = GetSolutionItemData (projLines);
+ item.UnresolvedProjectDependencies = ReadSolutionItemDependencies (sec);
- handler.UnresolvedProjectDependencies = ReadSolutionItemDependencies (projLines);
- handler.SlnProjectContent = projLines.ToArray ();
- handler.ReadSlnData (it);
+ // Deserialize the object
+ var ssec = sec.Sections.GetSection ("MonoDevelopProperties");
+ if (ssec != null) {
+ DataItem it = ReadDataItem (ssec);
+ item.ReadSlnData (it);
+ }
if (!items.ContainsKey (projectGuid)) {
items.Add (projectGuid, item);
sortedList.Add (item);
- data.ItemsByGuid [projectGuid] = item;
} else {
monitor.ReportError (GettextCatalog.GetString ("Invalid solution file. There are two projects with the same GUID. The project {0} will be ignored.", projectPath), null);
}
}
monitor.EndTask ();
- if (globals != null && globals.Contains ("NestedProjects")) {
- LoadNestedProjects (globals ["NestedProjects"] as Section, lines, items, monitor);
- globals.Remove ("NestedProjects");
- }
+ sol.LoadedProjects = new HashSet<string> (items.Keys);
+
+ var nested = sln.Sections.GetSection ("NestedProjects");
+ if (nested != null)
+ LoadNestedProjects (nested, items, monitor);
// Resolve project dependencies
- foreach (var it in items.OfType<SolutionEntityItem> ()) {
- MSBuildHandler handler = (MSBuildHandler) it.ItemHandler;
- if (handler.UnresolvedProjectDependencies != null) {
- foreach (var id in handler.UnresolvedProjectDependencies.ToArray ()) {
- SolutionItem dep;
- if (items.TryGetValue (id, out dep) && dep is SolutionEntityItem) {
- handler.UnresolvedProjectDependencies.Remove (id);
- it.ItemDependencies.Add ((SolutionEntityItem)dep);
+ foreach (var it in items.Values.OfType<SolutionItem> ()) {
+ if (it.UnresolvedProjectDependencies != null) {
+ foreach (var id in it.UnresolvedProjectDependencies.ToArray ()) {
+ SolutionFolderItem dep;
+ if (items.TryGetValue (id, out dep) && dep is SolutionItem) {
+ it.UnresolvedProjectDependencies.Remove (id);
+ it.ItemDependencies.Add ((SolutionItem)dep);
}
}
- if (handler.UnresolvedProjectDependencies.Count == 0)
- handler.UnresolvedProjectDependencies = null;
+ if (it.UnresolvedProjectDependencies.Count == 0)
+ it.UnresolvedProjectDependencies = null;
}
}
//Add top level folders and projects to the main folder
- foreach (SolutionItem ce in sortedList) {
+ foreach (SolutionFolderItem ce in sortedList) {
if (ce.ParentFolder == null)
folder.Items.Add (ce);
}
//FIXME: This can be just SolutionConfiguration also!
- if (globals != null) {
- if (globals.Contains ("SolutionConfigurationPlatforms")) {
- LoadSolutionConfigurations (globals ["SolutionConfigurationPlatforms"] as Section, lines,
- sol, monitor);
- globals.Remove ("SolutionConfigurationPlatforms");
- }
+ LoadSolutionConfigurations (sln.SolutionConfigurationsSection, sol, monitor);
- if (globals.Contains ("ProjectConfigurationPlatforms")) {
- LoadProjectConfigurationMappings (globals ["ProjectConfigurationPlatforms"] as Section, lines,
- sol, monitor);
- globals.Remove ("ProjectConfigurationPlatforms");
- }
+ LoadProjectConfigurationMappings (sln.ProjectConfigurationsSection, sol, items, monitor);
- if (globals.Contains ("MonoDevelopProperties")) {
- LoadMonoDevelopProperties (globals ["MonoDevelopProperties"] as Section, lines, sol, monitor);
- globals.Remove ("MonoDevelopProperties");
- }
-
- ArrayList toRemove = new ArrayList ();
- foreach (DictionaryEntry e in globals) {
- string name = (string) e.Key;
- if (name.StartsWith ("MonoDevelopProperties.")) {
- int i = name.IndexOf ('.');
- LoadMonoDevelopConfigurationProperties (name.Substring (i+1), (Section)e.Value, lines, sol, monitor);
- toRemove.Add (e.Key);
- }
+ LoadMonoDevelopProperties (sln.Sections.GetSection ("MonoDevelopProperties"), sol, monitor);
+
+ foreach (var e in sln.Sections) {
+ string name = e.Id;
+ if (name.StartsWith ("MonoDevelopProperties.")) {
+ int i = name.IndexOf ('.');
+ LoadMonoDevelopConfigurationProperties (name.Substring (i+1), e, sol, monitor);
}
- foreach (object key in toRemove)
- globals.Remove (key);
}
- //Save the global sections that we dont use
- List<string> globalLines = new List<string> ();
- foreach (Section sec in globals.Values)
- globalLines.InsertRange (globalLines.Count, lines.GetRange (sec.Start, sec.Count));
-
- data.GlobalExtra = globalLines;
monitor.EndTask ();
-
- // When reloading a project, keep the solution data and item id
- sol.SolutionItemAdded += delegate(object sender, SolutionItemChangeEventArgs e) {
- if (e.Reloading) {
- ItemSlnData.TransferData (e.ReplacedItem, e.SolutionItem);
- var ih = e.SolutionItem.ItemHandler as MSBuildHandler;
- if (ih != null)
- ih.ItemId = e.ReplacedItem.ItemId;
- }
- };
-
- return folder;
}
- void ParseGlobal (StreamReader reader, List<string> lines, ListDictionary dict)
+ void LoadProjectConfigurationMappings (SlnPropertySetCollection sets, Solution sln, Dictionary<string, SolutionFolderItem> items, ProgressMonitor monitor)
{
- //Process GlobalSection-s
- while (reader.Peek () >= 0) {
- string s = GetNextLine (reader, lines).Trim ();
- if (s.Length == 0)
- //Skip blank lines
- continue;
-
- Match m = GlobalSectionRegex.Match (s);
- if (!m.Success) {
- if (String.Compare (s, "EndGlobal", true) == 0)
- return;
-
- continue;
- }
-
- Section sec = new Section (m.Groups [1].Value, m.Groups [2].Value, lines.Count - 1, 1);
- dict [sec.Key] = sec;
-
- sec.Count = ReadUntil ("EndGlobalSection", reader, lines) - sec.Start + 1;
- //FIXME: sec.Count == -1 : No EndGlobalSection found, ignore entry?
- }
- }
-
- void LoadProjectConfigurationMappings (Section sec, List<string> lines, Solution sln, IProgressMonitor monitor)
- {
- if (sec == null || String.Compare (sec.Val, "postSolution", true) != 0)
+ if (sets == null)
return;
Dictionary<string, SolutionConfigurationEntry> cache = new Dictionary<string, SolutionConfigurationEntry> ();
Dictionary<string, string> ignoredProjects = new Dictionary<string, string> ();
- SlnData slnData = GetSlnData (sln.RootFolder);
-
- List<string> extras = new List<string> ();
- for (int i = 0; i < sec.Count - 2; i ++) {
- int lineNum = i + sec.Start + 1;
- string s = lines [lineNum].Trim ();
- extras.Add (s);
-
- //Format:
- // {projectGuid}.SolutionConfigName|SolutionPlatform.ActiveCfg = ProjConfigName|ProjPlatform
- // {projectGuid}.SolutionConfigName|SolutionPlatform.Build.0 = ProjConfigName|ProjPlatform
- // {projectGuid}.SolutionConfigName|SolutionPlatform.Deploy.0 = ProjConfigName|ProjPlatform
+ foreach (var pset in sets) {
+
+ var projGuid = pset.Id;
+
+ if (!items.ContainsKey (projGuid)) {
+ if (ignoredProjects.ContainsKey (projGuid))
+ // already warned
+ continue;
- string [] parts = s.Split (new char [] {'='}, 2);
- if (parts.Length < 2) {
- LoggingService.LogDebug ("{0} ({1}) : Invalid format. Ignoring", sln.FileName, lineNum + 1);
+ LoggingService.LogWarning (GettextCatalog.GetString ("{0} ({1}) : Project with guid = '{2}' not found or not loaded. Ignoring",
+ sln.FileName, pset.Line + 1, projGuid));
+ ignoredProjects [projGuid] = projGuid;
continue;
}
- string action;
- string projConfig = parts [1].Trim ();
-
- string left = parts [0].Trim ();
- if (left.EndsWith (".ActiveCfg")) {
- action = "ActiveCfg";
- left = left.Substring (0, left.Length - 10);
- } else if (left.EndsWith (".Build.0")) {
- action = "Build.0";
- left = left.Substring (0, left.Length - 8);
- } else if (left.EndsWith (".Deploy.0")) {
- action = "Deploy.0";
- left = left.Substring (0, left.Length - 9);
- } else {
- LoggingService.LogWarning (GettextCatalog.GetString ("{0} ({1}) : Unknown action. Only ActiveCfg, Build.0 and Deploy.0 supported.",
- sln.FileName, lineNum + 1));
+ SolutionFolderItem it;
+ if (!items.TryGetValue (projGuid, out it))
continue;
- }
- string [] t = left.Split (new char [] {'.'}, 2);
- if (t.Length < 2) {
- LoggingService.LogDebug ("{0} ({1}) : Invalid format of the left side. Ignoring",
- sln.FileName, lineNum + 1);
+ SolutionItem item = it as SolutionItem;
+
+ if (item == null || !item.SupportsConfigurations ())
continue;
- }
- string projGuid = t [0].ToUpper ();
- string slnConfig = t [1];
+ //Format:
+ // {projectGuid}.SolutionConfigName|SolutionPlatform.ActiveCfg = ProjConfigName|ProjPlatform
+ // {projectGuid}.SolutionConfigName|SolutionPlatform.Build.0 = ProjConfigName|ProjPlatform
+ // {projectGuid}.SolutionConfigName|SolutionPlatform.Deploy.0 = ProjConfigName|ProjPlatform
- if (!slnData.ItemsByGuid.ContainsKey (projGuid)) {
- if (ignoredProjects.ContainsKey (projGuid))
- // already warned
+ foreach (var prop in pset) {
+ string action;
+ string projConfig = prop.Value;
+
+ string left = prop.Key;
+ if (left.EndsWith (".ActiveCfg")) {
+ action = "ActiveCfg";
+ left = left.Substring (0, left.Length - 10);
+ } else if (left.EndsWith (".Build.0")) {
+ action = "Build.0";
+ left = left.Substring (0, left.Length - 8);
+ } else if (left.EndsWith (".Deploy.0")) {
+ action = "Deploy.0";
+ left = left.Substring (0, left.Length - 9);
+ } else {
+ LoggingService.LogWarning (GettextCatalog.GetString ("{0} ({1}) : Unknown action. Only ActiveCfg, Build.0 and Deploy.0 supported.",
+ sln.FileName, pset.Line));
continue;
+ }
- LoggingService.LogWarning (GettextCatalog.GetString ("{0} ({1}) : Project with guid = '{2}' not found or not loaded. Ignoring",
- sln.FileName, lineNum + 1, projGuid));
- ignoredProjects [projGuid] = projGuid;
- continue;
- }
+ string slnConfig = left;
- SolutionEntityItem item;
- if (slnData.ItemsByGuid.TryGetValue (projGuid, out item) && (item.SupportsBuild () || item is UnloadedSolutionItem)) {
string key = projGuid + "." + slnConfig;
SolutionConfigurationEntry combineConfigEntry = null;
if (cache.ContainsKey (key)) {
@@ -1092,6 +866,7 @@ namespace MonoDevelop.Projects.Formats.MSBuild
* if Build (true/false) for the project will
* will depend on presence/absence of Build.0 entry
*/
+
if (action == "ActiveCfg") {
combineConfigEntry.ItemConfiguration = FromSlnConfigurationId (projConfig);
} else if (action == "Build.0") {
@@ -1100,15 +875,12 @@ namespace MonoDevelop.Projects.Formats.MSBuild
combineConfigEntry.Deploy = true;
}
}
- extras.RemoveAt (extras.Count - 1);
}
-
- slnData.SectionExtras ["ProjectConfigurationPlatforms"] = extras;
}
/* Gets the CombineConfigurationEntry corresponding to the @entry in its parentCombine's
* CombineConfiguration. Creates the required bits if not present */
- SolutionConfigurationEntry GetConfigEntry (Solution sol, SolutionEntityItem item, string configName)
+ SolutionConfigurationEntry GetConfigEntry (Solution sol, SolutionItem item, string configName)
{
configName = FromSlnConfigurationId (configName);
@@ -1124,21 +896,13 @@ namespace MonoDevelop.Projects.Formats.MSBuild
return solutionConfig.AddItem (item);
}
- void LoadSolutionConfigurations (Section sec, List<string> lines, Solution solution, IProgressMonitor monitor)
+ void LoadSolutionConfigurations (SlnPropertySet sec, Solution solution, ProgressMonitor monitor)
{
- if (sec == null || String.Compare (sec.Val, "preSolution", true) != 0)
+ if (sec == null)
return;
- for (int i = 0; i < sec.Count - 2; i ++) {
- //FIXME: expects both key and val to be on the same line
- int lineNum = i + sec.Start + 1;
- string s = lines [lineNum].Trim ();
- if (s.Length == 0)
- //Skip blank lines
- continue;
+ foreach (var pair in sec) {
- KeyValuePair<string, string> pair = SplitKeyValue (s);
-
string configId = FromSlnConfigurationId (pair.Key);
SolutionConfiguration config = solution.Configurations [configId];
@@ -1154,37 +918,37 @@ namespace MonoDevelop.Projects.Formats.MSBuild
return new SolutionConfiguration (fullId);
}
- void LoadMonoDevelopProperties (Section sec, List<string> lines, Solution sln, IProgressMonitor monitor)
+ void LoadMonoDevelopProperties (SlnSection sec, Solution sln, ProgressMonitor monitor)
{
- DataItem it = ReadDataItem (sec, lines);
+ if (sec == null)
+ return;
+ DataItem it = ReadDataItem (sec);
MSBuildSerializer ser = new MSBuildSerializer (sln.FileName);
ser.SerializationContext.BaseFile = sln.FileName;
ser.Deserialize (sln, it);
}
- void LoadMonoDevelopConfigurationProperties (string configName, Section sec, List<string> lines, Solution sln, IProgressMonitor monitor)
+ void LoadMonoDevelopConfigurationProperties (string configName, SlnSection sec, Solution sln, ProgressMonitor monitor)
{
SolutionConfiguration config = sln.Configurations [configName];
if (config == null)
return;
- DataItem it = ReadDataItem (sec, lines);
+ DataItem it = ReadDataItem (sec);
MSBuildSerializer ser = new MSBuildSerializer (sln.FileName);
ser.Deserialize (config, it);
}
- void LoadNestedProjects (Section sec, List<string> lines,
- IDictionary<string, SolutionItem> entries, IProgressMonitor monitor)
+ void LoadNestedProjects (SlnSection sec, IDictionary<string, SolutionFolderItem> entries, ProgressMonitor monitor)
{
- if (sec == null || String.Compare (sec.Val, "preSolution", true) != 0)
+ if (sec == null || String.Compare (sec.SectionType, "preSolution", StringComparison.OrdinalIgnoreCase) != 0)
return;
- for (int i = 0; i < sec.Count - 2; i ++) {
+ foreach (var kvp in sec.Properties) {
// Guids should be upper case for VS compatibility
- KeyValuePair<string, string> pair = SplitKeyValue (lines [i + sec.Start + 1].Trim ());
- pair = new KeyValuePair<string, string> (pair.Key.ToUpper (), pair.Value.ToUpper ());
+ var pair = new KeyValuePair<string, string> (kvp.Key.ToUpper (), kvp.Value.ToUpper ());
- SolutionItem folderItem;
- SolutionItem item;
+ SolutionFolderItem folderItem;
+ SolutionFolderItem item;
if (!entries.TryGetValue (pair.Value, out folderItem)) {
//Container not found
@@ -1232,17 +996,6 @@ namespace MonoDevelop.Projects.Formats.MSBuild
}
- KeyValuePair<string, string> SplitKeyValue (string s)
- {
- string [] pair = s.Split (new char [] {'='}, 2);
- string key = pair [0].Trim ();
- string val = String.Empty;
- if (pair.Length == 2)
- val = pair [1].Trim ();
-
- return new KeyValuePair<string, string> (key, val);
- }
-
// Utility function to determine the sln file version
string GetSlnFileVersion(string strInSlnFile, out string headerComment)
{
@@ -1276,32 +1029,6 @@ namespace MonoDevelop.Projects.Formats.MSBuild
return strVersion;
}
- static SlnData GetSlnData (SolutionItem c)
- {
- if (c.ExtendedProperties.Contains (typeof (SlnFileFormat)))
- return c.ExtendedProperties [typeof (SlnFileFormat)] as SlnData;
- return null;
- }
-
- // static regexes
- static Regex projectRegex = null;
- internal static Regex ProjectRegex {
- get {
- if (projectRegex == null)
- projectRegex = new Regex(@"Project\(""(\{[^}]*\})""\) = ""(.*)"", ""(.*)"", ""(\{[^{]*\})""");
- return projectRegex;
- }
- }
-
- static Regex globalSectionRegex = null;
- static Regex GlobalSectionRegex {
- get {
- if (globalSectionRegex == null)
- globalSectionRegex = new Regex (@"GlobalSection\s*\(([^)]*)\)\s*=\s*(\w*)");
- return globalSectionRegex;
- }
- }
-
static Regex slnVersionRegex = null;
internal static Regex SlnVersionRegex {
get {