internal void Add (Import import) { if (!filenames.ContainsKey (import.EvaluatedProjectPath)) { groupingCollection.Add (import); filenames.Add (import.EvaluatedProjectPath, import); } }
/// <summary> /// Changes the value of the ProjectPath property on an existing import. /// Note: this methods causes the project to recreate all imports, so existing import /// instances might not be affected. /// </summary> public static void SetImportProjectPath(MSBuildBasedProject project, MSBuild.Import import, string newRawPath) { if (project == null) { throw new ArgumentNullException("project"); } if (import == null) { throw new ArgumentNullException("import"); } if (newRawPath == null) { throw new ArgumentNullException("newRawPath"); } lock (project.SyncRoot) { XmlAttribute a = (XmlAttribute)typeof(MSBuild.Import).InvokeMember( "ProjectPathAttribute", BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic, null, import, null ); a.Value = newRawPath; EndXmlManipulation(project.MSBuildProject); } project.CreateItemsListFromMSBuild(); }
public void TestICollectionMethods() { ObjectModelHelpers.DeleteTempProjectDirectory(); ObjectModelHelpers.CreateFileInTempProjectDirectory("import1.proj", @" <Project xmlns=`msbuildnamespace`> </Project> "); ObjectModelHelpers.CreateFileInTempProjectDirectory("import2.proj", @" <Project xmlns=`msbuildnamespace`> </Project> "); ObjectModelHelpers.CreateFileInTempProjectDirectory("main.proj", @" <Project xmlns=`msbuildnamespace`> <Import Project=`import1.proj` /> <Import Project=`import2.proj` /> <Target Name=`Build`> <WashCar/> </Target> </Project> "); Project project = ObjectModelHelpers.LoadProjectFileInTempProjectDirectory("main.proj", null); string import1Path = Path.Combine(ObjectModelHelpers.TempProjectDir, "import1.proj"); string import2Path = Path.Combine(ObjectModelHelpers.TempProjectDir, "import2.proj"); ImportCollection imports = project.Imports; Assertion.AssertEquals(2, imports.Count); Import[] array = new Import[2]; imports.CopyTo(array, 0); Dictionary<string, Import> hash = new Dictionary<string, Import>(StringComparer.OrdinalIgnoreCase); hash[array[0].EvaluatedProjectPath] = array[0]; hash[array[1].EvaluatedProjectPath] = array[1]; Assertion.AssertEquals(imports[import1Path], hash[import1Path]); Assertion.AssertEquals(imports[import2Path], hash[import2Path]); object[] arrayObjects = new object[2]; imports.CopyTo(arrayObjects, 0); hash.Clear(); hash[((Import)arrayObjects[0]).EvaluatedProjectPath] = ((Import)arrayObjects[0]); hash[((Import)arrayObjects[1]).EvaluatedProjectPath] = ((Import)arrayObjects[1]); Assertion.AssertEquals(imports[import1Path], hash[import1Path]); Assertion.AssertEquals(imports[import2Path], hash[import2Path]); Assertion.AssertEquals("import1.proj", imports[import1Path].ProjectPath); Assertion.AssertEquals("import2.proj", imports[import2Path].ProjectPath); }
public void Imports() { // this is machine-dependent, it's possible that additional imports are loaded //Assert.AreEqual(2, project.MSBuildProject.Imports.Count); Microsoft.Build.BuildEngine.Import[] imports = new Microsoft.Build.BuildEngine.Import[project.MSBuildProject.Imports.Count]; project.MSBuildProject.Imports.CopyTo(imports, 0); string[] paths = new string[imports.Length]; for (int i = 0; i < imports.Length; i++) { paths[i] = imports[i].ProjectPath; } Assert.Contains(WixProject.DefaultTargetsFile, paths); }
/// <summary> /// Gets the import paths from the project. /// </summary> string[] GetImportPaths() { int count = project.MSBuildProject.Imports.Count; Microsoft.Build.BuildEngine.Import[] imports = new Microsoft.Build.BuildEngine.Import[count]; project.MSBuildProject.Imports.CopyTo(imports, 0); string[] paths = new string[count]; for (int i = 0; i < count; ++i) { Microsoft.Build.BuildEngine.Import import = imports[i]; paths[i] = import.ProjectPath; } return(paths); }
public void TestAdd1 () { string first = @" <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003""> <Import Project='second.proj'/> </Project> "; using (StreamWriter sw = new StreamWriter ("Test/resources/first.proj")) { sw.Write (first); } string second = @" <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003""> </Project> "; using (StreamWriter sw = new StreamWriter ("Test/resources/second.proj")) { sw.Write (second); } string documentString = @" <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003""> <Import Project='Test\resources\first.proj'/> <Import Project='Test\resources\Import.csproj' Condition='false'/> </Project> "; engine = new Engine (Consts.BinPath); project = engine.CreateNewProject (); project.LoadXml (documentString); Import[] t = new Import [2]; Assert.AreEqual (2, project.Imports.Count, "Number of imports"); project.Imports.CopyTo (t, 0); string base_dir = Path.Combine (Environment.CurrentDirectory, Path.Combine ("Test", "resources")); Assert.IsNull (t [0].Condition, "A1"); Assert.AreEqual (false, t[0].IsImported, "A5"); Assert.AreEqual ("Test\\resources\\first.proj", t[0].ProjectPath, "A6"); Assert.AreEqual (Path.Combine (base_dir, "first.proj"), t[0].EvaluatedProjectPath, "A7"); Assert.AreEqual (true, t[1].IsImported, "A2"); Assert.AreEqual ("second.proj", t[1].ProjectPath, "A3"); Assert.AreEqual (Path.Combine (base_dir, "second.proj"), t[1].EvaluatedProjectPath, "A4"); }
internal void Add (Import import) { imports++; if (add_iterator == null) list.AddLast (import); else { list.AddAfter (add_iterator, import); add_iterator = add_iterator.Next; } }
public void CopyTo (Import[] array, int index) { CopyTo ((Array) array, index); }
internal bool TryGetImport (Import keyImport, out Import valueImport) { return filenames.TryGetValue (keyImport.EvaluatedProjectPath, out valueImport); }
internal bool Contains (Import import) { return filenames.ContainsKey (import.EvaluatedProjectPath); }
/// <summary> /// Removes an import from the project, and removes the corresponding <Import> element /// from the project's XML. /// </summary> /// <param name="importToRemove"></param> /// <owner>JeffCal</owner> public void RemoveImport ( Import importToRemove ) { ErrorUtilities.VerifyThrowArgumentNull(importToRemove, "importToRemove"); // Confirm that it's not an imported import. ErrorUtilities.VerifyThrowInvalidOperation(!importToRemove.IsImported, "CannotModifyImportedProjects"); // Confirm that the import belongs to this project. ErrorUtilities.VerifyThrowInvalidOperation(importToRemove.ParentProject == this.parentProject, "IncorrectObjectAssociation", "Import", "Project"); // Remove the Xml for the <Import> from the <Project>. this.parentProject.ProjectElement.RemoveChild(importToRemove.ImportElement); // Remove the import from our hashtable. this.imports.Remove(importToRemove.EvaluatedProjectPath); // Dissociate the import from the parent project. importToRemove.ParentProject = null; // The project file has been modified and needs to be saved and re-evaluated. this.parentProject.MarkProjectAsDirtyForReprocessXml(); }
/// <summary> /// Copy the contents of this collection into a strongly typed array /// </summary> /// <param name="array"></param> /// <param name="index"></param> /// <owner>LukaszG</owner> public void CopyTo(Import[] array, int index) { ErrorUtilities.VerifyThrow(this.imports != null, "ImportCollection's Hashtable not initialized!"); this.imports.Values.CopyTo(array, index); }
public void SyncRoot() { string importPath = String.Empty; string importPath2 = String.Empty; try { importPath = ObjectModelHelpers.CreateFileInTempProjectDirectory("import.proj", TestData.Content3SimpleTargetsDefaultSpecified); importPath2 = ObjectModelHelpers.CreateFileInTempProjectDirectory("import2.proj", TestData.Content3SimpleTargetsDefaultSpecified); Project p = new Project(); p.Imports.AddNewImport(importPath, "true"); p.Imports.AddNewImport(importPath2, "true"); object o = p.EvaluatedItems; Import[] importArray = new Import[p.Imports.Count]; p.Imports.CopyTo(importArray, 0); lock (p.Imports.SyncRoot) { int i = 0; foreach (Import import in p.Imports) { Assertion.AssertEquals(importArray[i].ProjectPath, import.ProjectPath); i++; } } } finally { CompatibilityTestHelpers.RemoveFile(importPath); CompatibilityTestHelpers.RemoveFile(importPath2); } }
public void CopyToStrong_OffsetIndex() { string importPath = String.Empty; try { const int OffsetIndex = 2; importPath = ObjectModelHelpers.CreateFileInTempProjectDirectory("import.proj", TestData.Content3SimpleTargetsDefaultSpecified); Project p = new Project(); p.Imports.AddNewImport(importPath, "true"); object o = p.EvaluatedItems; Import import = CompatibilityTestHelpers.FindFirstMatchingImportByPath(p.Imports, importPath); Import[] importArray = new Import[p.Imports.Count + OffsetIndex]; p.Imports.CopyTo(importArray, OffsetIndex); Assertion.AssertEquals(p.Imports.Count, importArray.Length - OffsetIndex); Assertion.AssertNull(importArray[OffsetIndex - 1]); Assertion.AssertEquals(true, 0 < Array.IndexOf(importArray, import)); } finally { CompatibilityTestHelpers.RemoveFile(importPath); } }
internal bool Contains(Import import) { return(filenames.ContainsKey(import.EvaluatedProjectPath)); }
internal bool TryGetImport(Import keyImport, out Import valueImport) { return(filenames.TryGetValue(keyImport.EvaluatedProjectPath, out valueImport)); }
public void GetEnumerator() { string importPath = String.Empty; string importPath2 = String.Empty; try { importPath = ObjectModelHelpers.CreateFileInTempProjectDirectory("import.proj", TestData.Content3SimpleTargetsDefaultSpecified); importPath2 = ObjectModelHelpers.CreateFileInTempProjectDirectory("import2.proj", TestData.Content3SimpleTargetsDefaultSpecified); Project p = new Project(); p.Imports.AddNewImport(importPath, "true"); p.Imports.AddNewImport(importPath2, "true"); object o = p.EvaluatedItems; Import[] importArray = new Import[p.Imports.Count]; p.Imports.CopyTo(importArray, 0); System.Collections.IEnumerator importEnum = p.Imports.GetEnumerator(); int enumerationCounter = 0; while (importEnum.MoveNext()) { Assertion.AssertEquals(true, object.ReferenceEquals(importArray[enumerationCounter], importEnum.Current)); Assertion.AssertEquals(importArray[enumerationCounter].ProjectPath, ((Import)importEnum.Current).ProjectPath); enumerationCounter++; } } finally { CompatibilityTestHelpers.RemoveFile(importPath); CompatibilityTestHelpers.RemoveFile(importPath2); } }
/// <summary> /// Process the <Import> element by loading the child project file, and processing its <Project> element. In a /// given main project, the same file cannot be imported twice -- this is to prevent circular imports. /// </summary> /// <owner>RGoel</owner> /// <param name="importElement"></param> /// <param name="projectDirectoryLocation"></param> /// <param name="importedProject"></param> private void ProcessImportElement ( XmlElement importElement, string projectDirectoryLocation, bool importedProject ) { Import temp = new Import(importElement, this, importedProject); if (temp.ConditionAttribute != null) { // Do not expand properties or items before passing in the value of the // condition attribute to EvaluateCondition, otherwise special characters // inside the property values can really confuse the condition parser. if (!Utilities.EvaluateCondition(temp.Condition, temp.ConditionAttribute, new Expander(this.evaluatedProperties), this.conditionedPropertiesTable, ParserOptions.AllowProperties, ParentEngine.LoggingServices, projectBuildEventContext)) { return; } } // If we got this far, we expect the "Project" attribute to have a reasonable // value, so process it now. // Expand any $(propertyname) references inside the "Project" attribute value. string expandedImportedFilename = (new Expander(this.evaluatedProperties)).ExpandAllIntoStringLeaveEscaped(temp.ProjectPath, temp.ProjectPathAttribute); // Expand any wildcards string[] importedFilenames = EngineFileUtilities.GetFileListEscaped(projectDirectoryLocation, expandedImportedFilename); for (int i = 0; i < importedFilenames.Length; i++) { string importedFilename = EscapingUtilities.UnescapeAll(importedFilenames[i]); ProjectErrorUtilities.VerifyThrowInvalidProject((importedFilename != null) && (importedFilename.Length != 0), importElement, "MissingRequiredAttribute", XMakeAttributes.project, XMakeElements.import); Import import = new Import(importElement, this, importedProject); try { if (!string.IsNullOrEmpty(projectDirectoryLocation)) { import.SetEvaluatedProjectPath(Path.GetFullPath(Path.Combine(projectDirectoryLocation, importedFilename))); } else { import.SetEvaluatedProjectPath(Path.GetFullPath(importedFilename)); } } catch (Exception e) // Catching Exception, but rethrowing unless it's an IO related exception. { if (ExceptionHandling.NotExpectedException(e)) throw; ProjectErrorUtilities.VerifyThrowInvalidProject(false, importElement, "InvalidAttributeValueWithException", importedFilename, XMakeAttributes.project, XMakeElements.import, e.Message); } XmlDocument importedDocument = LoadImportedProject(import); if (importedDocument != null) { this.rawGroups.InsertAtEnd(import); // Get the top-level nodes from the XML. XmlNodeList importedFileNodes = importedDocument.ChildNodes; // The XML parser will guarantee that we only have one real root element, // but we need to find it amongst the other types of XmlNode at the root. foreach (XmlNode importedChildNode in importedFileNodes) { if (XmlUtilities.IsXmlRootElement(importedChildNode)) { // Save the current directory, so we can restore it back later. string currentDirectory = Directory.GetCurrentDirectory(); // If we have a <VisualStudioProject> node, tell the user they must upgrade the project ProjectErrorUtilities.VerifyThrowInvalidProject(importedChildNode.LocalName != XMakeElements.visualStudioProject, importedChildNode, "ProjectUpgradeNeeded"); // This node must be a <Project> node. ProjectErrorUtilities.VerifyThrowInvalidProject(importedChildNode.LocalName == XMakeElements.project, importedChildNode, "UnrecognizedElement", importedChildNode.Name); ProjectErrorUtilities.VerifyThrowInvalidProject((importedChildNode.Prefix.Length == 0) && (String.Compare(importedChildNode.NamespaceURI, XMakeAttributes.defaultXmlNamespace, StringComparison.OrdinalIgnoreCase) == 0), importedChildNode, "ProjectMustBeInMSBuildXmlNamespace", XMakeAttributes.defaultXmlNamespace); // We have the <Project> element, so process it. this.ProcessProjectAttributes((XmlElement)importedChildNode, /* imported project */ true); this.ProcessProjectChildren((XmlElement)importedChildNode, Path.GetDirectoryName(import.EvaluatedProjectPath), /* imported project */ true); break; } } } } }
public void CopyToStrong_IndexZero() { string importPath = String.Empty; try { importPath = ObjectModelHelpers.CreateFileInTempProjectDirectory("import.proj", TestData.Content3SimpleTargetsDefaultSpecified); Project p = new Project(); p.Imports.AddNewImport(importPath, "true"); object o = p.EvaluatedItems; Import import = CompatibilityTestHelpers.FindFirstMatchingImportByPath(p.Imports, importPath); Import[] importArray = new Import[p.Imports.Count]; p.Imports.CopyTo(importArray, 0); Assertion.AssertEquals(p.Imports.Count, importArray.Length); Assertion.AssertEquals(0, Array.IndexOf(importArray, import)); Assertion.AssertEquals(true, object.ReferenceEquals(importArray[Array.IndexOf(importArray, import)], import)); } finally { CompatibilityTestHelpers.RemoveFile(importPath); } }
/// <summary> /// Loads the XML for the specified project that is being imported into the main project. /// </summary> /// <owner>RGoel, SumedhK</owner> /// <param name="import">The project being imported</param> /// <returns>XML for imported project; null, if duplicate import.</returns> private XmlDocument LoadImportedProject(Import import) { XmlDocument importedDocument = null; bool importedFileExists = File.Exists(import.EvaluatedProjectPath); // NOTE: don't use ErrorUtilities.VerifyThrowFileExists() here because that exception doesn't carry XML node // information, and we need that data to show a better error message if (!importedFileExists) { ProjectErrorUtilities.VerifyThrowInvalidProject((this.loadSettings & ProjectLoadSettings.IgnoreMissingImports) != 0, import.ProjectPathAttribute, "ImportedProjectNotFound", import.EvaluatedProjectPath); } // Make sure that the file we're about to import hasn't been imported previously. // This is how we prevent circular dependencies. It so happens that this mechanism // also prevents the same file from being imported twice, even it it's not a // circular dependency, but that's fine -- no good reason to do that anyway. if ((this.imports[import.EvaluatedProjectPath] != null) || (string.Compare(this.FullFileName, import.EvaluatedProjectPath, StringComparison.OrdinalIgnoreCase) == 0)) { ParentEngine.LoggingServices.LogWarning(projectBuildEventContext, Utilities.CreateBuildEventFileInfo(import.ProjectPathAttribute, FullFileName), "DuplicateImport", import.EvaluatedProjectPath); } else { // See if the imported project is also a top-level project that has been loaded // by the engine. If so, use the in-memory copy of the imported project instead // of reading the copy off of the disk. This way, we can reflect any changes // that have been made to the in-memory copy. Project importedProject = this.ParentEngine.GetLoadedProject(import.EvaluatedProjectPath); if (importedProject != null) { importedDocument = importedProject.XmlDocument; } // The imported project is not part of the engine, so read it off of disk. else { // If the file doesn't exist on disk but we're told to ignore missing imports, simply skip it if (importedFileExists) { // look up the engine's cache to see if we've already loaded this imported project on behalf of another // top-level project ImportedProject previouslyImportedProject = (ImportedProject)ParentEngine.ImportedProjectsCache[import.EvaluatedProjectPath]; // if this project hasn't been imported before, or if it has changed on disk, we need to load it if ((previouslyImportedProject == null) || previouslyImportedProject.HasChangedOnDisk(import.EvaluatedProjectPath)) { try { // Do not validate the imported file against a schema. // We only validate the parent project against a schema in V1, because without custom // namespace support, we would have to pollute the msbuild namespace with everything that // appears anywhere in our targets file. // cache this imported project, so that if another top-level project also imports this project, we // will not re-parse the XML (unless it changes) previouslyImportedProject = new ImportedProject(import.EvaluatedProjectPath); ParentEngine.ImportedProjectsCache[import.EvaluatedProjectPath] = previouslyImportedProject; } // catch XML exceptions early so that we still have the imported project file name catch (XmlException e) { BuildEventFileInfo fileInfo = new BuildEventFileInfo(e); ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(false, fileInfo, "InvalidImportedProjectFile", e.Message); } // catch IO exceptions, for example for when the file is in use. DDB #36839 catch (Exception e) { if (ExceptionHandling.NotExpectedException(e)) throw; BuildEventFileInfo fileInfo = new BuildEventFileInfo(import.EvaluatedProjectPath); ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(false, fileInfo, "InvalidImportedProjectFile", e.Message); } } importedDocument = previouslyImportedProject.Xml; } } // Add the imported filename to our list, so we can be sure not to import // it again. This helps prevent infinite recursion. this.imports[import.EvaluatedProjectPath] = import; } return importedDocument; }