Example #1
0
        public async Task <SolutionFolderItem> ReloadItem(ProgressMonitor monitor, SolutionFolderItem sitem)
        {
            if (Items.IndexOf(sitem) == -1)
            {
                throw new InvalidOperationException("Solution item '" + sitem.Name + "' does not belong to folder '" + Name + "'");
            }

            SolutionItem item = sitem as SolutionItem;

            if (item != null)
            {
                // Load the new item

                SolutionItem newItem;
                try {
                    if (ParentSolution.IsSolutionItemEnabled(item.FileName))
                    {
                        using (var ctx = new SolutionLoadContext(ParentSolution))
                            newItem = await Services.ProjectService.ReadSolutionItem(monitor, item.FileName, null, ctx : ctx, itemGuid : item.ItemId);
                    }
                    else
                    {
                        UnknownSolutionItem e = new UnloadedSolutionItem()
                        {
                            FileName = item.FileName
                        };
                        e.ItemId   = item.ItemId;
                        e.TypeGuid = item.TypeGuid;
                        newItem    = e;
                    }
                } catch (Exception ex) {
                    UnknownSolutionItem e = new UnknownSolutionItem();
                    e.LoadError = ex.Message;
                    e.FileName  = item.FileName;
                    newItem     = e;
                }

                if (!Items.Contains(item))
                {
                    // The old item is gone, which probably means it has already been reloaded (BXC20615), or maybe removed.
                    // In this case, there isn't anything else we can do
                    newItem.Dispose();

                    // Find the replacement if it exists
                    return(Items.OfType <SolutionItem> ().FirstOrDefault(it => it.FileName == item.FileName));
                }

                // Replace in the file list
                Items.Replace(item, newItem);

                item.ParentFolder = null;
                DisconnectChildEntryEvents(item);
                ConnectChildEntryEvents(newItem);

                NotifyModified("Items");
                OnItemRemoved(new SolutionItemChangeEventArgs(item, ParentSolution, true)
                {
                    ReplacedItem = item
                }, true);
                OnItemAdded(new SolutionItemChangeEventArgs(newItem, ParentSolution, true)
                {
                    ReplacedItem = item
                }, true);

                item.Dispose();
                return(newItem);
            }
            else
            {
                return(sitem);
            }
        }
Example #2
0
        public async Task <SolutionFolderItem> ReloadItem(ProgressMonitor monitor, SolutionFolderItem sitem)
        {
            if (Items.IndexOf(sitem) == -1)
            {
                throw new InvalidOperationException("Solution item '" + sitem.Name + "' does not belong to folder '" + Name + "'");
            }

            if (sitem is SolutionItem item)
            {
                // Load the new item

                SolutionItem newItem;
                try {
                    if (ParentSolution.IsSolutionItemEnabled(item.FileName))
                    {
                        using (var ctx = new SolutionLoadContext(ParentSolution))
                            newItem = await Services.ProjectService.ReadSolutionItem(monitor, item.FileName, null, ctx : ctx, itemGuid : item.ItemId);
                    }
                    else
                    {
                        UnknownSolutionItem e = new UnloadedSolutionItem()
                        {
                            FileName = item.FileName
                        };
                        e.ItemId   = item.ItemId;
                        e.TypeGuid = item.TypeGuid;
                        newItem    = e;
                    }
                } catch (Exception ex) {
                    newItem = new UnknownSolutionItem {
                        LoadError = ex.Message,
                        FileName  = item.FileName
                    };
                }

                if (!Items.Contains(item))
                {
                    // The old item is gone, which probably means it has already been reloaded (BXC20615), or maybe removed.
                    // In this case, there isn't anything else we can do
                    newItem.Dispose();

                    // Find the replacement if it exists
                    return(Items.OfType <SolutionItem> ().FirstOrDefault(it => it.FileName == item.FileName));
                }

                // Replace in the file list
                Items.Replace(item, newItem);

                item.ParentFolder = null;
                DisconnectChildEntryEvents(item);
                ConnectChildEntryEvents(newItem);

                // Shutdown project builder before the ItemAdded event is fired. This should prevent the old out of
                // date project builder being used by the TypeSystemService when getting reference information. The
                // TypeSystemService loads the project when the ItemAdded event is fired before the item is disposed.
                // Disposing the project will also shutdown the project builder but this happens too late and can
                // result in the old project builder being used which does not have the latest project xml.
                if (item is Project)
                {
                    await RemoteBuildEngineManager.UnloadProject(item.FileName);
                }

                NotifyModified("Items");
                OnItemRemoved(new SolutionItemChangeEventArgs(item, ParentSolution, true)
                {
                    ReplacedItem = item
                }, true);
                OnItemAdded(new SolutionItemChangeEventArgs(newItem, ParentSolution, true)
                {
                    ReplacedItem = item
                }, true);

                item.Dispose();
                return(newItem);
            }

            return(sitem);
        }
