void WriteFileInternal (string file, string sourceFile, Solution solution, bool saveProjects, ProgressMonitor monitor) { if (saveProjects) { var items = solution.GetAllSolutionItems ().ToArray (); monitor.BeginTask (items.Length + 1); foreach (var item in items) { try { monitor.BeginStep (); item.SavingSolution = true; item.SaveAsync (monitor).Wait (); } finally { item.SavingSolution = false; } } } else { monitor.BeginTask (1); monitor.BeginStep (); } SlnFile sln = new SlnFile (); sln.FileName = file; 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); } } sln.FormatVersion = format.SlnVersion; // Don't modify the product description if it already has a value if (string.IsNullOrEmpty (sln.ProductDescription)) sln.ProductDescription = format.ProductDescription; solution.WriteSolution (monitor, sln); sln.Write (file); monitor.EndTask (); }
void WriteProjectConfigurations (Solution sol, SlnFile sln) { var col = sln.ProjectConfigurationsSection; foreach (var item in sol.GetAllSolutionItems ()) { // Don't save configurations for shared projects if (!item.SupportsConfigurations ()) 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 = item.ItemId; if (!itemGuid.StartsWith ("{") && !itemGuid.EndsWith ("}")) itemGuid = "{" + itemGuid + "}"; var pset = col.GetOrCreatePropertySet (itemGuid, ignoreCase:true); var existingKeys = new HashSet<string> (pset.Keys); foreach (SolutionConfiguration cc in sol.Configurations) { var cce = cc.GetEntryForItem (item); if (cce == null) continue; var configId = ToSlnConfigurationId (cc); var itemConfigId = ToSlnConfigurationId (cce.ItemConfiguration); string key; pset.SetValue (key = configId + ".ActiveCfg", itemConfigId); existingKeys.Remove (key); if (cce.Build) { pset.SetValue (key = configId + ".Build.0", itemConfigId); existingKeys.Remove (key); } if (cce.Deploy) { pset.SetValue (key = configId + ".Deploy.0", itemConfigId); existingKeys.Remove (key); } } foreach (var k in existingKeys) pset.Remove (k); } }
internal void LoadSolution (Solution sol, SlnFile sln, ProgressMonitor monitor, SolutionLoadContext ctx) { var version = sln.FormatVersion; //Parse the .sln file var folder = sol.RootFolder; sol.Version = "0.1"; //FIXME: monitor.BeginTask("Loading projects ..", sln.Projects.Count + 1); Dictionary<string, SolutionFolderItem> items = new Dictionary<string, SolutionFolderItem> (); List<string> sortedList = new List<string> (); List<Task> loadTasks = new List<Task> (); foreach (SlnProject sec in sln.Projects) { try { // Valid guid? new Guid (sec.TypeGuid); } catch (FormatException) { monitor.Step (1); //Use default guid as projectGuid LoggingService.LogDebug (GettextCatalog.GetString ( "Invalid Project type guid '{0}' on line #{1}. Ignoring.", sec.Id, sec.Line)); continue; } string projTypeGuid = sec.TypeGuid.ToUpper (); string projectName = sec.Name; string projectPath = sec.FilePath; string projectGuid = sec.Id; lock (items) sortedList.Add (projectGuid); if (projTypeGuid == MSBuildProjectService.FolderTypeGuid) { //Solution folder SolutionFolder sfolder = new SolutionFolder (); sfolder.Name = projectName; sfolder.ItemId = projectGuid; DeserializeSolutionItem (monitor, sol, sfolder, sec); foreach (string f in ReadFolderFiles (sec)) sfolder.Files.Add (MSBuildProjectService.FromMSBuildPath (Path.GetDirectoryName (sol.FileName), f)); lock (items) items.Add (projectGuid, sfolder); monitor.Step (1); continue; } if (projectPath.StartsWith("http://")) { monitor.ReportWarning (GettextCatalog.GetString ( "{0}({1}): Projects with non-local source (http://...) not supported. '{2}'.", sol.FileName, sec.Line, projectPath)); monitor.Step (1); continue; } string path = MSBuildProjectService.FromMSBuildPath (Path.GetDirectoryName (sol.FileName), projectPath); if (String.IsNullOrEmpty (path)) { monitor.ReportWarning (GettextCatalog.GetString ( "Invalid project path found in {0} : {1}", sol.FileName, projectPath)); LoggingService.LogWarning (GettextCatalog.GetString ( "Invalid project path found in {0} : {1}", sol.FileName, projectPath)); monitor.Step (1); continue; } projectPath = Path.GetFullPath (path); SolutionItem item = null; Task<SolutionItem> loadTask; DateTime ti = DateTime.Now; if (sol.IsSolutionItemEnabled (projectPath)) { loadTask = Services.ProjectService.ReadSolutionItem (monitor, projectPath, format, projTypeGuid, projectGuid, ctx); } else { loadTask = Task.FromResult<SolutionItem> (new UnloadedSolutionItem () { FileName = projectPath }); } var ft = loadTask.ContinueWith (ta => { try { item = ta.Result; if (item == null) throw new UnknownSolutionItemTypeException (projTypeGuid); } catch (Exception cex) { var e = UnwrapException (cex).First (); string unsupportedMessage = e.Message; if (e is UserException) { var ex = (UserException) e; LoggingService.LogError ("{0}: {1}", ex.Message, ex.Details); monitor.ReportError (string.Format ("{0}{1}{1}{2}", ex.Message, Environment.NewLine, ex.Details), null); } else { LoggingService.LogError (string.Format ("Error while trying to load the project {0}", projectPath), e); monitor.ReportWarning (GettextCatalog.GetString ( "Error while trying to load the project '{0}': {1}", projectPath, e.Message)); } SolutionItem uitem; uitem = new UnknownSolutionItem () { FileName = projectPath, LoadError = unsupportedMessage, }; item = uitem; item.ItemId = projectGuid; item.TypeGuid = projTypeGuid; } item.UnresolvedProjectDependencies = ReadSolutionItemDependencies (sec); // Deserialize the object DeserializeSolutionItem (monitor, sol, item, sec); lock (items) { if (!items.ContainsKey (projectGuid)) { items.Add (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.Step (1); }); loadTasks.Add (ft); } Task.WaitAll (loadTasks.ToArray ()); 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.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 (it.UnresolvedProjectDependencies.Count == 0) it.UnresolvedProjectDependencies = null; } } //Add top level folders and projects to the main folder foreach (string id in sortedList) { SolutionFolderItem ce; if (items.TryGetValue (id, out ce) && ce.ParentFolder == null) folder.Items.Add (ce); } //FIXME: This can be just SolutionConfiguration also! LoadSolutionConfigurations (sln.SolutionConfigurationsSection, sol, monitor); LoadProjectConfigurationMappings (sln.ProjectConfigurationsSection, sol, items, 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); } } monitor.EndTask (); }
internal void WriteFileInternal (SlnFile sln, Solution solution, ProgressMonitor monitor) { SolutionFolder c = solution.RootFolder; // 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 the projects using (monitor.BeginTask (GettextCatalog.GetString ("Saving projects"), 1)) { monitor.BeginStep (); WriteProjects (c, sln, monitor, unknownProjects); } //FIXME: SolutionConfigurations? var pset = sln.SolutionConfigurationsSection; foreach (SolutionConfiguration config in solution.Configurations) { var cid = ToSlnConfigurationId (config); pset.SetValue (cid, cid); } WriteProjectConfigurations (solution, sln); //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", SlnSectionType.PreProcess); foreach (SolutionFolder folder in folders) { if (folder.IsRoot) continue; WriteNestedProjects (folder, solution.RootFolder, sec); } // 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 for configurations foreach (SolutionConfiguration conf in solution.Configurations) { string secId = "MonoDevelopProperties." + conf.Id; var sec = sln.Sections.GetOrCreateSection (secId, SlnSectionType.PreProcess); solution.WriteConfigurationData (monitor, sec.Properties, conf); if (sec.IsEmpty) sln.Sections.Remove (sec); } }
void WriteProjects (SolutionFolder folder, SlnFile sln, ProgressMonitor monitor, HashSet<string> unknownProjects) { monitor.BeginTask (folder.Items.Count); foreach (SolutionFolderItem ce in folder.Items.ToArray ()) { monitor.BeginStep (); if (ce is SolutionItem) { SolutionItem item = (SolutionItem) ce; 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 ('/', '\\'); var sec = proj.Sections.GetOrCreateSection ("MonoDevelopProperties", SlnSectionType.PreProcess); sec.SkipIfEmpty = true; folder.ParentSolution.WriteSolutionFolderItemData (monitor, sec.Properties, ce); if (item.ItemDependencies.Count > 0) { sec = proj.Sections.GetOrCreateSection ("ProjectDependencies", SlnSectionType.PostProcess); sec.Properties.ClearExcept (unknownProjects); foreach (var dep in item.ItemDependencies) sec.Properties.SetValue (dep.ItemId, dep.ItemId); } else proj.Sections.RemoveSection ("ProjectDependencies"); } else if (ce is SolutionFolder) { var proj = sln.Projects.GetOrCreateProject (ce.ItemId); proj.TypeGuid = MSBuildProjectService.FolderTypeGuid; proj.Name = ce.Name; proj.FilePath = ce.Name; // Folder files WriteFolderFiles (proj, (SolutionFolder) ce); //Write custom properties var sec = proj.Sections.GetOrCreateSection ("MonoDevelopProperties", SlnSectionType.PreProcess); sec.SkipIfEmpty = true; folder.ParentSolution.WriteSolutionFolderItemData (monitor, sec.Properties, ce); } if (ce is SolutionFolder) WriteProjects (ce as SolutionFolder, sln, monitor, unknownProjects); } monitor.EndTask (); }
internal protected virtual void OnWriteSolution (ProgressMonitor monitor, SlnFile file) { var secAttribute = (SolutionDataSectionAttribute) Attribute.GetCustomAttribute (GetType(), typeof(SolutionDataSectionAttribute)); if (secAttribute != null && secAttribute.ProcessOrder == SlnSectionType.PreProcess) { var sec = file.Sections.GetOrCreateSection (secAttribute.SectionName, SlnSectionType.PreProcess); sec.SkipIfEmpty = true; sec.WriteObjectProperties (this); } next.OnWriteSolution (monitor, file); if (secAttribute != null && secAttribute.ProcessOrder == SlnSectionType.PostProcess) { var sec = file.Sections.GetOrCreateSection (secAttribute.SectionName, SlnSectionType.PostProcess); sec.SkipIfEmpty = true; sec.WriteObjectProperties (this); } }
internal protected virtual void OnReadSolution (ProgressMonitor monitor, SlnFile file) { var secAttribute = (SolutionDataSectionAttribute) Attribute.GetCustomAttribute (GetType(), typeof(SolutionDataSectionAttribute)); if (secAttribute != null && secAttribute.ProcessOrder == SlnSectionType.PreProcess) { var sec = file.Sections.GetSection (secAttribute.SectionName, SlnSectionType.PreProcess); if (sec != null) sec.ReadObjectProperties (this); } next.OnReadSolution (monitor, file); if (secAttribute != null && secAttribute.ProcessOrder == SlnSectionType.PostProcess) { var sec = file.Sections.GetSection (secAttribute.SectionName, SlnSectionType.PostProcess); if (sec != null) sec.ReadObjectProperties (this); } }
public async Task SaveSolutionAfterChangingCSharpFormattingPolicyForTheFirstTime () { string dir = Util.CreateTmpDir ("FormattingPolicyChangedOnce"); var pset = PolicyService.GetPolicySet ("Mono"); var monoFormattingPolicy = pset.Get<CSharpFormattingPolicy> ("text/x-csharp"); var formattingPolicy = monoFormattingPolicy.Clone (); var solution = new Solution (); solution.Policies.Set (formattingPolicy); bool expectedSetting = !formattingPolicy.IndentSwitchCaseSection; formattingPolicy.IndentSwitchCaseSection = expectedSetting; string fileName = Path.Combine (dir, "FormattingPolicyChangedOnce.sln"); await solution.SaveAsync (fileName, Util.GetMonitor ()); var file = new SlnFile (); file.Read (fileName); var s = file.Sections.GetSection ("MonoDevelopProperties", SlnSectionType.PreProcess); var missingItem = default(KeyValuePair<string, string>); Assert.AreEqual (expectedSetting.ToString (), s.Properties.SingleOrDefault (p => p.Key.Contains ("IndentSwitchCaseSection")).Value); Assert.AreEqual (missingItem, s.Properties.SingleOrDefault (p => p.Key.Contains ("IndentSwitchSection"))); Assert.AreEqual (missingItem, s.Properties.SingleOrDefault (p => p.Key.Contains ("IndentBlock"))); Assert.AreEqual (missingItem, s.Properties.SingleOrDefault (p => p.Key.Contains ("SpaceBeforeDot"))); Assert.AreEqual (missingItem, s.Properties.SingleOrDefault (p => p.Key.Contains ("NewLineForElse"))); }
public static bool RemoveProject(this SlnFile slnFile, string projectPath) { if (string.IsNullOrEmpty(projectPath)) { throw new ArgumentException(); } var projectPathNormalized = PathUtility.GetPathWithDirectorySeparator(projectPath); var projectsToRemove = slnFile.Projects.Where((p) => string.Equals(p.FilePath, projectPathNormalized, StringComparison.OrdinalIgnoreCase)).ToList(); bool projectRemoved = false; if (projectsToRemove.Count == 0) { Reporter.Output.WriteLine(string.Format( CommonLocalizableStrings.ProjectNotFoundInTheSolution, projectPath)); } else { foreach (var slnProject in projectsToRemove) { var buildConfigsToRemove = slnFile.ProjectConfigurationsSection.GetPropertySet(slnProject.Id); if (buildConfigsToRemove != null) { slnFile.ProjectConfigurationsSection.Remove(buildConfigsToRemove); } var nestedProjectsSection = slnFile.Sections.GetSection( "NestedProjects", SlnSectionType.PreProcess); if (nestedProjectsSection != null && nestedProjectsSection.Properties.ContainsKey(slnProject.Id)) { nestedProjectsSection.Properties.Remove(slnProject.Id); } slnFile.Projects.Remove(slnProject); Reporter.Output.WriteLine( string.Format(CommonLocalizableStrings.ProjectRemovedFromTheSolution, slnProject.FilePath)); } foreach (var project in slnFile.Projects) { var dependencies = project.Dependencies; if (dependencies == null) { continue; } dependencies.SkipIfEmpty = true; foreach (var removed in projectsToRemove) { dependencies.Properties.Remove(removed.Id); } } projectRemoved = true; } return(projectRemoved); }
public static VisualStudioSolution Load(string fileName) { return(new VisualStudioSolution(SlnFile.Read(fileName))); }
public void WhenGivenAValidSlnFileItReadsAndVerifiesContents() { var tmpFile = CreateFile(); File.WriteAllText(tmpFile, SolutionWithAppAndLibProjects); SlnFile slnFile = SlnFile.Read(tmpFile); Console.WriteLine(new { slnFile_FormatVersion = slnFile.FormatVersion, slnFile_ProductDescription = slnFile.ProductDescription, slnFile_VisualStudioVersion = slnFile.VisualStudioVersion, slnFile_MinimumVisualStudioVersion = slnFile.MinimumVisualStudioVersion, slnFile_BaseDirectory = slnFile.BaseDirectory, slnFile_FullPath = slnFile.FullPath, tmpFilePath = tmpFile }.ToString()); slnFile.FormatVersion.Should().Be("12.00"); slnFile.ProductDescription.Should().Be("Visual Studio 15"); slnFile.VisualStudioVersion.Should().Be("15.0.26006.2"); slnFile.MinimumVisualStudioVersion.Should().Be("10.0.40219.1"); slnFile.BaseDirectory.Should().Be(Path.GetDirectoryName(tmpFile)); slnFile.FullPath.Should().Be(Path.GetFullPath(tmpFile)); slnFile.Projects.Count.Should().Be(2); var project = slnFile.Projects[0]; project.Id.Should().Be("{7072A694-548F-4CAE-A58F-12D257D5F486}"); project.TypeGuid.Should().Be("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"); project.Name.Should().Be("App"); project.FilePath.Should().Be(Path.Combine("App", "App.csproj")); project = slnFile.Projects[1]; project.Id.Should().Be("{21D9159F-60E6-4F65-BC6B-D01B71B15FFC}"); project.TypeGuid.Should().Be("{13B669BE-BB05-4DDF-9536-439F39A36129}"); project.Name.Should().Be("Lib"); project.FilePath.Should().Be(Path.Combine("..", "Lib", "Lib.csproj")); slnFile.SolutionConfigurationsSection.Count.Should().Be(6); slnFile.SolutionConfigurationsSection .GetValue("Debug|Any CPU", string.Empty) .Should().Be("Debug|Any CPU"); slnFile.SolutionConfigurationsSection .GetValue("Debug|x64", string.Empty) .Should().Be("Debug|x64"); slnFile.SolutionConfigurationsSection .GetValue("Debug|x86", string.Empty) .Should().Be("Debug|x86"); slnFile.SolutionConfigurationsSection .GetValue("Release|Any CPU", string.Empty) .Should().Be("Release|Any CPU"); slnFile.SolutionConfigurationsSection .GetValue("Release|x64", string.Empty) .Should().Be("Release|x64"); slnFile.SolutionConfigurationsSection .GetValue("Release|x86", string.Empty) .Should().Be("Release|x86"); slnFile.ProjectConfigurationsSection.Count.Should().Be(2); var projectConfigSection = slnFile .ProjectConfigurationsSection .GetPropertySet("{7072A694-548F-4CAE-A58F-12D257D5F486}"); projectConfigSection.Count.Should().Be(12); projectConfigSection .GetValue("Debug|Any CPU.ActiveCfg", string.Empty) .Should().Be("Debug|Any CPU"); projectConfigSection .GetValue("Debug|Any CPU.Build.0", string.Empty) .Should().Be("Debug|Any CPU"); projectConfigSection .GetValue("Debug|x64.ActiveCfg", string.Empty) .Should().Be("Debug|x64"); projectConfigSection .GetValue("Debug|x64.Build.0", string.Empty) .Should().Be("Debug|x64"); projectConfigSection .GetValue("Debug|x86.ActiveCfg", string.Empty) .Should().Be("Debug|x86"); projectConfigSection .GetValue("Debug|x86.Build.0", string.Empty) .Should().Be("Debug|x86"); projectConfigSection .GetValue("Release|Any CPU.ActiveCfg", string.Empty) .Should().Be("Release|Any CPU"); projectConfigSection .GetValue("Release|Any CPU.Build.0", string.Empty) .Should().Be("Release|Any CPU"); projectConfigSection .GetValue("Release|x64.ActiveCfg", string.Empty) .Should().Be("Release|x64"); projectConfigSection .GetValue("Release|x64.Build.0", string.Empty) .Should().Be("Release|x64"); projectConfigSection .GetValue("Release|x86.ActiveCfg", string.Empty) .Should().Be("Release|x86"); projectConfigSection .GetValue("Release|x86.Build.0", string.Empty) .Should().Be("Release|x86"); projectConfigSection = slnFile .ProjectConfigurationsSection .GetPropertySet("{21D9159F-60E6-4F65-BC6B-D01B71B15FFC}"); projectConfigSection.Count.Should().Be(12); projectConfigSection .GetValue("Debug|Any CPU.ActiveCfg", string.Empty) .Should().Be("Debug|Any CPU"); projectConfigSection .GetValue("Debug|Any CPU.Build.0", string.Empty) .Should().Be("Debug|Any CPU"); projectConfigSection .GetValue("Debug|x64.ActiveCfg", string.Empty) .Should().Be("Debug|x64"); projectConfigSection .GetValue("Debug|x64.Build.0", string.Empty) .Should().Be("Debug|x64"); projectConfigSection .GetValue("Debug|x86.ActiveCfg", string.Empty) .Should().Be("Debug|x86"); projectConfigSection .GetValue("Debug|x86.Build.0", string.Empty) .Should().Be("Debug|x86"); projectConfigSection .GetValue("Release|Any CPU.ActiveCfg", string.Empty) .Should().Be("Release|Any CPU"); projectConfigSection .GetValue("Release|Any CPU.Build.0", string.Empty) .Should().Be("Release|Any CPU"); projectConfigSection .GetValue("Release|x64.ActiveCfg", string.Empty) .Should().Be("Release|x64"); projectConfigSection .GetValue("Release|x64.Build.0", string.Empty) .Should().Be("Release|x64"); projectConfigSection .GetValue("Release|x86.ActiveCfg", string.Empty) .Should().Be("Release|x86"); projectConfigSection .GetValue("Release|x86.Build.0", string.Empty) .Should().Be("Release|x86"); slnFile.Sections.Count.Should().Be(3); var solutionPropertiesSection = slnFile.Sections.GetSection("SolutionProperties"); solutionPropertiesSection.Properties.Count.Should().Be(1); solutionPropertiesSection.Properties .GetValue("HideSolutionNode", string.Empty) .Should().Be("FALSE"); }
public IEnumerable <ProjectDependency> ResolveProjectDependencies(string projectDir, string xprojFile = null, SlnFile solutionFile = null) { var projectContexts = ProjectContext.CreateContextForEachFramework(projectDir); xprojFile = xprojFile ?? FindXprojFile(projectDir); ProjectRootElement xproj = null; if (xprojFile != null) { xproj = ProjectRootElement.Open(xprojFile); } return(ResolveProjectDependencies( projectContexts, ResolveXProjProjectDependencyNames(xproj), solutionFile)); }