void TestCreateInterface (string interfacecode, string outputString, string stubString = null)
		{
			var project = new UnknownProject ();
			project.FileName = "test.csproj";
			
			TypeSystemService.LoadProject (project);
			
			TypeSystemService.ParseFile (project, "program.cs", "text/x-csharp", interfacecode);
			TypeSystemService.ParseFile (project, "stub.cs", "text/x-csharp", "class Stub {\n "+stubString+"}\n");
			
			var wrapper = TypeSystemService.GetProjectContentWrapper (project);
			wrapper.UpdateContent (c => c.AddAssemblyReferences (new [] { Mscorlib, SystemCore }));
			
			var pctx = TypeSystemService.GetCompilation (project);
			
			var stubType = pctx.MainAssembly.GetTypeDefinition ("", "Stub", 0);
			var iface = pctx.MainAssembly.GetTypeDefinition ("", "ITest", 0);
			
			var gen = new CSharpCodeGenerator ();
			gen.EolMarker = "\n";
			gen.Compilation = pctx;
			string generated = gen.CreateInterfaceImplementation (stubType, stubType.Parts.First (), iface, false);
			Assert.IsNotEmpty (generated);
			// crop #region
			generated = generated.Substring (generated.IndexOf ("implementation") + "implementation".Length);
			generated = generated.Substring (0, generated.LastIndexOf ("#"));
			generated = generated.Trim ();
			if (outputString != generated)
				Console.WriteLine (generated);
			Assert.AreEqual (outputString, generated);
		}
Beispiel #2
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;
		}
		static void TestInsertionPoints (string text)
		{
			
			TestWorkbenchWindow tww = new TestWorkbenchWindow ();
			TestViewContent sev = new TestViewContent ();
			var project = new UnknownProject ();
			project.FileName = "test.csproj";
			
			TypeSystemService.LoadProject (project);

			sev.Project = project;
			tww.ViewContent = sev;
			var doc = new MonoDevelop.Ide.Gui.Document (tww);
			var data = doc.Editor;
			List<InsertionPoint> loc = new List<InsertionPoint> ();
			for (int i = 0; i < text.Length; i++) {
				char ch = text [i];
				if (ch == '@') {
					i++;
					ch = text [i];
					NewLineInsertion insertBefore = NewLineInsertion.None;
					NewLineInsertion insertAfter = NewLineInsertion.None;
					
					switch (ch) {
					case 'n':
						break;
					case 'd':
						insertAfter = NewLineInsertion.Eol;
						break;
					case 'D':
						insertAfter = NewLineInsertion.BlankLine;
						break;
					case 'u':
						insertBefore = NewLineInsertion.Eol;
						break;
					case 'U':
						insertBefore = NewLineInsertion.BlankLine;
						break;
					case 's':
						insertBefore = insertAfter = NewLineInsertion.Eol;
						break;
					case 'S':
						insertBefore = insertAfter = NewLineInsertion.BlankLine;
						break;
						
					case 't':
						insertBefore = NewLineInsertion.Eol;
						insertAfter = NewLineInsertion.BlankLine;
						break;
					case 'T':
						insertBefore = NewLineInsertion.None;
						insertAfter = NewLineInsertion.BlankLine;
						break;
					case 'v':
						insertBefore = NewLineInsertion.BlankLine;
						insertAfter = NewLineInsertion.Eol;
						break;
					case 'V':
						insertBefore = NewLineInsertion.None;
						insertAfter = NewLineInsertion.Eol;
						break;
					default:
						Assert.Fail ("unknown insertion point:" + ch);
						break;
					}
					loc.Add (new InsertionPoint (data.Document.OffsetToLocation (data.Document.TextLength), insertBefore, insertAfter));
				} else {
					data.Insert (data.Document.TextLength, ch.ToString ());
				}
			}
			
			var parsedFile = TypeSystemService.ParseFile (project, "program.cs", "text/x-csharp", data.Document.Text);

			var foundPoints = CodeGenerationService.GetInsertionPoints (doc.Editor, parsedFile, parsedFile.TopLevelTypeDefinitions.First ());
			Assert.AreEqual (loc.Count, foundPoints.Count, "point count doesn't match");
			for (int i = 0; i < loc.Count; i++) {
				Assert.AreEqual (loc[i].Location, foundPoints[i].Location, "point " + i + " doesn't match");
				Assert.AreEqual (loc[i].LineAfter, foundPoints[i].LineAfter, "point " + i + " ShouldInsertNewLineAfter doesn't match");
				Assert.AreEqual (loc[i].LineBefore, foundPoints[i].LineBefore, "point " + i + " ShouldInsertNewLineBefore doesn't match");
			}
		}