internal BuildItemGroup (XmlElement xmlElement, Project project, ImportedProject importedProject, bool readOnly, bool dynamic) { this.buildItems = new List <BuildItem> (); this.importedProject = importedProject; this.itemGroupElement = xmlElement; this.parentProject = project; this.read_only = readOnly; this.isDynamic = dynamic; if (!FromXml) return; foreach (XmlNode xn in xmlElement.ChildNodes) { if (!(xn is XmlElement)) continue; XmlElement xe = (XmlElement) xn; BuildItem bi = CreateItem (project, xe); buildItems.Add (bi); project.LastItemGroupContaining [bi.Name] = this; } DefinedInFileName = importedProject != null ? importedProject.FullFileName : project != null ? project.FullFileName : null; }
internal BuildChoose (XmlElement xmlElement, Project project, ImportedProject importedProject) { //this.xmlElement = xmlElement; //this.project = project; //this.importedProject = importedProject; this.whens = new List <BuildWhen> (); foreach (XmlNode xn in xmlElement.ChildNodes) { if (!(xn is XmlElement)) continue; XmlElement xe = (XmlElement)xn; if (xe.Name == "When") { if (otherwise != null) throw new InvalidProjectFileException ("The 'Otherwise' element must be last in a 'Choose' element."); if (xe.Attributes.GetNamedItem ("Condition") == null) throw new InvalidProjectFileException ("The 'When' element requires a 'Condition' attribute."); BuildWhen bw = new BuildWhen (xe, project); whens.Add (bw); } else if (xe.Name == "Otherwise") { if (this.whens.Count == 0) throw new InvalidProjectFileException ("At least one 'When' element must occur in a 'Choose' element."); otherwise = new BuildWhen (xe, project); } } DefinedInFileName = importedProject != null ? importedProject.FullFileName : project != null ? project.FullFileName : null; }
internal Target (XmlElement targetElement, Project project, ImportedProject importedProject) { if (project == null) throw new ArgumentNullException ("project"); if (targetElement == null) throw new ArgumentNullException ("targetElement"); this.targetElement = targetElement; this.name = targetElement.GetAttribute ("Name"); this.project = project; this.engine = project.ParentEngine; this.importedProject = importedProject; this.onErrorElements = new List <XmlElement> (); this.buildState = BuildState.NotStarted; this.buildTasks = new List <BuildTask> (); this.batchingImpl = new TargetBatchingImpl (project, this.targetElement); bool onErrorFound = false; foreach (XmlNode xn in targetElement.ChildNodes) { if (xn is XmlElement) { XmlElement xe = (XmlElement) xn; if (xe.Name == "OnError") { onErrorElements.Add (xe); onErrorFound = true; } else if (onErrorFound) throw new InvalidProjectFileException ( "The element <OnError> must be last under element <Target>. Found element <Error> instead."); else buildTasks.Add (new BuildTask (xe, this)); } } }
internal Import(XmlElement importElement, Project project, ImportedProject originalProject) { if (importElement == null) { throw new ArgumentNullException("importElement"); } if (project == null) { throw new ArgumentNullException("project"); } this.project = project; this.importElement = importElement; this.originalProject = originalProject; if (ProjectPath == String.Empty) { throw new InvalidProjectFileException("The required attribute \"Project\" is missing from element <Import>."); } evaluatedProjectPath = EvaluateProjectPath(ProjectPath); evaluatedProjectPath = GetFullPath(); if (EvaluatedProjectPath == String.Empty) { throw new InvalidProjectFileException("The required attribute \"Project\" is missing from element <Import>."); } }
internal BuildPropertyGroup (XmlElement xmlElement, Project project, ImportedProject importedProject, bool readOnly, bool isDynamic) { this.importedProject = importedProject; this.parentCollection = null; this.parentProject = project; this.propertyGroup = xmlElement; this.read_only = readOnly; this.isDynamic = isDynamic; if (FromXml) { this.properties = new List <BuildProperty> (); foreach (XmlNode xn in propertyGroup.ChildNodes) { if (!(xn is XmlElement)) continue; XmlElement xe = (XmlElement) xn; BuildProperty bp = new BuildProperty (parentProject, xe); AddProperty (bp); } } else this.propertiesByName = new Dictionary <string, BuildProperty> (StringComparer.OrdinalIgnoreCase); DefinedInFileName = importedProject != null ? importedProject.FullFileName : (project != null ? project.FullFileName : null); }
internal Target(XmlElement targetElement, Project project, ImportedProject importedProject) { if (project == null) { throw new ArgumentNullException("project"); } if (targetElement == null) { throw new ArgumentNullException("targetElement"); } this.targetElement = targetElement; this.name = targetElement.GetAttribute("Name"); this.project = project; this.engine = project.ParentEngine; this.importedProject = importedProject; this.onErrorElements = new List <XmlElement> (); this.buildState = BuildState.NotStarted; this.buildTasks = new List <IBuildTask> (); this.batchingImpl = new TargetBatchingImpl(project, this.targetElement); bool onErrorFound = false; foreach (XmlNode xn in targetElement.ChildNodes) { if (xn is XmlElement) { XmlElement xe = (XmlElement)xn; if (xe.Name == "OnError") { onErrorElements.Add(xe); onErrorFound = true; } else if (onErrorFound) { throw new InvalidProjectFileException( "The element <OnError> must be last under element <Target>. Found element <Error> instead."); } #if NET_3_5 else if (xe.Name == "ItemGroup") { var group = new BuildTaskItemGroup(xe, this); buildTasks.AddRange(group.Items); continue; } else if (xe.Name == "PropertyGroup") { buildTasks.Add(new BuildTaskPropertyGroup(xe, this)); continue; } #endif else { buildTasks.Add(new BuildTask(xe, this)); } } } }
internal BuildPropertyGroup(XmlElement xmlElement, Project project, ImportedProject importedProject, bool readOnly) { this.importedProject = importedProject; this.parentCollection = null; this.parentProject = project; this.propertyGroup = xmlElement; this.read_only = readOnly; if (FromXml) { this.properties = new List <BuildProperty> (); foreach (XmlNode xn in propertyGroup.ChildNodes) { if (!(xn is XmlElement)) { continue; } XmlElement xe = (XmlElement)xn; BuildProperty bp = new BuildProperty(parentProject, xe); AddProperty(bp); } } else { this.propertiesByName = new Dictionary <string, BuildProperty> (StringComparer.InvariantCultureIgnoreCase); } }
internal BuildItemGroup(XmlElement xmlElement, Project project, ImportedProject importedProject, bool readOnly, bool dynamic) { this.buildItems = new List <BuildItem> (); this.importedProject = importedProject; this.itemGroupElement = xmlElement; this.parentProject = project; this.read_only = readOnly; this.isDynamic = dynamic; if (!FromXml) { return; } foreach (XmlNode xn in xmlElement.ChildNodes) { if (!(xn is XmlElement)) { continue; } XmlElement xe = (XmlElement)xn; BuildItem bi = CreateItem(project, xe); buildItems.Add(bi); project.LastItemGroupContaining [bi.Name] = this; } DefinedInFileName = importedProject != null ? importedProject.FullFileName : project != null ? project.FullFileName : null; }
internal BuildPropertyGroup(XmlElement xmlElement, Project project, ImportedProject importedProject, bool readOnly, bool isDynamic) { this.importedProject = importedProject; this.parentCollection = null; this.parentProject = project; this.propertyGroup = xmlElement; this.read_only = readOnly; this.isDynamic = isDynamic; if (FromXml) { this.properties = new List <BuildProperty> (); foreach (XmlNode xn in propertyGroup.ChildNodes) { if (!(xn is XmlElement)) { continue; } XmlElement xe = (XmlElement)xn; BuildProperty bp = new BuildProperty(parentProject, xe); AddProperty(bp); } } else { this.propertiesByName = new Dictionary <string, BuildProperty> (StringComparer.OrdinalIgnoreCase); } DefinedInFileName = importedProject != null ? importedProject.FullFileName : (project != null ? project.FullFileName : null); }
// FIXME: condition internal void Evaluate(bool ignoreMissingImports) { string filename = evaluatedProjectPath; // NOTE: it's a hack to transform Microsoft.CSharp.Targets to Microsoft.CSharp.targets if (Path.HasExtension(filename)) { filename = Path.ChangeExtension(filename, Path.GetExtension(filename)); } if (!File.Exists(filename)) { if (ignoreMissingImports) { project.LogWarning(project.FullFileName, "Could not find project file {0}, to import. Ignoring.", filename); return; } else { throw new InvalidProjectFileException(String.Format("Imported project: \"{0}\" does not exist.", filename)); } } ImportedProject importedProject = new ImportedProject(); importedProject.Load(filename); project.ProcessElements(importedProject.XmlDocument.DocumentElement, importedProject); }
internal BuildItemGroup(XmlElement xmlElement, Project project, ImportedProject importedProject, bool readOnly) { this.buildItems = new List <BuildItem> (); this.importedProject = importedProject; this.itemGroupElement = xmlElement; this.parentProject = project; this.read_only = readOnly; if (!FromXml) { return; } foreach (XmlNode xn in xmlElement.ChildNodes) { if (!(xn is XmlElement)) { continue; } XmlElement xe = (XmlElement)xn; BuildItem bi = new BuildItem(xe, this); buildItems.Add(bi); project.LastItemGroupContaining [bi.Name] = this; } }
// if @alternateProjectPath is available then that it used as the EvaluatedProjectPath! internal Import(XmlElement importElement, string alternateProjectPath, Project project, ImportedProject originalProject) { if (importElement == null) { throw new ArgumentNullException("importElement"); } if (project == null) { throw new ArgumentNullException("project"); } this.project = project; this.importElement = importElement; this.originalProject = originalProject; if (ProjectPath == String.Empty) { throw new InvalidProjectFileException("The required attribute \"Project\" is missing from element <Import>."); } if (ConditionParser.ParseAndEvaluate(Condition, project)) { evaluatedProjectPath = String.IsNullOrEmpty(alternateProjectPath) ? EvaluateProjectPath(ProjectPath) : alternateProjectPath; evaluatedProjectPath = GetFullPath(); if (EvaluatedProjectPath == String.Empty) { throw new InvalidProjectFileException("The required attribute \"Project\" is missing from element <Import>."); } } }
internal Target(XmlElement targetElement, Project project, ImportedProject importedProject) { if (project == null) { throw new ArgumentNullException("project"); } if (targetElement == null) { throw new ArgumentNullException("targetElement"); } this.targetElement = targetElement; this.name = targetElement.GetAttribute("Name"); this.project = project; this.engine = project.ParentEngine; this.importedProject = importedProject; this.onErrorElements = new List <XmlElement> (); this.buildState = BuildState.NotStarted; this.buildTasks = new List <BuildTask> (); this.batchingImpl = new TargetBatchingImpl(project, this.targetElement); bool onErrorFound = false; foreach (XmlNode xn in targetElement.ChildNodes) { if (xn is XmlElement) { XmlElement xe = (XmlElement)xn; if (xe.Name == "OnError") { onErrorElements.Add(xe); onErrorFound = true; } else if (onErrorFound) { throw new InvalidProjectFileException( "The element <OnError> must be last under element <Target>. Found element <Error> instead."); } #if NET_3_5 else if (xe.Name == "ItemGroup") { //don't blow up for ItemGroups inside Targets in >= 3.5 // TODO: evaluate them (see https://bugzilla.xamarin.com/show_bug.cgi?id=1862 and test in TargetTest.cs ) continue; } #endif else { buildTasks.Add(new BuildTask(xe, this)); } } } }
internal UsingTask (XmlElement usingTaskElement, Project project, ImportedProject importedProject) { this.project = project; this.importedProject = importedProject; this.usingTaskElement = usingTaskElement; if (project == null) throw new ArgumentNullException ("project"); if (usingTaskElement == null) throw new ArgumentNullException ("usingTaskElement"); if (AssemblyName != null && AssemblyFile != null) throw new InvalidProjectFileException ("A <UsingTask> element must contain either the \"AssemblyName\" attribute or the \"AssemblyFile\" attribute (but not both). "); if (TaskName == String.Empty) throw new InvalidProjectFileException ("The required attribute \"TaskName\" is missing from element <UsingTask>. "); }
internal Import (XmlElement importElement, Project project, ImportedProject originalProject) { if (importElement == null) throw new ArgumentNullException ("importElement"); if (project == null) throw new ArgumentNullException ("project"); this.project = project; this.importElement = importElement; this.originalProject = originalProject; if (ProjectPath == String.Empty) throw new InvalidProjectFileException ("The required attribute \"Project\" is missing from element <Import>."); evaluatedProjectPath = EvaluateProjectPath (ProjectPath); evaluatedProjectPath = GetFullPath (); if (EvaluatedProjectPath == String.Empty) throw new InvalidProjectFileException ("The required attribute \"Project\" is missing from element <Import>."); }
internal BuildChoose(XmlElement xmlElement, Project project, ImportedProject importedProject) { //this.xmlElement = xmlElement; //this.project = project; //this.importedProject = importedProject; this.whens = new List <BuildWhen> (); foreach (XmlNode xn in xmlElement.ChildNodes) { if (!(xn is XmlElement)) { continue; } XmlElement xe = (XmlElement)xn; if (xe.Name == "When") { if (otherwise != null) { throw new InvalidProjectFileException("The 'Otherwise' element must be last in a 'Choose' element."); } if (xe.Attributes.GetNamedItem("Condition") == null) { throw new InvalidProjectFileException("The 'When' element requires a 'Condition' attribute."); } BuildWhen bw = new BuildWhen(xe, project); whens.Add(bw); } else if (xe.Name == "Otherwise") { if (this.whens.Count == 0) { throw new InvalidProjectFileException("At least one 'When' element must occur in a 'Choose' element."); } otherwise = new BuildWhen(xe, project); } } DefinedInFileName = importedProject != null ? importedProject.FullFileName : project != null ? project.FullFileName : null; }
internal Target (XmlElement targetElement, Project project, ImportedProject importedProject) { if (project == null) throw new ArgumentNullException ("project"); if (targetElement == null) throw new ArgumentNullException ("targetElement"); this.targetElement = targetElement; this.name = targetElement.GetAttribute ("Name"); this.project = project; this.engine = project.ParentEngine; this.importedProject = importedProject; this.onErrorElements = new List <XmlElement> (); this.buildState = BuildState.NotStarted; this.buildTasks = new List <BuildTask> (); this.batchingImpl = new TargetBatchingImpl (project, this.targetElement); bool onErrorFound = false; foreach (XmlNode xn in targetElement.ChildNodes) { if (xn is XmlElement) { XmlElement xe = (XmlElement) xn; if (xe.Name == "OnError") { onErrorElements.Add (xe); onErrorFound = true; } else if (onErrorFound) throw new InvalidProjectFileException ( "The element <OnError> must be last under element <Target>. Found element <Error> instead."); #if NET_3_5 else if (xe.Name == "ItemGroup") { //don't blow up for ItemGroups inside Targets in >= 3.5 // TODO: evaluate them (see https://bugzilla.xamarin.com/show_bug.cgi?id=1862 and test in TargetTest.cs ) continue; } #endif else buildTasks.Add (new BuildTask (xe, this)); } } }
internal BuildItemGroup (XmlElement xmlElement, Project project, ImportedProject importedProject, bool readOnly) { this.buildItems = new List <BuildItem> (); this.importedProject = importedProject; this.itemGroupElement = xmlElement; this.parentProject = project; this.read_only = readOnly; if (!FromXml) return; foreach (XmlNode xn in xmlElement.ChildNodes) { if (!(xn is XmlElement)) continue; XmlElement xe = (XmlElement) xn; BuildItem bi = new BuildItem (xe, this); buildItems.Add (bi); project.LastItemGroupContaining [bi.Name] = this; } }
// FIXME: condition internal void Evaluate (bool ignoreMissingImports) { string filename = evaluatedProjectPath; // NOTE: it's a hack to transform Microsoft.CSharp.Targets to Microsoft.CSharp.targets if (Path.HasExtension (filename)) filename = Path.ChangeExtension (filename, Path.GetExtension (filename)); if (!File.Exists (filename)) { if (ignoreMissingImports) { project.LogWarning (project.FullFileName, "Could not find project file {0}, to import. Ignoring.", filename); return; } else { throw new InvalidProjectFileException (String.Format ("Imported project: \"{0}\" does not exist.", filename)); } } ImportedProject importedProject = new ImportedProject (); importedProject.Load (filename); project.ProcessElements (importedProject.XmlDocument.DocumentElement, importedProject); }
// FIXME: condition internal void Evaluate() { string filename = evaluatedProjectPath; // NOTE: it's a hack to transform Microsoft.CSharp.Targets to Microsoft.CSharp.targets if (Path.HasExtension(filename)) { filename = Path.ChangeExtension(filename, Path.GetExtension(filename)); } if (!File.Exists(filename)) { throw new InvalidProjectFileException(String.Format("Imported project: \"{0}\" does not exist.", filename)); } ImportedProject importedProject = new ImportedProject(); importedProject.Load(filename); project.ProcessElements(importedProject.XmlDocument.DocumentElement, importedProject); }
// if @alternateProjectPath is available then that it used as the EvaluatedProjectPath! internal Import (XmlElement importElement, string alternateProjectPath, Project project, ImportedProject originalProject) { if (importElement == null) throw new ArgumentNullException ("importElement"); if (project == null) throw new ArgumentNullException ("project"); this.project = project; this.importElement = importElement; this.originalProject = originalProject; if (ProjectPath == String.Empty) throw new InvalidProjectFileException ("The required attribute \"Project\" is missing from element <Import>."); if (ConditionParser.ParseAndEvaluate (Condition, project)) { evaluatedProjectPath = String.IsNullOrEmpty (alternateProjectPath) ? EvaluateProjectPath (ProjectPath) : alternateProjectPath; evaluatedProjectPath = GetFullPath (); if (EvaluatedProjectPath == String.Empty) throw new InvalidProjectFileException ("The required attribute \"Project\" is missing from element <Import>."); } }
internal UsingTask(XmlElement usingTaskElement, Project project, ImportedProject importedProject) { this.project = project; this.importedProject = importedProject; this.usingTaskElement = usingTaskElement; if (project == null) { throw new ArgumentNullException("project"); } if (usingTaskElement == null) { throw new ArgumentNullException("usingTaskElement"); } if (AssemblyName != null && AssemblyFile != null) { throw new InvalidProjectFileException("A <UsingTask> element must contain either the \"AssemblyName\" attribute or the \"AssemblyFile\" attribute (but not both). "); } if (TaskName == String.Empty) { throw new InvalidProjectFileException("The required attribute \"TaskName\" is missing from element <UsingTask>. "); } }
/// <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; }
internal BuildItemGroup (XmlElement xmlElement, Project project, ImportedProject importedProject, bool readOnly) : this (xmlElement, project, importedProject, readOnly, false) { }
internal BuildItemGroup(XmlElement xmlElement, Project project, ImportedProject importedProject, bool readOnly) : this(xmlElement, project, importedProject, readOnly, false) { }
// For every extension path, in order, finds suitable // import filename(s) matching the Import, and calls // @func with them // // func: bool func(importPath, from_source_msg) // // If for an extension path, atleast one file gets imported, // then it stops at that. // So, in case imports like "$(MSBuildExtensionsPath)\foo\*", // for every extension path, it will try to import the "foo\*", // and if atleast one file gets successfully imported, then it // stops at that internal static void ForEachExtensionPathTillFound (XmlElement xmlElement, Project project, ImportedProject importingProject, Func<string, string, bool> func) { string project_attribute = xmlElement.GetAttribute ("Project"); string condition_attribute = xmlElement.GetAttribute ("Condition"); bool has_extn_ref = project_attribute.IndexOf ("$(MSBuildExtensionsPath)") >= 0 || project_attribute.IndexOf ("$(MSBuildExtensionsPath32)") >= 0 || project_attribute.IndexOf ("$(MSBuildExtensionsPath64)") >= 0; string importingFile = importingProject != null ? importingProject.FullFileName : project.FullFileName; DirectoryInfo base_dir_info = null; if (!String.IsNullOrEmpty (importingFile)) base_dir_info = new DirectoryInfo (Path.GetDirectoryName (importingFile)); else base_dir_info = new DirectoryInfo (Directory.GetCurrentDirectory ()); IEnumerable<string> extn_paths = has_extn_ref ? GetExtensionPaths (project) : new string [] {null}; bool import_needed = false; try { foreach (string path in extn_paths) { string extn_msg = null; if (has_extn_ref) { project.SetExtensionsPathProperties (path); extn_msg = "from extension path " + path; } // do this after setting new Extension properties, as condition might // reference it if (!ConditionParser.ParseAndEvaluate (condition_attribute, project)) continue; import_needed = true; // We stop if atleast one file got imported. // Remaining extension paths are *not* tried bool atleast_one = false; foreach (string importPath in GetImportPathsFromString (project_attribute, project, base_dir_info)) { try { if (func (importPath, extn_msg)) atleast_one = true; } catch (Exception e) { throw new InvalidProjectFileException (String.Format ( "{0}: Project file could not be imported, it was being imported by " + "{1}: {2}", importPath, importingFile, e.Message), e); } } if (atleast_one) return; } } finally { if (has_extn_ref) project.SetExtensionsPathProperties (Project.DefaultExtensionsPath); } if (import_needed) throw new InvalidProjectFileException (String.Format ("{0} could not import \"{1}\"", importingFile, project_attribute)); }
internal Import (XmlElement importElement, Project project, ImportedProject originalProject) : this (importElement, null, project, originalProject) {}
// For every extension path, in order, finds suitable // import filename(s) matching the Import, and calls // @func with them // // func: bool func(importPath, from_source_msg) // // If for an extension path, atleast one file gets imported, // then it stops at that. // So, in case imports like "$(MSBuildExtensionsPath)\foo\*", // for every extension path, it will try to import the "foo\*", // and if atleast one file gets successfully imported, then it // stops at that internal static void ForEachExtensionPathTillFound(XmlElement xmlElement, Project project, ImportedProject importingProject, Func <string, string, bool> func) { string project_attribute = xmlElement.GetAttribute("Project"); string condition_attribute = xmlElement.GetAttribute("Condition"); // Visual Studio project files use a property called VCTargetsPath, that is defined in the // registry under the key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\4.0. // Override it as xbuild doesn't know about it. bool has_vc_ref = project_attribute.IndexOf("$(VCTargetsPath)") >= 0; if (has_vc_ref) { project_attribute = project_attribute.Replace("$(VCTargetsPath)", "$(MSBuildExtensionsPath)"); } bool has_extn_ref = project_attribute.IndexOf("$(MSBuildExtensionsPath)") >= 0 || project_attribute.IndexOf("$(MSBuildExtensionsPath32)") >= 0 || project_attribute.IndexOf("$(MSBuildExtensionsPath64)") >= 0; string importingFile = importingProject != null ? importingProject.FullFileName : project.FullFileName; DirectoryInfo base_dir_info = null; if (!String.IsNullOrEmpty(importingFile)) { base_dir_info = new DirectoryInfo(Path.GetDirectoryName(importingFile)); } else { base_dir_info = new DirectoryInfo(Directory.GetCurrentDirectory()); } IEnumerable <string> extn_paths = has_extn_ref ? GetExtensionPaths(project) : new string [] { null }; try { foreach (string path in extn_paths) { string extn_msg = null; if (has_extn_ref) { project.SetExtensionsPathProperties(path); extn_msg = "from extension path " + path; } // do this after setting new Extension properties, as condition might // reference it if (!ConditionParser.ParseAndEvaluate(condition_attribute, project)) { continue; } // We stop if atleast one file got imported. // Remaining extension paths are *not* tried bool atleast_one = false; foreach (string importPath in GetImportPathsFromString(project_attribute, project, base_dir_info)) { try { if (func(importPath, extn_msg)) { atleast_one = true; } } catch (Exception e) { throw new InvalidProjectFileException(String.Format( "{0}: Project file could not be imported, it was being imported by " + "{1}: {2}", importPath, importingFile, e.Message), e); } } if (atleast_one) { return; } } } finally { if (has_extn_ref) { project.SetExtensionsPathProperties(Project.DefaultExtensionsPath); } } }
// For every extension path, in order, finds suitable // import filename(s) matching the Import, and calls // @func with them // // func: bool func(importPath, from_source_msg) // // If for an extension path, atleast one file gets imported, // then it stops at that. // So, in case imports like "$(MSBuildExtensionsPath)\foo\*", // for every extension path, it will try to import the "foo\*", // and if atleast one file gets successfully imported, then it // stops at that internal static void ForEachExtensionPathTillFound(XmlElement xmlElement, Project project, ImportedProject importingProject, Func <string, string, bool> func) { string project_attribute = xmlElement.GetAttribute("Project"); string condition_attribute = xmlElement.GetAttribute("Condition"); bool has_extn_ref = project_attribute.IndexOf("$(MSBuildExtensionsPath)") >= 0 || project_attribute.IndexOf("$(MSBuildExtensionsPath32)") >= 0 || project_attribute.IndexOf("$(MSBuildExtensionsPath64)") >= 0; bool condn_has_extn_ref = condition_attribute.IndexOf("$(MSBuildExtensionsPath)") >= 0 || condition_attribute.IndexOf("$(MSBuildExtensionsPath32)") >= 0 || condition_attribute.IndexOf("$(MSBuildExtensionsPath64)") >= 0; // we can skip the following logic in case the condition doesn't reference any extension paths // and it evaluates to false since nothing would change anyway if (!condn_has_extn_ref && !ConditionParser.ParseAndEvaluate(condition_attribute, project)) { return; } string importingFile = importingProject != null ? importingProject.FullFileName : project.FullFileName; DirectoryInfo base_dir_info = null; if (!String.IsNullOrEmpty(importingFile)) { base_dir_info = new DirectoryInfo(Path.GetDirectoryName(importingFile)); } else { base_dir_info = new DirectoryInfo(Directory.GetCurrentDirectory()); } var importPaths = GetImportPathsFromString(project_attribute, project, base_dir_info); var extensionPaths = GetExtensionPaths(project); if (!has_extn_ref) { foreach (var importPath in importPaths) { foreach (var extensionPath in extensionPaths) { has_extn_ref = has_extn_ref || importPath.IndexOf(extensionPath) >= 0; } } } IEnumerable <string> extn_paths = has_extn_ref ? extensionPaths : new string [] { null }; bool import_needed = false; var currentLoadSettings = project.ProjectLoadSettings; try { foreach (var settings in new ProjectLoadSettings [] { ProjectLoadSettings.None, currentLoadSettings }) { foreach (string path in extn_paths) { string extn_msg = null; if (has_extn_ref) { project.SetExtensionsPathProperties(path); extn_msg = "from extension path " + path; } // do this after setting new Extension properties, as condition might // reference it if (!ConditionParser.ParseAndEvaluate(condition_attribute, project)) { continue; } import_needed = true; project.ProjectLoadSettings = settings; // We stop if atleast one file got imported. // Remaining extension paths are *not* tried bool atleast_one = false; foreach (string importPath in importPaths) { try { if (func(importPath, extn_msg)) { atleast_one = true; } } catch (Exception e) { throw new InvalidProjectFileException(String.Format( "{0}: Project file could not be imported, it was being imported by " + "{1}: {2}", importPath, importingFile, e.Message), e); } } if (atleast_one) { return; } } } } finally { project.ProjectLoadSettings = currentLoadSettings; if (has_extn_ref) { project.SetExtensionsPathProperties(Project.DefaultExtensionsPath); } } if (import_needed) { throw new InvalidProjectFileException(String.Format("{0} could not import \"{1}\"", importingFile, project_attribute)); } }