Example #3
0
		//ExtendedProperties
		//	Per config
		//		Platform : Eg. Any CPU
		//		SolutionConfigurationPlatforms
		//
		SolutionFolder LoadSolution (Solution sol, string fileName, MSBuildFileFormat format, IProgressMonitor 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;

						int e = ReadUntil ("EndProject", reader, lines);
						sec.Count = (e < 0) ? 1 : (e - sec.Start + 1);

						continue;
					}

					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");
					}

					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");
					}
				}
			}

			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.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);
				} 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));
					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;

				if (projTypeGuid == MSBuildProjectService.FolderTypeGuid) {
					//Solution folder
					SolutionFolder sfolder = new SolutionFolder ();
					sfolder.Name = projectName;
					MSBuildProjectService.InitializeItemHandler (sfolder);
					MSBuildProjectService.SetId (sfolder, projectGuid);

					projLines = lines.GetRange (sec.Start + 1, sec.Count - 2);
					DeserializeSolutionItem (sol, sfolder, projLines);
					
					foreach (string f in ReadFolderFiles (projLines))
						sfolder.Files.Add (MSBuildProjectService.FromMSBuildPath (Path.GetDirectoryName (fileName), f));
					
					SlnData slnData = new SlnData ();
					slnData.Extra = projLines.ToArray ();
					sfolder.ExtendedProperties [typeof (SlnFileFormat)] = slnData;

					items.Add (projectGuid, sfolder);
					sortedList.Add (sfolder);
					
					continue;
				}

				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));
					continue;
				}

				string path = MSBuildProjectService.FromMSBuildPath (Path.GetDirectoryName (fileName), projectPath);
				if (String.IsNullOrEmpty (path)) {
					monitor.ReportWarning (GettextCatalog.GetString (
						"Invalid project path found in {0} : {1}", fileName, projectPath));
					LoggingService.LogWarning (GettextCatalog.GetString (
						"Invalid project path found in {0} : {1}", fileName, projectPath));
					continue;
				}

				projectPath = Path.GetFullPath (path);
				
				SolutionEntityItem item = null;
				
				try {
					if (sol.IsSolutionItemEnabled (projectPath)) {
						item = ProjectExtensionUtil.LoadSolutionItem (monitor, projectPath, delegate {
							return MSBuildProjectService.LoadItem (monitor, projectPath, format, projTypeGuid, projectGuid);
						});
						
						if (item == null) {
							throw new UnknownSolutionItemTypeException (projTypeGuid);
						}
					} else {
						var uitem = new UnloadedSolutionItem () {
							FileName = projectPath
						};
						var h = new MSBuildHandler (projTypeGuid, projectGuid) {
							Item = uitem,
						};
						uitem.SetItemHandler (h);
						item = uitem;
					}
					
				} catch (Exception e) {
					// If we get a TargetInvocationException from using Activator.CreateInstance we
					// need to unwrap the real exception
					while (e is TargetInvocationException)
						e = ((TargetInvocationException) e).InnerException;
					
					bool loadAsProject = false;

					if (e is UnknownSolutionItemTypeException) {
						var name = ((UnknownSolutionItemTypeException)e).TypeName;

						var relPath = new FilePath (path).ToRelative (sol.BaseDirectory);
						if (!string.IsNullOrEmpty (name)) {
							var guids = name.Split (';');
							var projectInfo = MSBuildProjectService.GetUnknownProjectTypeInfo (guids, fileName);
							if (projectInfo != null) {
								loadAsProject = projectInfo.LoadFiles;
								LoggingService.LogWarning (string.Format ("Could not load {0} project '{1}'. {2}", projectInfo.Name, relPath, projectInfo.GetInstructions ()));
								monitor.ReportWarning (GettextCatalog.GetString ("Could not load {0} project '{1}'. {2}", projectInfo.Name, relPath, projectInfo.GetInstructions ()));
							} else {
								LoggingService.LogWarning (string.Format ("Could not load project '{0}' with unknown item type '{1}'", relPath, name));
								monitor.ReportWarning (GettextCatalog.GetString ("Could not load project '{0}' with unknown item type '{1}'", relPath, name));
							}
						} else {
							LoggingService.LogWarning (string.Format ("Could not load project '{0}' with unknown item type", relPath));
							monitor.ReportWarning (GettextCatalog.GetString ("Could not load project '{0}' with unknown item type", relPath));
						}

					} else 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));
					}

					SolutionEntityItem uitem;
					if (loadAsProject) {
						uitem = new UnknownProject () {
							FileName = projectPath,
							LoadError = e.Message,
						};
					} else {
						uitem = new UnknownSolutionItem () {
							FileName = projectPath,
							LoadError = 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);

				handler.UnresolvedProjectDependencies = ReadSolutionItemDependencies (projLines);
				handler.SlnProjectContent = projLines.ToArray ();
				handler.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");
			}

			// Resolve project dependencies
			foreach (var it in items.Values.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);
						}
					}
					if (handler.UnresolvedProjectDependencies.Count == 0)
						handler.UnresolvedProjectDependencies = null;
				}
			}

			//Add top level folders and projects to the main folder
			foreach (SolutionItem 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");
				}

				if (globals.Contains ("ProjectConfigurationPlatforms")) {
					LoadProjectConfigurationMappings (globals ["ProjectConfigurationPlatforms"] as Section, lines,
						sol, monitor);
					globals.Remove ("ProjectConfigurationPlatforms");
				}

				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);
					}
				}
				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;
		}
