/// <summary> /// Parse a ProjectOutputElement /// </summary> private ProjectOutputElement ParseProjectOutputElement(XmlElementWithLocation element, ProjectTaskElement parent) { ProjectXmlUtilities.VerifyThrowProjectAttributes(element, s_validAttributesOnOutput); ProjectXmlUtilities.VerifyThrowProjectRequiredAttribute(element, XMakeAttributes.taskParameter); ProjectXmlUtilities.VerifyThrowProjectNoChildElements(element); string taskParameter = element.GetAttribute(XMakeAttributes.taskParameter); string itemName = element.GetAttribute(XMakeAttributes.itemName); string propertyName = element.GetAttribute(XMakeAttributes.propertyName); ProjectErrorUtilities.VerifyThrowInvalidProject ( (itemName.Length > 0 || propertyName.Length > 0) && (itemName.Length == 0 || propertyName.Length == 0), element.Location, "InvalidTaskOutputSpecification", parent.Name ); ProjectXmlUtilities.VerifyThrowProjectAttributeEitherMissingOrNotEmpty(element, XMakeAttributes.itemName); ProjectXmlUtilities.VerifyThrowProjectAttributeEitherMissingOrNotEmpty(element, XMakeAttributes.propertyName); ProjectErrorUtilities.VerifyThrowInvalidProject(!ReservedPropertyNames.IsReservedProperty(propertyName), element.Location, "CannotModifyReservedProperty", propertyName); return(new ProjectOutputElement(element, parent, _project)); }
/// <summary> /// Parse a ProjectExtensionsElement /// </summary> private ProjectSdkElement ParseProjectSdkElement(XmlElementWithLocation element) { if (string.IsNullOrEmpty(element.GetAttribute(XMakeAttributes.sdkName))) { ProjectErrorUtilities.ThrowInvalidProject(element.Location, "InvalidSdkElementName", element.Name); } return(new ProjectSdkElement(element, _project, _project)); }
/// <summary> /// Parse a ProjectItemElement /// </summary> private ProjectItemElement ParseProjectItemElement(XmlElementWithLocation element, ProjectItemGroupElement parent) { ProjectXmlUtilities.VerifyThrowProjectAttributes(element, s_validAttributesOnItem); bool belowTarget = parent.Parent is ProjectTargetElement; string itemType = element.Name; string include = element.GetAttribute(XMakeAttributes.include); string exclude = element.GetAttribute(XMakeAttributes.exclude); string remove = element.GetAttribute(XMakeAttributes.remove); // Remove must be missing, unless inside a target and Include is missing ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute((remove.Length == 0 || (belowTarget && include.Length == 0)), (XmlAttributeWithLocation)element.Attributes[XMakeAttributes.remove]); // Include must be present, unless inside a target ProjectErrorUtilities.VerifyThrowInvalidProject(include.Length > 0 || belowTarget, element.Location, "MissingRequiredAttribute", XMakeAttributes.include, itemType); // Exclude must be missing, unless Include exists ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute(exclude.Length == 0 || include.Length > 0, (XmlAttributeWithLocation)element.Attributes[XMakeAttributes.exclude]); // If we have an Include attribute at all, it must have non-zero length ProjectErrorUtilities.VerifyThrowInvalidProject(include.Length > 0 || element.Attributes[XMakeAttributes.include] == null, element.Location, "MissingRequiredAttribute", XMakeAttributes.include, itemType); XmlUtilities.VerifyThrowProjectValidElementName(element); ProjectErrorUtilities.VerifyThrowInvalidProject(XMakeElements.IllegalItemPropertyNames[itemType] == null, element.Location, "CannotModifyReservedItem", itemType); ProjectItemElement item = new ProjectItemElement(element, parent, _project); foreach (XmlElementWithLocation childElement in ProjectXmlUtilities.GetVerifyThrowProjectChildElements(element)) { ProjectMetadataElement metadatum = ParseProjectMetadataElement(childElement, item); item.AppendParentedChildNoChecks(metadatum); } return(item); }
/// <summary> /// Parse a ProjectItemElement /// </summary> private ProjectItemElement ParseProjectItemElement(XmlElementWithLocation element, ProjectItemGroupElement parent) { ProjectXmlUtilities.VerifyThrowProjectAttributes(element, s_validAttributesOnItem); bool belowTarget = parent.Parent is ProjectTargetElement; string itemType = element.Name; string include = element.GetAttribute(XMakeAttributes.include); string exclude = element.GetAttribute(XMakeAttributes.exclude); string remove = element.GetAttribute(XMakeAttributes.remove); string update = element.GetAttribute(XMakeAttributes.update); var exclusiveItemOperation = ""; int exclusiveAttributeCount = 0; if (element.HasAttribute(XMakeAttributes.include)) { exclusiveAttributeCount++; exclusiveItemOperation = XMakeAttributes.include; } if (element.HasAttribute(XMakeAttributes.remove)) { exclusiveAttributeCount++; exclusiveItemOperation = XMakeAttributes.remove; } if (element.HasAttribute(XMakeAttributes.update)) { exclusiveAttributeCount++; exclusiveItemOperation = XMakeAttributes.update; } // At most one of the include, remove, or update attributes may be specified if (exclusiveAttributeCount > 1) { XmlAttributeWithLocation errorAttribute = remove.Length > 0 ? (XmlAttributeWithLocation)element.Attributes[XMakeAttributes.remove] : (XmlAttributeWithLocation)element.Attributes[XMakeAttributes.update]; ProjectErrorUtilities.ThrowInvalidProject(errorAttribute.Location, "InvalidAttributeExclusive"); } // Include, remove, or update must be present unless inside a target ProjectErrorUtilities.VerifyThrowInvalidProject(exclusiveAttributeCount == 1 || belowTarget, element.Location, "MissingRequiredAttribute", exclusiveItemOperation, itemType); // Exclude must be missing, unless Include exists ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute(exclude.Length == 0 || include.Length > 0, (XmlAttributeWithLocation)element.Attributes[XMakeAttributes.exclude]); // If we have an Include attribute at all, it must have non-zero length ProjectErrorUtilities.VerifyThrowInvalidProject(include.Length > 0 || element.Attributes[XMakeAttributes.include] == null, element.Location, "MissingRequiredAttribute", XMakeAttributes.include, itemType); // If we have a Remove attribute at all, it must have non-zero length ProjectErrorUtilities.VerifyThrowInvalidProject(remove.Length > 0 || element.Attributes[XMakeAttributes.remove] == null, element.Location, "MissingRequiredAttribute", XMakeAttributes.remove, itemType); // If we have an Update attribute at all, it must have non-zero length ProjectErrorUtilities.VerifyThrowInvalidProject(update.Length > 0 || element.Attributes[XMakeAttributes.update] == null, element.Location, "MissingRequiredAttribute", XMakeAttributes.update, itemType); XmlUtilities.VerifyThrowProjectValidElementName(element); ProjectErrorUtilities.VerifyThrowInvalidProject(XMakeElements.IllegalItemPropertyNames[itemType] == null, element.Location, "CannotModifyReservedItem", itemType); ProjectItemElement item = new ProjectItemElement(element, parent, _project); foreach (XmlElementWithLocation childElement in ProjectXmlUtilities.GetVerifyThrowProjectChildElements(element)) { ProjectMetadataElement metadatum = ParseProjectMetadataElement(childElement, item); item.AppendParentedChildNoChecks(metadatum); } return item; }
/// <summary> /// Verify that the element has the specified required attribute on it and /// it has a value other than empty string /// </summary> internal static void VerifyThrowProjectRequiredAttribute(XmlElementWithLocation element, string attributeName) { ProjectErrorUtilities.VerifyThrowInvalidProject(element.GetAttribute(attributeName).Length > 0, element.Location, "MissingRequiredAttribute", attributeName, element.Name); }
/// <summary> /// Processes the <Service> element, and add an appropriate reference /// items to the startupServicesItemGroup. /// </summary> /// <owner>RGoel</owner> private void ProcessServiceElement ( XmlElementWithLocation serviceElement, ProjectItemGroupElement startupServicesItemGroup ) { // Make sure this is the <Service> element. error.VerifyThrow((serviceElement != null) && (serviceElement.Name == VSProjectElements.service), "Expected <Service> element."); // Make sure the caller has already created an ProjectItemGroupElement for us to // put the new items in. error.VerifyThrow(startupServicesItemGroup != null, "Received null ProjectItemGroupElement"); // Get the required "ID" attribute. string id = serviceElement.GetAttribute(VSProjectAttributes.id); ProjectErrorUtilities.VerifyThrowInvalidProject((id != null) && (id.Length > 0), serviceElement.Location, "MissingAttribute", VSProjectAttributes.id, VSProjectElements.service); // Remove the "ID" attribute, so it doesn't show up in our loop later. serviceElement.RemoveAttribute(VSProjectAttributes.id); // The <Service> element gets converted to XMake as an item of type "Service". // The "ID" attribute becomes the "Include" for the new item. For // example, // ----------------------------------------------------------------------- // Everett format: // =============== // <Service ID = "ABCD1234-78F4-4F98-AFD6-720DA6E648A2" /> // ----------------------------------------------------------------------- // XMake format: // ============= // <Service Include="ABCD1234-78F4-4F98-AFD6-720DA6E648A2" /> // ----------------------------------------------------------------------- startupServicesItemGroup.AddItem(XMakeProjectStrings.service, ProjectCollection.Escape(id)); // There should be no other attributes on the <Service> element (besides // "ID" which we already took care of). But loop through them // anyway, so we can emit a useful error message. foreach (XmlAttributeWithLocation serviceAttribute in serviceElement.Attributes) { ProjectErrorUtilities.VerifyThrowInvalidProject(false, serviceAttribute.Location, "UnrecognizedAttribute", serviceAttribute.Name, VSProjectElements.service); } // There should be no children of the <Service> element. ProjectXmlUtilities.VerifyThrowProjectNoChildElements(serviceElement); }
/// <summary> /// Processes the <VisualStudioProject> XML element, and everything /// within it. As it is doing this, it will add stuff to the xmakeProject. /// </summary> /// <owner>RGoel</owner> private void ProcessVisualStudioProjectElement ( XmlElementWithLocation visualStudioProjectElement ) { // Make sure this is the <VisualStudioProject> element. error.VerifyThrow((visualStudioProjectElement != null) && (visualStudioProjectElement.Name == VSProjectElements.visualStudioProject), "Expected <VisualStudioProject> element."); // Make sure the caller has given us a valid xmakeProject object. error.VerifyThrow(xmakeProject != null, "Expected valid XMake project object."); // This is just about better error reporting. Detect if the user tried // to convert a VC++ or some other type of project, and give a more friendly // error message. string projectType = visualStudioProjectElement.GetAttribute(VSProjectAttributes.projectType); ProjectErrorUtilities.VerifyThrowInvalidProject((projectType == null) || (projectType.Length == 0), visualStudioProjectElement.Location, "ProjectTypeCannotBeConverted", projectType); // Make sure the <VisualStudioProject> tag doesn't have any attributes. ProjectErrorUtilities.VerifyThrowInvalidProject(!visualStudioProjectElement.HasAttributes, visualStudioProjectElement.Location, "NoAttributesExpected", VSProjectElements.visualStudioProject); bool languageFound = false; // Loop through all the direct children of the <VisualStudioProject> element. foreach(XmlNode visualStudioProjectChildNode in visualStudioProjectElement) { // Handle XML comments under the <VisualStudioProject> node (just ignore them) if ((visualStudioProjectChildNode.NodeType == XmlNodeType.Comment) || (visualStudioProjectChildNode.NodeType == XmlNodeType.Whitespace)) { continue; } if (visualStudioProjectChildNode.NodeType == XmlNodeType.Element) { XmlElementWithLocation visualStudioProjectChildElement = (XmlElementWithLocation)visualStudioProjectChildNode; switch (visualStudioProjectChildElement.Name) { // See if we have a <CSHARP>, <VisualBasic>, or <VISUALJSHARP> element. case VSProjectElements.cSharp: case VSProjectElements.visualJSharp: case VSProjectElements.visualBasic: case VSProjectElements.ECSharp: case VSProjectElements.EVisualBasic: // Make sure this is the first language node we're encountering. ProjectErrorUtilities.VerifyThrowInvalidProject(!languageFound, visualStudioProjectChildElement.Location, "MultipleLanguageNodesNotAllowed", VSProjectElements.visualStudioProject); languageFound = true; this.language = visualStudioProjectChildNode.Name; this.ProcessLanguageElement((XmlElementWithLocation)visualStudioProjectChildElement); break; default: ProjectErrorUtilities.VerifyThrowInvalidProject(false, visualStudioProjectChildElement.Location, "UnrecognizedChildElement", visualStudioProjectChildElement.Name, VSProjectElements.visualStudioProject); break; } } else { ProjectXmlUtilities.ThrowProjectInvalidChildElement(visualStudioProjectChildNode.Name, visualStudioProjectElement.Name, visualStudioProjectElement.Location); } } }
/// <summary> /// Parse a ProjectItemElement /// </summary> private ProjectItemElement ParseProjectItemElement(XmlElementWithLocation element, ProjectItemGroupElement parent) { bool belowTarget = parent.Parent is ProjectTargetElement; string itemType = element.Name; string include = element.GetAttribute(XMakeAttributes.include); string exclude = element.GetAttribute(XMakeAttributes.exclude); string remove = element.GetAttribute(XMakeAttributes.remove); string update = element.GetAttribute(XMakeAttributes.update); var exclusiveItemOperation = ""; int exclusiveAttributeCount = 0; if (element.HasAttribute(XMakeAttributes.include)) { exclusiveAttributeCount++; exclusiveItemOperation = XMakeAttributes.include; } if (element.HasAttribute(XMakeAttributes.remove)) { exclusiveAttributeCount++; exclusiveItemOperation = XMakeAttributes.remove; } if (element.HasAttribute(XMakeAttributes.update)) { exclusiveAttributeCount++; exclusiveItemOperation = XMakeAttributes.update; } // At most one of the include, remove, or update attributes may be specified if (exclusiveAttributeCount > 1) { XmlAttributeWithLocation errorAttribute = remove.Length > 0 ? (XmlAttributeWithLocation)element.Attributes[XMakeAttributes.remove] : (XmlAttributeWithLocation)element.Attributes[XMakeAttributes.update]; ProjectErrorUtilities.ThrowInvalidProject(errorAttribute.Location, "InvalidAttributeExclusive"); } // Include, remove, or update must be present unless inside a target ProjectErrorUtilities.VerifyThrowInvalidProject(exclusiveAttributeCount == 1 || belowTarget, element.Location, "IncludeRemoveOrUpdate", exclusiveItemOperation, itemType); // Exclude must be missing, unless Include exists ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute(exclude.Length == 0 || include.Length > 0, (XmlAttributeWithLocation)element.Attributes[XMakeAttributes.exclude]); // If we have an Include attribute at all, it must have non-zero length ProjectErrorUtilities.VerifyThrowInvalidProject(include.Length > 0 || element.Attributes[XMakeAttributes.include] == null, element.Location, "MissingRequiredAttribute", XMakeAttributes.include, itemType); // If we have a Remove attribute at all, it must have non-zero length ProjectErrorUtilities.VerifyThrowInvalidProject(remove.Length > 0 || element.Attributes[XMakeAttributes.remove] == null, element.Location, "MissingRequiredAttribute", XMakeAttributes.remove, itemType); // If we have an Update attribute at all, it must have non-zero length ProjectErrorUtilities.VerifyThrowInvalidProject(update.Length > 0 || element.Attributes[XMakeAttributes.update] == null, element.Location, "MissingRequiredAttribute", XMakeAttributes.update, itemType); XmlUtilities.VerifyThrowProjectValidElementName(element); ProjectErrorUtilities.VerifyThrowInvalidProject(XMakeElements.IllegalItemPropertyNames[itemType] == null, element.Location, "CannotModifyReservedItem", itemType); ProjectItemElement item = new ProjectItemElement(element, parent, _project); foreach (XmlAttributeWithLocation attribute in element.Attributes) { bool isKnownAttribute; bool isValidMetadataNameInAttribute; CheckMetadataAsAttributeName(attribute.Name, out isKnownAttribute, out isValidMetadataNameInAttribute); if (!isKnownAttribute && !isValidMetadataNameInAttribute) { ProjectXmlUtilities.ThrowProjectInvalidAttribute(attribute); } else if (isValidMetadataNameInAttribute) { ProjectMetadataElement metadatum = _project.CreateMetadataElement(attribute.Name, attribute.Value); metadatum.ExpressedAsAttribute = true; metadatum.Parent = item; item.AppendParentedChildNoChecks(metadatum); } } foreach (XmlElementWithLocation childElement in ProjectXmlUtilities.GetVerifyThrowProjectChildElements(element)) { ProjectMetadataElement metadatum = ParseProjectMetadataElement(childElement, item); item.AppendParentedChildNoChecks(metadatum); } return(item); }
/// <summary> /// Given an element corresponding to a .NET Assembly reference, create the appropriate element in the new project /// </summary> /// <param name="referenceElement"></param> /// <param name="referencesItemGroup"></param> /// <param name="referenceName"></param> /// <returns></returns> private ProjectItemElement ConvertAssemblyReference(XmlElementWithLocation referenceElement, ProjectItemGroupElement referencesItemGroup, string referenceName) { ProjectItemElement newReferenceItem; // This is a regular .NET assembly reference. // This gets added as a new XMake item of type "Reference". The "Include" // attribute is the assembly name, and all the other attributes remain // the same. For example, // ----------------------------------------------------------------------- // Everett format: // =============== // <Reference // Name = "System.Xml" // AssemblyName = "System.Xml" // HintPath = "..\..\binaries\x86chk\bin\i386\System.Xml.dll" // /> // ----------------------------------------------------------------------- // XMake format: // ============= // <Reference Include="System.Xml"> // <Name>System.Xml</Name> // <HintPath>..\..\binaries\x86chk\bin\i386\System.Xml.dll</HintPath> // </Reference> // ----------------------------------------------------------------------- // Get the "AssemblyName" attribute. If not found, just use the value from the // "Name" attribute. This is what the project loading code does in VS. string assemblyName = referenceElement.GetAttribute(VSProjectAttributes.assemblyName); if ((assemblyName == null) || (assemblyName.Length == 0)) { assemblyName = referenceName; } else { // Remove the "AssemblyName" attribute so we don't add it again at // the end. referenceElement.RemoveAttribute(VSProjectAttributes.assemblyName); } // MyType should only be added when System.Windows.Forms is present. If this // reference is seen, then set a flag so we can later add MyType. if (0 == String.Compare("System.Windows.Forms", assemblyName, StringComparison.OrdinalIgnoreCase)) { hasWindowsFormsReference = true; } // Remove hint paths that we think are to RTM or Everett framework assemblies string hintPath = referenceElement.GetAttribute(VSProjectAttributes.hintPath); if (hintPath != null) { hintPath = hintPath.ToUpper(CultureInfo.InvariantCulture); if (hintPath.IndexOf(LegacyFrameworkPaths.RTMFrameworkPath, StringComparison.Ordinal) != -1 || hintPath.IndexOf(LegacyFrameworkPaths.EverettFrameworkPath, StringComparison.Ordinal) != -1 || hintPath.IndexOf(LegacyFrameworkPaths.JSharpRTMFrameworkPath, StringComparison.Ordinal) != -1) { referenceElement.RemoveAttribute(VSProjectAttributes.hintPath); } } newReferenceItem = referencesItemGroup.AddItem(XMakeProjectStrings.reference, ProjectCollection.Escape(assemblyName)); return newReferenceItem; }
/// <summary> /// Processes the <Reference> element, and add an appropriate reference /// items to the referencesItemGroup. /// </summary> /// <owner>RGoel</owner> private void ProcessReferenceElement ( XmlElementWithLocation referenceElement, ProjectItemGroupElement referencesItemGroup ) { // Make sure this is the <Reference> element. error.VerifyThrow((referenceElement != null) && (referenceElement.Name == VSProjectElements.reference), "Expected <Reference> element."); // Make sure the caller has already created an ProjectItemGroupElement for us to // put the new items in. error.VerifyThrow(referencesItemGroup != null, "Received null ProjectItemGroupElement"); // Before we do anything else, look for the "Platform" attribute. // If it's available, we need to remove it, and if it ends in // "-Designer", we need to disregard this reference entirely. string platform = referenceElement.GetAttribute(VSProjectAttributes.platform); if ((platform != null) && (platform.Length > 0)) { if (platform.IndexOf("-Designer", 0, platform.Length, StringComparison.Ordinal) != -1) { return; } referenceElement.RemoveAttribute ( VSProjectAttributes.platform ); } ProjectItemElement newReferenceItem; // Get the "Name" attribute. This is a required attribute in the VS7/ // Everett format. string referenceName = referenceElement.GetAttribute(VSProjectAttributes.name); ProjectErrorUtilities.VerifyThrowInvalidProject((referenceName != null) && (referenceName.Length > 0), referenceElement.Location, "MissingAttribute", VSProjectAttributes.name, VSProjectElements.reference); // Before we go any further, we must special-case some assemblies for VSD projects. if ( ( ( this.language == VSProjectElements.ECSharp ) || ( this.language == VSProjectElements.EVisualBasic ) ) ) { if ( ( this.frameworkVersionForVSD == XMakeProjectStrings.vTwo ) && ( 0 == String.Compare ( referenceName, VSProjectElements.SystemDataCommon, StringComparison.OrdinalIgnoreCase ) ) ) { // We need to remove all references to "System.Data.Common" for VSD projects only. // Note : We only want to do this for projects that will be updated to v2.0 // System.Data.Common is still valid for v1.0 upgraded projects. return; } else if ( 0 == String.Compare ( referenceName, VSProjectElements.SystemSR, StringComparison.OrdinalIgnoreCase ) ) { // We always want to remove all references to "System.SR" return; } } if ( ( this.language == VSProjectElements.EVisualBasic ) && ( 0 == String.Compare ( referenceName, VSProjectElements.MSCorLib, StringComparison.OrdinalIgnoreCase ) ) ) { // We also want to get rid of all 'mscorlib' references for VB projects only. return; } // We need to find out what type of reference this is -- a .NET assembly // reference, a COM reference, or a project reference. In the XMake format, // we use separate item types for each of these. // See if there's a "Guid" attribute on the <Reference> element. If so, // it's a classic COM reference. string comReferenceGuid = referenceElement.GetAttribute(VSProjectAttributes.guid); // See if there's a "Project" guid attribute. If so, it's a project // reference. string referencedProjectGuid = referenceElement.GetAttribute(VSProjectAttributes.project); if ((comReferenceGuid != null) && (comReferenceGuid.Length > 0) && (comReferenceGuid != "{00000000-0000-0000-0000-000000000000}")) { newReferenceItem = ConvertClassicComReference(referenceElement, referencesItemGroup, referenceName); } else if ((referencedProjectGuid != null) && (referencedProjectGuid.Length > 0)) { newReferenceItem = ConvertProjectToProjectReference(referenceElement, referencesItemGroup, referenceName, ref referencedProjectGuid); } else { newReferenceItem = ConvertAssemblyReference(referenceElement, referencesItemGroup, referenceName); } // Add all the rest of the attributes on the <Reference> element to the new // XMake item. foreach (XmlAttribute referenceAttribute in referenceElement.Attributes) { newReferenceItem.AddMetadata(referenceAttribute.Name, ProjectCollection.Escape(referenceAttribute.Value)); } // There should be no children of the <Reference> element. ProjectXmlUtilities.VerifyThrowProjectNoChildElements(referenceElement); }
/// <summary> /// Processes the <Platform> element, and everything within it. As it is /// doing this, it will add stuff to the xmakeProject, including new /// configuration-specific property groups. /// </summary> /// <owner>BCham</owner> private void ProcessPlatformElement ( XmlElementWithLocation platformElement ) { if ( !IsUserFile ) { // Make sure this is the <Platform> element. error.VerifyThrow((platformElement != null) && (platformElement.Name == VSProjectElements.platform), "Expected <Platform> element."); // Make sure the caller has given us a valid xmakeProject object. error.VerifyThrow(xmakeProject != null, "Expected valid XMake project object."); // The platform listed in the <Platform> element will be the platform // used for the Whidbey project. // ----------------------------------------------------------------------- // Everett format: // =============== // <Platform Name = "Pocket PC" /> // ----------------------------------------------------------------------- // XMake format: // ============= // <PropertyGroup> // <Property PlatformFamilyName="PocketPC"/> // <Property PlatformID="3C41C503-53EF-4c2a-8DD4-A8217CAD115E"/> // </PropertyGroup> // ----------------------------------------------------------------------- // Get the "Name" attribute of the <Platform> element. platformForVSD = platformElement.GetAttribute(VSProjectAttributes.name); ProjectErrorUtilities.VerifyThrowInvalidProject((platformForVSD != null) && (platformForVSD.Length > 0), platformElement.Location, "MissingAttribute", VSProjectElements.platform, VSProjectAttributes.name); // Create a new property group, and add all of the XML attributes as XMake // properties. ProjectPropertyGroupElement platformPropertyGroup = xmakeProject.AddPropertyGroup(); string platformID; string platformFamily; frameworkVersionForVSD = XMakeProjectStrings.vOne; switch ( platformForVSD ) { case VSProjectElements.PocketPC: platformID = "3C41C503-53EF-4c2a-8DD4-A8217CAD115E"; platformFamily = "PocketPC"; break; case VSProjectElements.Smartphone: platformID = "4DE813A2-67E0-4a00-945C-3188240A8243"; platformFamily = "Smartphone"; break; case VSProjectElements.WindowsCE: default: // If we're dealing with a platform other than the three that Everett ships with, we'll assign it as Windows CE platformID = "E2BECB1F-8C8C-41ba-B736-9BE7D946A398"; platformFamily = "WindowsCE"; // We don't ship with a v1.0 WindowsCE platform. Default to v2.0 instead. frameworkVersionForVSD = XMakeProjectStrings.vTwo; break; } // Add the properties for PlatformID and PlatformFamilyName platformPropertyGroup.AddProperty(XMakeProjectStrings.platformID, platformID); platformPropertyGroup.AddProperty(XMakeProjectStrings.platformFamilyName, platformFamily); // Since we're here, we know this is a VSD project. Therefore, let's // add a property for the deployment target path. Note, we only need a suffix. // The prefix will be defaulted to based on the selected device. platformPropertyGroup.AddProperty(XMakeProjectStrings.deployTargetSuffix, "$(AssemblyName)" ); // And, we should also set the Target Framework version. For // VSD projects, we want to stay with v1.0 platformPropertyGroup.AddProperty(XMakeProjectStrings.TargetFrameworkVersion, frameworkVersionForVSD); } }
/// <summary> /// Processes the <Config> element, and everything within it. As it is /// doing this, it will add stuff to the xmakeProject, including new /// configuration-specific property groups. /// </summary> /// <owner>RGoel</owner> private void ProcessConfigElement ( XmlElementWithLocation configElement ) { // Make sure this is the <Config> element. error.VerifyThrow((configElement != null) && (configElement.Name == VSProjectElements.config), "Expected <Config> element."); // Make sure the caller has given us a valid xmakeProject object. error.VerifyThrow(xmakeProject != null, "Expected valid XMake project object."); // All of the attributes on the <Config> tag get converted to XMake // properties, except for the "Name" attribute which becomes part of // the "Condition" on the <PropertyGroup>. For example, // ----------------------------------------------------------------------- // Everett format: // =============== // <Config // Name = "Debug" // AllowUnsafeBlocks = "false" // BaseAddress = "285212672" // CheckForOverflowUnderflow = "false" // ConfigurationOverrideFile = "" // DefineConstants = "DEBUG;TRACE" // DocumentationFile = "" // DebugSymbols = "true" // FileAlignment = "4096" // IncrementalBuild = "true" // NoStdLib = "false" // NoWarn = "" // Optimize = "false" // OutputPath = "bin\Debug\" // RegisterForComInterop = "false" // RemoveIntegerChecks = "false" // TreatWarningsAsErrors = "true" // WarningLevel = "4" // /> // ----------------------------------------------------------------------- // XMake format: // ============= // <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> // <AllowUnsafeBlocks>false</AllowUnsafeBlocks> // <BaseAddress>285212672</BaseAddress> // <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow> // <ConfigurationOverrideFile></ConfigurationOverrideFile> // <DefineConstants>DEBUG;TRACE</DefineConstants> // <DocumentationFile></DocumentationFile> // <DebugSymbols>true</DebugSymbols> // <FileAlignment>4096</FileAlignment> // <NoStdLib>false</NoStdLib> // <NoWarn></NoWarn> // <Optimize>false</Optimize> // <OutputPath>bin\Debug\</OutputPath> // <RegisterForComInterop>false</RegisterForComInterop> // <RemoveIntegerChecks>false</RemoveIntegerChecks> // <TreatWarningsAsErrors>true</TreatWarningsAsErrors> // <WarningLevel>4</WarningLevel> // </PropertyGroup> // ----------------------------------------------------------------------- // Get the "Name" attribute of the <Config> element. string configName = configElement.GetAttribute(VSProjectAttributes.name); ProjectErrorUtilities.VerifyThrowInvalidProject((configName != null) && (configName.Length > 0), configElement.Location, "MissingAttribute", VSProjectElements.config, VSProjectAttributes.name); // In the case of VSD projects, the "Name" attribute will have a pipe in it, // followed by the device platform. This last part needs to be removed, // leaving just the config name. if ( ( this.language == VSProjectElements.ECSharp ) || ( this.language == VSProjectElements.EVisualBasic ) ) { int pipeLocation = configName.IndexOf ( '|' ); if ( pipeLocation != -1 ) { configName = configName.Remove ( pipeLocation, configName.Length - pipeLocation ); } } // Remove the "Name" attribute from the <Config> element, so it doesn't get // added as an XMake property. configElement.RemoveAttribute(VSProjectAttributes.name); // PPD@31111: J# Only: We need to remove the AdditionalOptions attribute // (and note it down) before we create the property group out of the configElement string additionalOptionsValue = null; if (VSProjectElements.visualJSharp == this.language) { additionalOptionsValue = configElement.GetAttribute(VSProjectAttributes.additionalOptions); // Dont bother about getting a null value for additionalOptionsValue // GetAttribute return String.Empty if the attribute is not present configElement.RemoveAttribute(VSProjectAttributes.additionalOptions); } // Create a new property group, and add all of the XML attributes as XMake // properties. ProjectPropertyGroupElement configPropertyGroup = xmakeProject.AddPropertyGroup(); // Process OutputPath attribute separately to ensure it contains trailing backslash string outputPath = configElement.GetAttribute(VSProjectAttributes.outputPath); if (outputPath != null && outputPath.Length > 0) { if (outputPath[outputPath.Length-1] != Path.DirectorySeparatorChar) outputPath += Path.DirectorySeparatorChar; configElement.RemoveAttribute(VSProjectAttributes.outputPath); configPropertyGroup.AddProperty(VSProjectAttributes.outputPath, ProjectCollection.Escape(outputPath)); } // If the "SelectedDevice" or "DeploymentPlatform" attributes exist in the per-user // project file, we should get rid of them. string selectedDevice = configElement.GetAttribute ( VSProjectAttributes.selectedDevice ); if ( isUserFile && ( selectedDevice != null ) && ( selectedDevice.Length > 0 ) ) { configElement.RemoveAttribute ( VSProjectAttributes.selectedDevice ); } string deploymentPlatform = configElement.GetAttribute ( VSProjectAttributes.deploymentPlatform ); if ( isUserFile && ( deploymentPlatform != null ) && ( deploymentPlatform.Length > 0 ) ) { configElement.RemoveAttribute ( VSProjectAttributes.deploymentPlatform ); } // Get rid of the "IncrementalBuild" attribute string incrementalBuild = configElement.GetAttribute ( VSProjectAttributes.incrementalBuild ); if (incrementalBuild != null && incrementalBuild.Length > 0) { configElement.RemoveAttribute ( VSProjectAttributes.incrementalBuild ); } // VSWhidbey bug 261464. For VB projects migrated from VS7/Everett, the VB team would // like to enable XML documentation by default (this feature was unavailable to VB users // in VS7/Everett. To enable for VB, set the DocumentationFile property to <assemblyname>.xml if ((!this.isUserFile) && (VSProjectElements.visualBasic == this.language)) { string documentationFile = this.assemblyName + XMakeProjectStrings.xmlFileExtension; configPropertyGroup.AddProperty(VSProjectAttributes.documentationFile, ProjectCollection.Escape(documentationFile)); } // process the rest of Config attributes this.AddXMakePropertiesFromXMLAttributes(configPropertyGroup, configElement); // PPD@31111: J# Only: We now need to parse the additionalOptionsValue for properties and // add the individual properties to configPropertyGroup. // This needs to be done after the AddXMakePropertiesFromXMLAttributes call above since // an property defined in the AdditionalOptions takes precedence. if (VSProjectElements.visualJSharp == this.language) { AdditionalOptionsParser addnlOptParser = new AdditionalOptionsParser(); addnlOptParser.ProcessAdditionalOptions(additionalOptionsValue, configPropertyGroup); } // VSWhidbey bug 302946. For VB projects migrated from VS7/Everett, the VB team would // like to disable the following new warnings for Whidbey: 42016,42017,42018,42019,42032 // New projects created in Whidbey already have these warnings disabled by default. if ((!this.isUserFile) && (VSProjectElements.visualBasic == this.language)) { configPropertyGroup.AddProperty(XMakeProjectStrings.noWarn, XMakeProjectStrings.disabledVBWarnings); } // VSWhidbey bug 472064. For all projects that are converted, if "DebugSymbols" is set for a // particular platform/configuration, we set a "DebugType" property if and only if "DebugType" property // is not already there. DebugType is set to "full" for DebugSymbols=true, DebugType is set to "none" // if DebugSymbols=false, and we don't do anything if DebugSymbols is not present in the source project. if (!this.isUserFile) { string debugType = configElement.GetAttribute(VSProjectAttributes.debugType); if (String.IsNullOrEmpty(debugType)) { string debugSymbols = configElement.GetAttribute(XMakeProjectStrings.debugSymbols); if ( 0 == String.Compare ( debugSymbols, "true", StringComparison.OrdinalIgnoreCase ) ) { configPropertyGroup.AddProperty(VSProjectAttributes.debugType, VSProjectAttributes.debugTypeFull); } else if ( 0 == String.Compare(debugSymbols, "false", StringComparison.OrdinalIgnoreCase) ) { configPropertyGroup.AddProperty(VSProjectAttributes.debugType, VSProjectAttributes.debugTypeNone); } } } // VSWhidbey bug 472064. For all VC# projects that are converted, we add an ErrorReport // property, always set to "prompt" if ( !this.isUserFile && this.language == VSProjectElements.cSharp ) { configPropertyGroup.AddProperty(VSProjectAttributes.errorReport, VSProjectAttributes.errorReportPrompt); } // Platform of course depends on the language we are dealing with - J# in whidbey supports only x86 string platform = (this.language != VSProjectElements.visualJSharp) ? XMakeProjectStrings.defaultPlatform : XMakeProjectStrings.x86Platform; // Add the "Condition" to the new <PropertyGroup>. configPropertyGroup.Condition = XMakeProjectStrings.configplatformPrefix + ProjectCollection.Escape(configName) + XMakeProjectStrings.configplatformSeparator + ProjectCollection.Escape(platform) + XMakeProjectStrings.configplatformSuffix; // Loop through all the direct child elements of the <Config> element. foreach(XmlNode configChildNode in configElement) { // Handle XML comments under the the <Config> node (just ignore them). if ((configChildNode.NodeType == XmlNodeType.Comment) || (configChildNode.NodeType == XmlNodeType.Whitespace)) { continue; } if (configChildNode.NodeType == XmlNodeType.Element) { XmlElementWithLocation configChildElement = (XmlElementWithLocation)configChildNode; switch (configChildElement.Name) { // The <InteropRegistration> element. case VSProjectElements.interopRegistration: this.ProcessInteropRegistrationElement((XmlElementWithLocation)configChildElement, configPropertyGroup); break; default: ProjectErrorUtilities.VerifyThrowInvalidProject(false, configChildElement.Location, "UnrecognizedChildElement", configChildElement.Name, VSProjectElements.config); break; } } else { ProjectXmlUtilities.ThrowProjectInvalidChildElement(configChildNode.Name, configElement.Name, configElement.Location); } } }
/// <summary> /// Processes the <Settings> element, and everything within it. As it is /// doing this, it will add stuff to the xmakeProject. /// </summary> /// <owner>RGoel</owner> private void ProcessSettingsElement ( XmlElementWithLocation settingsElement ) { // Make sure this is the <Settings> element. error.VerifyThrow((settingsElement != null) && (settingsElement.Name == VSProjectElements.settings), "Expected <Settings> element."); // Make sure the caller has given us a valid xmakeProject object. error.VerifyThrow(xmakeProject != null, "Expected valid XMake project object."); // Make sure the caller has given us a valid globalPropertyGroup object. error.VerifyThrow(globalPropertyGroup != null, "Expected valid global ProjectPropertyElementGroup."); // All of the attributes on the <Settings> tag get converted to XMake // properties, except for PreBuildEvent and PostBuildEvent. For example, // ----------------------------------------------------------------------- // Everett format: // =============== // <Settings // ApplicationIcon = "" // AssemblyKeyContainerName = "" // AssemblyName = "XMakeBuildEngine" // AssemblyOriginatorKeyFile = "" // DefaultClientScript = "JScript" // DefaultHTMLPageLayout = "Grid" // DefaultTargetSchema = "IE50" // DelaySign = "false" // OutputType = "Library" // PreBuildEvent = "" // PostBuildEvent = "..\..\PostBuildEvent.bat" // RootNamespace = "XMakeBuildEngine" // RunPostBuildEvent = "OnBuildSuccess" // StartupObject = "" // > // ... // ... // ... // </Settings> // ----------------------------------------------------------------------- // XMake format: // ============= // <PropertyGroup> // <ApplicationIcon></ApplicationIcon> // <AssemblyKeyContainerName></AssemblyKeyContainerName> // <AssemblyName>XMakeBuildEngine</AssemblyName> // <AssemblyOriginatorKeyFile></AssemblyOriginatorKeyFile> // <DefaultClientScript>JScript</DefaultClientScript> // <DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout> // <DefaultTargetSchema>IE50</DefaultTargetSchema> // <DelaySign>false</DelaySign> // <OutputType>Library</OutputType> // <RootNamespace>XMakeBuildEngine</RootNamespace> // <RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent> // <StartupObject></StartupObject> // </PropertyGroup> // ----------------------------------------------------------------------- // The "PreBuildEvent" and "PostBuildEvent" properties need to be handled // specially. These can contain references to predefined macros, such // as "$(ProjectDir)". But these get defined in Microsoft.CSharp.targets, so the // "PreBuildEvent" and "PostBuildEvent" properties need to get added to // the project file *after* the <Import> for Microsoft.CSharp.targets. For now, // just save the values of these two properties. this.preBuildEvent = settingsElement.GetAttribute(VSProjectAttributes.preBuildEvent); settingsElement.RemoveAttribute(VSProjectAttributes.preBuildEvent); this.postBuildEvent = settingsElement.GetAttribute(VSProjectAttributes.postBuildEvent); settingsElement.RemoveAttribute(VSProjectAttributes.postBuildEvent); // cache the assembly name in case its needed to upgrade the // documentation file property) this.assemblyName = settingsElement.GetAttribute(VSProjectAttributes.assemblyName); // cache the output type. this.outputType = settingsElement.GetAttribute(XMakeProjectStrings.outputType); // Take care of copying all the other normal properties. this.AddXMakePropertiesFromXMLAttributes(this.globalPropertyGroup, settingsElement); // Loop through all the direct child elements of the <Build> element. foreach(XmlNode settingsChildNode in settingsElement) { // Handle XML comments under the the <Settings> node (just ignore them). if ((settingsChildNode.NodeType == XmlNodeType.Comment) || (settingsChildNode.NodeType == XmlNodeType.Whitespace)) { continue; } if (settingsChildNode.NodeType == XmlNodeType.Element) { XmlElementWithLocation settingsChildElement = (XmlElementWithLocation)settingsChildNode; switch (settingsChildElement.Name) { // The <Config> element. case VSProjectElements.config: this.ProcessConfigElement(settingsChildElement); break; // In the case of a VSD project, the <Platform> element case VSProjectElements.platform: this.ProcessPlatformElement(settingsChildElement); break; default: ProjectErrorUtilities.VerifyThrowInvalidProject(false, settingsChildElement.Location, "UnrecognizedChildElement", settingsChildElement.Name, VSProjectElements.settings); break; } } else { ProjectXmlUtilities.ThrowProjectInvalidChildElement(settingsChildNode.Name, settingsElement.Name, settingsElement.Location); } } }
/// <summary> /// Processes the language (e.g. <CSHARP>) XML element, and everything /// within it. As it is doing this, it will add stuff to the xmakeProject. /// </summary> /// <owner>RGoel</owner> private void ProcessLanguageElement ( XmlElementWithLocation languageElement ) { // Make sure we have a valid XML element to process. error.VerifyThrow(languageElement != null, "Expected valid XML language element."); // Make sure the caller has given us a valid xmakeProject object. error.VerifyThrow(xmakeProject != null, "Expected valid XMake project object."); // Get the project instance GUID for this project file. It is required for // the main project file, but not for the .USER file. this.projectGuid = languageElement.GetAttribute(VSProjectAttributes.projectGuid); ProjectErrorUtilities.VerifyThrowInvalidProject((this.projectGuid != null) || (this.isUserFile == true), languageElement.Location, "MissingAttribute", languageElement.Name, VSProjectAttributes.projectGuid); // Get the project type for this project file. We only support "Local". We do not // convert web projects -- that's Venus's job. string projectType = languageElement.GetAttribute(VSProjectAttributes.projectType); ProjectErrorUtilities.VerifyThrowInvalidProject(projectType == null || projectType.Length == 0 || (String.Compare(projectType, VSProjectAttributes.local, StringComparison.OrdinalIgnoreCase) == 0), languageElement.Location, "ProjectTypeCannotBeConverted", projectType); // All of the attributes on the language tag get converted to XMake // properties. A couple exceptions ... for the "ProductVersion" // and "SchemaVersion" properties, we don't just copy the previous // value; we actually set it to 8.0.##### and 2.0 respectively. // In addition, we also add a default value for the "Configuration" // property. For example, // ----------------------------------------------------------------------- // Everett format: // =============== // <CSHARP // ProjectType = "Local" // ProductVersion = "7.10.2284" // SchemaVersion = "1.0" // ProjectGuid = "{71F4C768-901B-4027-BD9D-378665D6C0B2}" // > // ... // ... // ... // </CSHARP> // ----------------------------------------------------------------------- // XMake format: // ============= // <PropertyGroup> // <ProjectType>Local</ProjectType> // <ProductVersion>8.0.31031</ProductVersion> // <SchemaVersion>2.0</SchemaVersion> // <ProjectGuid>{71F4C768-901B-4027-BD9D-378665D6C0B2}</ProjectGuid> // <Configuration Condition = " '$(Configuration)' == '' ">Debug</Configuration> // </PropertyGroup> // ----------------------------------------------------------------------- // For Dev11, we are removing "ProductVersion" and "SchemaVersion" from all // project templates. Thus, eliminated writing these tags from this method. // ----------------------------------------------------------------------- string originalMyType = languageElement.GetAttribute(XMakeProjectStrings.myType); if ((originalMyType != null) && (originalMyType.Length != 0)) { // Flag the fact that the Everett project already had a MyType property in there, // so we don't try to override it later. this.isMyTypeAlreadySetInOriginalProject = true; } // Copy over all the other properties. this.globalPropertyGroup = xmakeProject.AddPropertyGroup(); this.AddXMakePropertiesFromXMLAttributes(this.globalPropertyGroup, languageElement); // Add the "Configuration" property. Put a condition on it so it only gets // set to the default if the user doesn't have an environment variable called // "Configuration". The final XML looks something like this: // <Configuration Condition = " '$(Configuration)' == '' ">Debug</Configuration> ProjectPropertyElement configurationProperty = this.globalPropertyGroup.AddProperty( XMakeProjectStrings.configuration, XMakeProjectStrings.defaultConfiguration); configurationProperty.Condition = XMakeProjectStrings.configurationPrefix + XMakeProjectStrings.configurationSuffix; // Add the "Platform" property. Put a condition on it so it only gets // set to the default if the user doesn't have an environment variable called // "Platform". The final XML looks something like this: // <Property Platform = "AnyCPU" Condition = " '$(Platform)' == '' " /> // Platform of course depends on the language we are dealing with - J# in whidbey supports only x86 string platform = (this.language != VSProjectElements.visualJSharp) ? XMakeProjectStrings.defaultPlatform : XMakeProjectStrings.x86Platform; ProjectPropertyElement platformProperty = this.globalPropertyGroup.AddProperty( XMakeProjectStrings.platform, platform); platformProperty.Condition = XMakeProjectStrings.platformPrefix + XMakeProjectStrings.platformSuffix; bool isTriumphProject = false; // For SDE projects, we need to add a special <ProjectTypeGuids> property to // the project file. This will contain the project types for both the // flavor and the main language project type. In addition, SDE projects // need to have the host process disabled. if (!this.isUserFile) { if (languageElement.Name == VSProjectElements.ECSharp) { this.globalPropertyGroup.AddProperty ( XMakeProjectStrings.projectTypeGuids, "{" + XMakeProjectStrings.VSDCSProjectTypeGuid + "};{" + XMakeProjectStrings.cSharpGuid + "}" ); string visualStudioProjectExtensions = GetProjectExtensionsString(XMakeProjectStrings.visualStudio); visualStudioProjectExtensions += XMakeProjectStrings.disableCSHostProc; SetProjectExtensionsString(XMakeProjectStrings.visualStudio, visualStudioProjectExtensions); } else if (languageElement.Name == VSProjectElements.EVisualBasic) { this.globalPropertyGroup.AddProperty ( XMakeProjectStrings.projectTypeGuids, "{" + XMakeProjectStrings.VSDVBProjectTypeGuid + "};{" + XMakeProjectStrings.visualBasicGuid + "}" ); string visualStudioProjectExtensions = GetProjectExtensionsString(XMakeProjectStrings.visualStudio); visualStudioProjectExtensions += XMakeProjectStrings.disableVBHostProc; SetProjectExtensionsString(XMakeProjectStrings.visualStudio, visualStudioProjectExtensions); } } // Loop through all the direct child elements of the language element. foreach(XmlNode languageChildNode in languageElement) { // Handle XML comments under the the language node (just ignore them). if ((languageChildNode.NodeType == XmlNodeType.Comment) || (languageChildNode.NodeType == XmlNodeType.Whitespace)) { continue; } if (languageChildNode.NodeType == XmlNodeType.Element) { XmlElementWithLocation languageChildElement = (XmlElementWithLocation)languageChildNode; switch (languageChildElement.Name) { // The <Build> element. case VSProjectElements.build: this.ProcessBuildElement((XmlElementWithLocation)languageChildElement); break; case VSProjectElements.files: this.ProcessFilesElement((XmlElementWithLocation)languageChildElement); break; case VSProjectElements.startupServices: this.ProcessStartupServicesElement((XmlElementWithLocation)languageChildElement); break; case VSProjectElements.userProperties: this.ProcessUserPropertiesElement((XmlElementWithLocation)languageChildElement, out isTriumphProject); break; case VSProjectElements.otherProjectSettings: this.ProcessOtherProjectSettingsElement((XmlElementWithLocation)languageChildElement); break; default: ProjectErrorUtilities.VerifyThrowInvalidProject(false, languageChildElement.Location, "UnrecognizedChildElement", languageChildNode.Name, languageElement.Name); break; } } else { ProjectXmlUtilities.ThrowProjectInvalidChildElement(languageChildNode.Name, languageElement.Name, languageElement.Location); } } AddFinalPropertiesAndImports(languageElement, isTriumphProject); }
/// <summary> /// Parse a ProjectUsingTaskElement /// </summary> private ProjectUsingTaskElement ParseProjectUsingTaskElement(XmlElementWithLocation element) { ProjectXmlUtilities.VerifyThrowProjectAttributes(element, s_validAttributesOnUsingTask); ProjectErrorUtilities.VerifyThrowInvalidProject(element.GetAttribute(XMakeAttributes.taskName).Length > 0, element.Location, "ProjectTaskNameEmpty"); string assemblyName = element.GetAttribute(XMakeAttributes.assemblyName); string assemblyFile = element.GetAttribute(XMakeAttributes.assemblyFile); ProjectErrorUtilities.VerifyThrowInvalidProject ( ((assemblyName.Length > 0) ^ (assemblyFile.Length > 0)), element.Location, "UsingTaskAssemblySpecification", XMakeElements.usingTask, XMakeAttributes.assemblyName, XMakeAttributes.assemblyFile ); ProjectXmlUtilities.VerifyThrowProjectAttributeEitherMissingOrNotEmpty(element, XMakeAttributes.assemblyName); ProjectXmlUtilities.VerifyThrowProjectAttributeEitherMissingOrNotEmpty(element, XMakeAttributes.assemblyFile); ProjectUsingTaskElement usingTask = new ProjectUsingTaskElement(element, _project, _project); bool foundTaskElement = false; bool foundParameterGroup = false; foreach (XmlElementWithLocation childElement in ProjectXmlUtilities.GetVerifyThrowProjectChildElements(element)) { ProjectElement child = null; string childElementName = childElement.Name; switch (childElementName) { case XMakeElements.usingTaskParameterGroup: if (foundParameterGroup) { ProjectXmlUtilities.ThrowProjectInvalidChildElementDueToDuplicate(childElement); } child = ParseUsingTaskParameterGroupElement(childElement, usingTask); foundParameterGroup = true; break; case XMakeElements.usingTaskBody: if (foundTaskElement) { ProjectXmlUtilities.ThrowProjectInvalidChildElementDueToDuplicate(childElement); } child = ParseUsingTaskBodyElement(childElement, usingTask); foundTaskElement = true; break; default: ProjectXmlUtilities.ThrowProjectInvalidChildElement(childElement.Name, element.Name, element.Location); break; } usingTask.AppendParentedChildNoChecks(child); } return usingTask; }
/// <summary> /// Parse a ProjectOutputElement /// </summary> private ProjectOutputElement ParseProjectOutputElement(XmlElementWithLocation element, ProjectTaskElement parent) { ProjectXmlUtilities.VerifyThrowProjectAttributes(element, s_validAttributesOnOutput); ProjectXmlUtilities.VerifyThrowProjectRequiredAttribute(element, XMakeAttributes.taskParameter); ProjectXmlUtilities.VerifyThrowProjectNoChildElements(element); string taskParameter = element.GetAttribute(XMakeAttributes.taskParameter); string itemName = element.GetAttribute(XMakeAttributes.itemName); string propertyName = element.GetAttribute(XMakeAttributes.propertyName); ProjectErrorUtilities.VerifyThrowInvalidProject ( (itemName.Length > 0 || propertyName.Length > 0) && (itemName.Length == 0 || propertyName.Length == 0), element.Location, "InvalidTaskOutputSpecification", parent.Name ); ProjectXmlUtilities.VerifyThrowProjectAttributeEitherMissingOrNotEmpty(element, XMakeAttributes.itemName); ProjectXmlUtilities.VerifyThrowProjectAttributeEitherMissingOrNotEmpty(element, XMakeAttributes.propertyName); ProjectErrorUtilities.VerifyThrowInvalidProject(!ReservedPropertyNames.IsReservedProperty(propertyName), element.Location, "CannotModifyReservedProperty", propertyName); return new ProjectOutputElement(element, parent, _project); }
/// <summary> /// Processes the <Import> element, and add an appropriate reference /// items to the importsItemGroup. /// </summary> /// <owner>RGoel</owner> private void ProcessImportElement ( XmlElementWithLocation importElement, ProjectItemGroupElement importsItemGroup ) { // Make sure this is the <Import> element. error.VerifyThrow((importElement != null) && (importElement.Name == VSProjectElements.import), "Expected <Import> element."); // Make sure the caller has already created an ProjectItemGroupElement for us to // put the new items in. error.VerifyThrow(importsItemGroup != null, "Received null ProjectItemGroupElement"); // Get the required "Namespace" attribute. string importNamespace = importElement.GetAttribute(VSProjectAttributes.importNamespace); ProjectErrorUtilities.VerifyThrowInvalidProject((importNamespace != null) && (importNamespace.Length > 0), importElement.Location, "MissingAttribute", VSProjectAttributes.importNamespace, VSProjectElements.import); // Remove the "Namespace" attribute, so it doesn't show up in our loop later. importElement.RemoveAttribute(VSProjectAttributes.importNamespace); // The <Import> element gets converted to XMake as an item of type "Import". // The "Namespace" attribute becomes the "Include" for the new item. For // example, // ----------------------------------------------------------------------- // Everett format: // =============== // <Import Namespace = "System.Collections" /> // ----------------------------------------------------------------------- // XMake format: // ============= // <Import Include="System.Collections" /> // ----------------------------------------------------------------------- importsItemGroup.AddItem(XMakeProjectStrings.import, ProjectCollection.Escape(importNamespace)); // There should be no other attributes on the <Import> element (besides // "Namespace" which we already took care of). But loop through them // anyway, so we can emit a useful error message. foreach (XmlAttributeWithLocation importAttribute in importElement.Attributes) { ProjectErrorUtilities.VerifyThrowInvalidProject(false, importAttribute.Location, "UnrecognizedAttribute", importAttribute.Name, VSProjectElements.import); } // There should be no children of the <Import> element. ProjectXmlUtilities.VerifyThrowProjectNoChildElements(importElement); }
/// <summary> /// Parse a ProjectUsingTaskElement /// </summary> private ProjectUsingTaskElement ParseProjectUsingTaskElement(XmlElementWithLocation element) { ProjectXmlUtilities.VerifyThrowProjectAttributes(element, s_validAttributesOnUsingTask); ProjectErrorUtilities.VerifyThrowInvalidProject(element.GetAttribute(XMakeAttributes.taskName).Length > 0, element.Location, "ProjectTaskNameEmpty"); string assemblyName = element.GetAttribute(XMakeAttributes.assemblyName); string assemblyFile = element.GetAttribute(XMakeAttributes.assemblyFile); ProjectErrorUtilities.VerifyThrowInvalidProject ( ((assemblyName.Length > 0) ^ (assemblyFile.Length > 0)), element.Location, "UsingTaskAssemblySpecification", XMakeElements.usingTask, XMakeAttributes.assemblyName, XMakeAttributes.assemblyFile ); ProjectXmlUtilities.VerifyThrowProjectAttributeEitherMissingOrNotEmpty(element, XMakeAttributes.assemblyName); ProjectXmlUtilities.VerifyThrowProjectAttributeEitherMissingOrNotEmpty(element, XMakeAttributes.assemblyFile); ProjectUsingTaskElement usingTask = new ProjectUsingTaskElement(element, _project, _project); bool foundTaskElement = false; bool foundParameterGroup = false; foreach (XmlElementWithLocation childElement in ProjectXmlUtilities.GetVerifyThrowProjectChildElements(element)) { ProjectElement child = null; string childElementName = childElement.Name; switch (childElementName) { case XMakeElements.usingTaskParameterGroup: if (foundParameterGroup) { ProjectXmlUtilities.ThrowProjectInvalidChildElementDueToDuplicate(childElement); } child = ParseUsingTaskParameterGroupElement(childElement, usingTask); foundParameterGroup = true; break; case XMakeElements.usingTaskBody: if (foundTaskElement) { ProjectXmlUtilities.ThrowProjectInvalidChildElementDueToDuplicate(childElement); } child = ParseUsingTaskBodyElement(childElement, usingTask); foundTaskElement = true; break; default: ProjectXmlUtilities.ThrowProjectInvalidChildElement(childElement.Name, element.Name, element.Location); break; } usingTask.AppendParentedChildNoChecks(child); } return(usingTask); }
/// <summary> /// Processes the <File> element, and adds an appropriate item to the /// filesItemGroup. /// </summary> /// <owner>RGoel</owner> private void ProcessFileElement ( XmlElementWithLocation fileElement, ProjectItemGroupElement filesItemGroup ) { // Make sure this is the <File> element. error.VerifyThrow((fileElement != null) && (fileElement.Name == VSProjectElements.file), "Expected <File> element."); // Make sure the caller has already created an ProjectItemGroupElement for us to // put the new items in. error.VerifyThrow(filesItemGroup != null, "Received null ProjectItemGroupElement"); // Get the required "RelPath" attribute. string relPath = fileElement.GetAttribute(VSProjectAttributes.relPath); ProjectErrorUtilities.VerifyThrowInvalidProject((relPath != null) && (relPath.Length > 0), fileElement.Location, "MissingAttribute", VSProjectAttributes.relPath, VSProjectElements.file); // Remove the "RelPath" attribute, so we don't end up adding it twice. fileElement.RemoveAttribute(VSProjectAttributes.relPath); // Get the "Link" attribute. This is for linked items only. string linkPath = fileElement.GetAttribute(VSProjectAttributes.link); // Remove the "Link" attribute, so we don't end up adding it twice. fileElement.RemoveAttribute(VSProjectAttributes.link); // Get the "BuildAction" attribute. If it doesn't exist, figure out // what the build action is based on the file extension. This is // what the project loading code does in VS. string buildAction = fileElement.GetAttribute(VSProjectAttributes.buildAction); if ((buildAction == null) || (buildAction.Length == 0)) { buildAction = VSProjectAttributes.buildActionNone; } // Remove the "BuildAction" attribute, so we don't end up adding it twice. fileElement.RemoveAttribute(VSProjectAttributes.buildAction); ProjectItemElement newFileItem; // Bug Whidbey #248965. If a .resx file is completely empty, do not include a reference // to it in the upgraded project file. if (! (0 == String.Compare(Path.GetExtension(relPath), ".resx", StringComparison.OrdinalIgnoreCase) && IsFilePresentButEmpty(relPath, linkPath)) ) { // Add the new item to XMake. if ((linkPath == null) || (linkPath.Length == 0)) { // Normal item. // The <File> element gets converted to XMake as a new item, where // the item type is the BuildAction, and the "Include" contains // the relative path to the item. For // example, // ----------------------------------------------------------------------- // Everett format: // =============== // <File // RelPath = "Properties\PropertyGroupCollection.cs" // SubType = "Code" // BuildAction = "Compile" // /> // ----------------------------------------------------------------------- // XMake format: // ============= // <Compile Include = "Properties\PropertyGroupCollection.cs"> // <SubType>Code</SubType> // </Compile> // ----------------------------------------------------------------------- newFileItem = filesItemGroup.AddItem(buildAction, ProjectCollection.Escape(relPath)); } else { // Linked item. // The <File> element gets converted to XMake as a new item, where // the item type is the BuildAction, the "Include" contains // the physical relative path to the item, and the non-XMake "Link" // attribute contains the project-relative path for item (for display // purposes in the Solution Explorer). For example, // ----------------------------------------------------------------------- // Everett format: // =============== // <File // RelPath = "Properties\PropertyGroupCollection.cs" // Link = "c:\Rajeev\External\PropertyGroupCollection.cs" // SubType = "Code" // BuildAction = "Compile" // /> // ----------------------------------------------------------------------- // XMake format: // ============= // <Compile Include = "c:\Rajeev\External\PropertyGroupCollection.cs"> // <Link>Properties\PropertyGroupCollection.cs</Link> // <SubType>Code</SubType> // </Compile> // ----------------------------------------------------------------------- newFileItem = filesItemGroup.AddItem(buildAction, ProjectCollection.Escape(linkPath)); newFileItem.AddMetadata(XMakeProjectStrings.link, ProjectCollection.Escape(relPath)); } // Add all the rest of the attributes on the <File> element to the new // XMake item. foreach (XmlAttribute fileAttribute in fileElement.Attributes) { newFileItem.AddMetadata(fileAttribute.Name, ProjectCollection.Escape(fileAttribute.Value)); } // If this is a VSD(devices) project and we're dealing with a content file, // mark it to copy if newer. if ( ( ( ( this.language == VSProjectElements.ECSharp ) || ( this.language == VSProjectElements.EVisualBasic ) ) ) && ( 0 == String.Compare ( buildAction, XMakeProjectStrings.content, StringComparison.OrdinalIgnoreCase ) ) ) { newFileItem.AddMetadata ( XMakeProjectStrings.copytooutput, XMakeProjectStrings.preservenewest ); } } else { string warning = ResourceUtilities.FormatString( AssemblyResources.GetString("EmptyResxRemoved"), relPath); conversionWarnings.Add(warning); } // There should be no children of the <File> element. ProjectXmlUtilities.VerifyThrowProjectNoChildElements(fileElement); }
/// <summary> /// Processes the <Folder> element, and adds an appropriate item to the /// filesItemGroup. /// </summary> /// <owner>RGoel</owner> private void ProcessFolderElement ( XmlElementWithLocation folderElement, ProjectItemGroupElement filesItemGroup ) { // Make sure this is the <Folder> element. error.VerifyThrow((folderElement != null) && (folderElement.Name == VSProjectElements.folder), "Expected <Folder> element."); // Make sure the caller has already created an ProjectItemGroupElement for us to // put the new items in. error.VerifyThrow(filesItemGroup != null, "Received null ProjectItemGroupElement"); // Get the required "RelPath" attribute. string relPath = folderElement.GetAttribute(VSProjectAttributes.relPath); ProjectErrorUtilities.VerifyThrowInvalidProject((relPath != null) && (relPath.Length > 0), folderElement.Location, "MissingAttribute", VSProjectAttributes.relPath, VSProjectElements.folder); // Remove the "RelPath" attribute, so we don't end up adding it twice. folderElement.RemoveAttribute(VSProjectAttributes.relPath); // We need to find out what type of folder this is -- a web references // folder, a web reference URL, or just an empty project folder. // See if there's a "WebReferences" attribute on the <Folder> element. If so, // and the value is set to "True", then it's a web reference folder. string webReferences = folderElement.GetAttribute(VSProjectAttributes.webReferences); // Remove the "WebReferences" attribute, so we don't end up adding it twice. folderElement.RemoveAttribute(VSProjectAttributes.webReferences); // See if there's a "WebReferenceURL" attribute. If so, it's a web reference // URL. string webReferenceUrl = folderElement.GetAttribute(VSProjectAttributes.webReferenceUrl); // Remove the "WebReferenceURL" attribute, so we don't end up adding it twice. folderElement.RemoveAttribute(VSProjectAttributes.webReferenceUrl); ProjectItemElement newFolderItem; if ((webReferences != null) && (0 == String.Compare(webReferences, "true", StringComparison.OrdinalIgnoreCase))) { // This is a web reference folder. // The <Folder> element gets converted to XMake as an item of type // "WebReferences". The "Include" will contain the relative path. // For example, // ----------------------------------------------------------------------- // Everett format: // =============== // <Folder // RelPath = "Web References\" // WebReferences = "TRUE" // /> // ----------------------------------------------------------------------- // XMake format: // ============= // <WebReferences Include = "Web References\" /> // ----------------------------------------------------------------------- newFolderItem = filesItemGroup.AddItem(XMakeProjectStrings.webReferences, ProjectCollection.Escape(relPath)); } else if ((webReferenceUrl != null) && (webReferenceUrl.Length > 0)) { // This is an actual web reference URL. // The <Folder> element gets converted to XMake as an item of type // "WebReferenceURL". The "Include" will contain the URL. // For example, // ----------------------------------------------------------------------- // Everett format: // =============== // <Folder // RelPath = "Web References\mobileakipman\" // WebReferenceUrl = "http://mobileakipman/HelloName/service1.asmx" // UrlBehavior = "Static" // /> // ----------------------------------------------------------------------- // XMake format: // ============= // <WebReferenceUrl Include="http://mobileakipman/HelloName/service1.asmx"> // <RelPath>Web References\mobileakipman\</RelPath> // <UrlBehavior>Static</UrlBehavior> // </WebReferenceUrl> // ----------------------------------------------------------------------- newFolderItem = filesItemGroup.AddItem(XMakeProjectStrings.webReferenceUrl, ProjectCollection.Escape(webReferenceUrl)); newFolderItem.AddMetadata(XMakeProjectStrings.relPath, ProjectCollection.Escape(relPath)); // Whidbey projects have some new properties to control the behavior of the // proxy generation. For projects migrated from Everett, we want to force // the proxy generation to mimic the Everett behavior, so that people's projects // still work the same as they did in Everett. (These properties did not // exist in Everett.) See spec at: // http://devdiv/SpecTool/Documents/Whidbey/VSCore/Solution%20Project%20Build/FeatureSpecs/Project-WebReferences.doc if (!this.newWebReferencePropertiesAdded) { this.globalPropertyGroup.AddProperty(XMakeProjectStrings.webRefEnableProperties, (this.language == VSProjectElements.visualJSharp) ? "false" : "true"); this.globalPropertyGroup.AddProperty(XMakeProjectStrings.webRefEnableSqlTypes, "false"); this.globalPropertyGroup.AddProperty(XMakeProjectStrings.webRefEnableLegacyEventing, "true"); this.newWebReferencePropertiesAdded = true; } } else { // This is just a project folder that happens not to have any files in it. // The <Folder> element gets converted to XMake as an item of type "Folder". // However, we do need to remove the trailing backslash, because XMake // interprets that as a recursion (bug # 58591). For example, // ----------------------------------------------------------------------- // Everett format: // =============== // <Folder // RelPath = "MyEmptyProjectFolder\" // /> // ----------------------------------------------------------------------- // XMake format: // ============= // <Folder Include="MyEmptyProjectFolder" /> // ----------------------------------------------------------------------- // Remove the trailing backslash. XMake interprets trailing backslashes // as a recursive wildcard. This will be fixed in M2 -- bug # 58591 if (relPath.EndsWith("\\", StringComparison.Ordinal)) { relPath = relPath.Remove(relPath.Length - 1, 1); } newFolderItem = filesItemGroup.AddItem(XMakeProjectStrings.folder, ProjectCollection.Escape(relPath)); } // Add all the rest of the attributes on the <Folder> element to the new // XMake item. foreach (XmlAttribute folderAttribute in folderElement.Attributes) { newFolderItem.AddMetadata(folderAttribute.Name, ProjectCollection.Escape(folderAttribute.Value)); } // There should be no children of the <Folder> element. ProjectXmlUtilities.VerifyThrowProjectNoChildElements(folderElement); }
/// <summary> /// Parse a ProjectItemElement /// </summary> private ProjectItemElement ParseProjectItemElement(XmlElementWithLocation element, ProjectItemGroupElement parent) { ProjectXmlUtilities.VerifyThrowProjectAttributes(element, s_validAttributesOnItem); bool belowTarget = parent.Parent is ProjectTargetElement; string itemType = element.Name; string include = element.GetAttribute(XMakeAttributes.include); string exclude = element.GetAttribute(XMakeAttributes.exclude); string remove = element.GetAttribute(XMakeAttributes.remove); // Remove must be missing, unless inside a target and Include is missing ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute((remove.Length == 0 || (belowTarget && include.Length == 0)), (XmlAttributeWithLocation)element.Attributes[XMakeAttributes.remove]); // Include must be present, unless inside a target ProjectErrorUtilities.VerifyThrowInvalidProject(include.Length > 0 || belowTarget, element.Location, "MissingRequiredAttribute", XMakeAttributes.include, itemType); // Exclude must be missing, unless Include exists ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute(exclude.Length == 0 || include.Length > 0, (XmlAttributeWithLocation)element.Attributes[XMakeAttributes.exclude]); // If we have an Include attribute at all, it must have non-zero length ProjectErrorUtilities.VerifyThrowInvalidProject(include.Length > 0 || element.Attributes[XMakeAttributes.include] == null, element.Location, "MissingRequiredAttribute", XMakeAttributes.include, itemType); XmlUtilities.VerifyThrowProjectValidElementName(element); ProjectErrorUtilities.VerifyThrowInvalidProject(XMakeElements.IllegalItemPropertyNames[itemType] == null, element.Location, "CannotModifyReservedItem", itemType); ProjectItemElement item = new ProjectItemElement(element, parent, _project); foreach (XmlElementWithLocation childElement in ProjectXmlUtilities.GetVerifyThrowProjectChildElements(element)) { ProjectMetadataElement metadatum = ParseProjectMetadataElement(childElement, item); item.AppendParentedChildNoChecks(metadatum); } return item; }