Example #4
0
        public SolutionItem ReloadItem(IProgressMonitor monitor, SolutionItem sitem)
        {
            if (Items.IndexOf(sitem) == -1)
            {
                throw new InvalidOperationException("Solution item '" + sitem.Name + "' does not belong to folder '" + Name + "'");
            }

            SolutionEntityItem item = sitem as SolutionEntityItem;

            if (item != null)
            {
                // Load the new item

                SolutionEntityItem newItem;
                try {
                    if (ParentSolution.IsSolutionItemEnabled(item.FileName))
                    {
                        newItem = Services.ProjectService.ReadSolutionItem(monitor, item.FileName);
                    }
                    else
                    {
                        UnknownSolutionItem e = new UnloadedSolutionItem()
                        {
                            FileName = item.FileName
                        };
                        var ch = item.GetItemHandler() as MonoDevelop.Projects.Formats.MSBuild.MSBuildHandler;
                        if (ch != null)
                        {
                            var h = new MonoDevelop.Projects.Formats.MSBuild.MSBuildHandler(ch.TypeGuid, ch.ItemId)
                            {
                                Item = e,
                            };
                            e.SetItemHandler(h);
                        }
                        newItem = e;
                    }
                } catch (Exception ex) {
                    UnknownSolutionItem e = new UnknownSolutionItem();
                    e.LoadError = ex.Message;
                    e.FileName  = item.FileName;
                    newItem     = e;
                }

                if (!Items.Contains(item))
                {
                    // The old item is gone, which probably means it has already been reloaded (BXC20615), or maybe removed.
                    // In this case, there isn't anything else we can do
                    newItem.Dispose();

                    // Find the replacement if it exists
                    return(Items.OfType <SolutionEntityItem> ().FirstOrDefault(it => it.FileName == item.FileName));
                }

                // Replace in the file list
                Items.Replace(item, newItem);

                DisconnectChildEntryEvents(item);
                ConnectChildEntryEvents(newItem);

                NotifyModified("Items");
                OnItemRemoved(new SolutionItemChangeEventArgs(item, ParentSolution, true)
                {
                    ReplacedItem = item
                }, true);
                OnItemAdded(new SolutionItemChangeEventArgs(newItem, ParentSolution, true)
                {
                    ReplacedItem = item
                }, true);

                item.Dispose();
                return(newItem);
            }
            else
            {
                return(sitem);
            }
        }