private void UpdateSlowCheetah(Project project)
        {
            // This is done on the UI thread because changes are made to the project file,
            // causing it to be reloaded. To avoid conflicts with NuGet installation,
            // the update is done sequentially
            if (this.HasUserAcceptedWarningMessage(Resources.Resources.NugetUpdate_Title, Resources.Resources.NugetUpdate_Text))
            {
                // Creates dialog informing the user to wait for the installation to finish
                IVsThreadedWaitDialogFactory twdFactory = this.package.GetService(typeof(SVsThreadedWaitDialogFactory)) as IVsThreadedWaitDialogFactory;
                IVsThreadedWaitDialog2       dialog     = null;
                twdFactory?.CreateInstance(out dialog);

                string title = Resources.Resources.NugetUpdate_WaitTitle;
                string text  = Resources.Resources.NugetUpdate_WaitText;
                dialog?.StartWaitDialog(title, text, null, null, null, 0, false, true);
                try
                {
                    // Installs the latest version of the SlowCheetah NuGet package
                    var componentModel = (IComponentModel)this.package.GetService(typeof(SComponentModel));
                    if (this.IsSlowCheetahInstalled(project))
                    {
                        IVsPackageUninstaller packageUninstaller = componentModel.GetService <IVsPackageUninstaller>();
                        packageUninstaller.UninstallPackage(project, PackageName, true);
                    }

                    IVsPackageInstaller2 packageInstaller = componentModel.GetService <IVsPackageInstaller2>();
                    packageInstaller.InstallLatestPackage(null, project, PackageName, false, false);

                    project.Save();
                    ProjectRootElement projectRoot = ProjectRootElement.Open(project.FullName);
                    foreach (ProjectPropertyGroupElement propertyGroup in projectRoot.PropertyGroups.Where(pg => pg.Label.Equals("SlowCheetah")))
                    {
                        projectRoot.RemoveChild(propertyGroup);
                    }

                    foreach (ProjectImportElement import in projectRoot.Imports.Where(i => i.Label == "SlowCheetah" || i.Project == "$(SlowCheetahTargets)"))
                    {
                        projectRoot.RemoveChild(import);
                    }

                    projectRoot.Save();
                }
                finally
                {
                    // Closes the wait dialog. If the dialog failed, does nothing
                    int canceled;
                    dialog?.EndWaitDialog(out canceled);
                }
            }
        }
 void RemoveImports(ProjectRootElement root)
 {
     foreach (var import in root.Imports)
     {
         root.RemoveChild(import);
     }
 }
        /// <summary>
        /// Replaces the configurations property with the expected configurations.
        /// Doesn't attempt to preserve any content since it can all be regenerated.
        /// Does attempt to preserve the ordering in the project file.
        /// </summary>
        /// <param name="project">Project</param>
        /// <param name="oldPropertyGroups">PropertyGroups to remove</param>
        /// <param name="newConfigurations"></param>
        private static void ReplaceConfigurationsProperty(ProjectRootElement project, IEnumerable <ProjectPropertyGroupElement> oldPropertyGroups, IEnumerable <string> newConfigurations)
        {
            foreach (var oldPropertyGroup in oldPropertyGroups)
            {
                project.RemoveChild(oldPropertyGroup);
            }

            string configurationsValue    = string.Join(";", newConfigurations);
            var    configurationsProperty = project.Properties.FirstOrDefault(p => p.Name == "Configurations");

            if (configurationsProperty == null)
            {
                var firstPropertyGroup = project.PropertyGroups.FirstOrDefault();
                if (firstPropertyGroup == null)
                {
                    firstPropertyGroup = project.CreatePropertyGroupElement();
                }

                configurationsProperty = firstPropertyGroup.AddProperty("Configurations", configurationsValue);
            }
            else
            {
                configurationsProperty.Value = configurationsValue;
            }
        }
示例#4
0
        public static void AddTargetsFileToOldProjects(VCProject vcProject)
        {
            string             projectFilePath         = vcProject.ProjectFile;
            ProjectRootElement projectRootElement      = ProjectRootElement.Open(projectFilePath);
            ICollection <ProjectImportElement> imports = projectRootElement.Imports;
            ProjectPropertyGroupElement        userMacrosPropertyGroup = projectRootElement.PropertyGroups.Where(g => g.Label.Equals("UserMacros")).FirstOrDefault();
            ProjectImportElement userFileImport = imports.Where(i => i.Project.Equals("$(VCTargetsPath)\\Microsoft.Cpp.targets")).FirstOrDefault();

            if (userMacrosPropertyGroup != null && !userMacrosPropertyGroup.NextSibling.Equals(userFileImport))
            {
                projectRootElement.RemoveChild(userFileImport);

                projectRootElement.InsertAfterChild(userFileImport, userMacrosPropertyGroup);

                //delete all occurences of PLCnCLIIncludes and PLCnCLIMacros -> saved in .users file now
                IEnumerable <ProjectPropertyElement> elementsToDelete = projectRootElement.PropertyGroups
                                                                        .Where(g => g.Label.Equals("Configuration"))
                                                                        .SelectMany(g => g.Properties
                                                                                    .Where(p => p.Name.Equals("PLCnCLIMacros") || p.Name.Equals("PLCnCLIIncludes")));
                elementsToDelete.ToList().ForEach(e => e.Parent.RemoveChild(e));

                MessageBox.Show("The project file needs to be updated outside of the environment. Please choose 'Reload all...' in the next dialog.",
                                "Project update needed", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                projectRootElement.Save();
            }
        }
示例#5
0
        /// <summary>
        /// Replaces all configuration propertygroups with empty property groups corresponding to the expected configurations.
        /// Doesn't attempt to preserve any content since it can all be regenerated.
        /// Does attempt to preserve the ordering in the project file.
        /// </summary>
        /// <param name="project">Project</param>
        /// <param name="oldPropertyGroups">PropertyGroups to remove</param>
        /// <param name="newConfigurations"></param>
        private static void ReplaceConfigurationPropertyGroups(ProjectRootElement project, IEnumerable <ProjectPropertyGroupElement> oldPropertyGroups, IEnumerable <string> newConfigurations)
        {
            ProjectElement insertAfter = null, insertBefore = null;

            foreach (var oldPropertyGroup in oldPropertyGroups)
            {
                insertBefore = oldPropertyGroup.NextSibling;
                project.RemoveChild(oldPropertyGroup);
            }

            if (insertBefore == null)
            {
                // find first itemgroup after imports
                var insertAt = project.Imports.FirstOrDefault()?.NextSibling;

                while (insertAt != null)
                {
                    if (insertAt is ProjectItemGroupElement)
                    {
                        insertBefore = insertAt;
                        break;
                    }

                    insertAt = insertAt.NextSibling;
                }
            }

            if (insertBefore == null)
            {
                // find last propertygroup after imports, defaulting to after imports
                insertAfter = project.Imports.FirstOrDefault();

                while (insertAfter?.NextSibling != null && insertAfter.NextSibling is ProjectPropertyGroupElement)
                {
                    insertAfter = insertAfter.NextSibling;
                }
            }


            foreach (var newConfiguration in newConfigurations)
            {
                var newPropertyGroup = project.CreatePropertyGroupElement();
                newPropertyGroup.Condition = $"'$(Configuration)|$(Platform)' == '{newConfiguration}'";
                if (insertBefore != null)
                {
                    project.InsertBeforeChild(newPropertyGroup, insertBefore);
                }
                else if (insertAfter != null)
                {
                    project.InsertAfterChild(newPropertyGroup, insertAfter);
                }
                else
                {
                    project.AppendChild(newPropertyGroup);
                }
                insertBefore = null;
                insertAfter  = newPropertyGroup;
            }
        }
        /// <inheritdoc/>
        public override async TPL.Task Execute(Project project)
        {
            // We handle any NuGet package logic before editing the project file
            await this.Successor.Execute(project);

            project.Save();
            ProjectRootElement projectRoot = ProjectRootElement.Open(project.FullName);

            foreach (ProjectPropertyGroupElement propertyGroup in projectRoot.PropertyGroups.Where(pg => pg.Label.Equals("SlowCheetah")))
            {
                projectRoot.RemoveChild(propertyGroup);
            }

            foreach (ProjectImportElement import in projectRoot.Imports.Where(i => i.Label == "SlowCheetah" || i.Project == "$(SlowCheetahTargets)"))
            {
                projectRoot.RemoveChild(import);
            }

            projectRoot.Save();
        }
示例#7
0
        private void ChangeImports()
        {
            var projectStyle = _sdkBaselineProject.ProjectStyle;

            switch (projectStyle)
            {
            case ProjectStyle.Default:
                foreach (var import in _projectRootElement.Imports)
                {
                    _projectRootElement.RemoveChild(import);
                }
                _projectRootElement.Sdk = "Microsoft.NET.Sdk";
                break;

            case ProjectStyle.DefaultWithCustomTargets:
                break;

            case ProjectStyle.Custom:
                throw new NotSupportedException("Projects with more than 2 imports of custom targets are not supported");
            }
        }
示例#8
0
        private static void ProcessImportsFrom21b(ProjectRootElement projectXml, Action <__VSUL_ERRORLEVEL, string> log)
        {
            var bottleImports = projectXml.Imports.Where(p => p.Project.Equals(Ptvs21BetaBottleTargets, StringComparison.OrdinalIgnoreCase)).ToList();
            var flaskImports  = projectXml.Imports.Where(p => p.Project.Equals(Ptvs21BetaFlaskTargets, StringComparison.OrdinalIgnoreCase)).ToList();

            foreach (var import in bottleImports.Concat(flaskImports))
            {
                import.Project = WebTargets;
            }

            if (bottleImports.Any())
            {
                var globals = projectXml.PropertyGroups.FirstOrDefault() ?? projectXml.AddPropertyGroup();
                AddOrSetProperty(globals, "PythonDebugWebServerCommandArguments", "--debug $(CommandLineArguments)");
                AddOrSetProperty(globals, "PythonWsgiHandler", "{StartupModule}.wsgi_app()");
                log(__VSUL_ERRORLEVEL.VSUL_INFORMATIONAL, Strings.UpgradedBottleImports);
            }
            if (flaskImports.Any())
            {
                var globals = projectXml.PropertyGroups.FirstOrDefault() ?? projectXml.AddPropertyGroup();
                AddOrSetProperty(globals, "PythonWsgiHandler", "{StartupModule}.wsgi_app");
                log(__VSUL_ERRORLEVEL.VSUL_INFORMATIONAL, Strings.UpgradedFlaskImports);
            }

            var commonPropsImports = projectXml.Imports.Where(p => p.Project.Equals(CommonProps, StringComparison.OrdinalIgnoreCase)).ToList();

            foreach (var p in commonPropsImports)
            {
                projectXml.RemoveChild(p);
                log(__VSUL_ERRORLEVEL.VSUL_INFORMATIONAL, Strings.UpgradedRemoveCommonProps);
            }

            if (projectXml.Imports.Count == 1 && projectXml.Imports.First().Project.Equals(CommonTargets, StringComparison.OrdinalIgnoreCase))
            {
                projectXml.RemoveChild(projectXml.Imports.First());
                projectXml.AddImport(PtvsTargets);
                log(__VSUL_ERRORLEVEL.VSUL_INFORMATIONAL, Strings.UpgradedRemoveCommonTargets);
            }
        }
            public void SetProperty(string unevaluatedPropertyValue, ProjectRootElement projectXml)
            {
                if (OnlyWhitespaceCharacters(unevaluatedPropertyValue))
                {
                    (bool success, ProjectTargetElement target) = FindTargetToRemove(projectXml);
                    if (success)
                    {
                        projectXml.RemoveChild(target);
                        return;
                    }
                }

                SetParameter(projectXml, unevaluatedPropertyValue);
            }
        //async Task RemoveReferences(ProjectRootElement root)
        //{
        //    await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
        //    var frameworkMultiTargeting = await ServiceProvider.GetServiceAsync(typeof(SVsFrameworkMultiTargeting)) as IVsFrameworkMultiTargeting;

        //    foreach (var itemGroup in root.ItemGroups)
        //    {
        //        foreach (var item in itemGroup.Items)
        //        {
        //            if (item.ElementName == Constants.Reference)
        //            {
        //                bool isFrameworkReference = false;
        //                frameworkMultiTargeting.IsReferenceableInTargetFx(item.Include, Constants.NetFramework, out isFrameworkReference);

        //                if (isFrameworkReference)
        //                    itemGroup.RemoveChild(item);
        //            }
        //        }

        //        if (itemGroup.Items.Count == 0)
        //        {
        //            root.RemoveChild(itemGroup);
        //        }
        //    }
        //}

        void RemoveItems(ProjectRootElement root)
        {
            foreach (var itemGroup in root.ItemGroups)
            {
                foreach (var item in itemGroup.Items)
                {
                    if (Constants.ItemTypesNotNeeded.Contains(item.ElementName))
                    {
                        itemGroup.RemoveChild(item);
                    }
                }

                if (itemGroup.Items.Count == 0)
                {
                    root.RemoveChild(itemGroup);
                }
            }
        }
示例#11
0
            public async Task SetPropertyAsync(string unevaluatedPropertyValue, IProjectProperties defaultProperties, ProjectRootElement projectXml)
            {
                // Check if project file already has props in place for this.
                if (await TrySetPropertyAsync(unevaluatedPropertyValue, defaultProperties, projectXml).ConfigureAwait(true))
                {
                    return;
                }

                if (OnlyWhitespaceCharacters(unevaluatedPropertyValue))
                {
                    (bool success, ProjectTargetElement target) = FindTargetToRemove(projectXml);
                    if (success)
                    {
                        projectXml.RemoveChild(target);
                        return;
                    }
                }

                SetParameter(projectXml, unevaluatedPropertyValue);
            }
示例#12
0
        protected override void UpgradeProject(
            ref ProjectRootElement projectXml,
            ref ProjectRootElement userProjectXml,
            Action <__VSUL_ERRORLEVEL, string> log
            )
        {
            Version version;

            // ToolsVersion less than 4.0 (or unspecified) is not supported, so
            // set it to 4.0.
            if (!Version.TryParse(projectXml.ToolsVersion, out version) ||
                version < new Version(4, 0))
            {
                projectXml.ToolsVersion = "4.0";
                log(__VSUL_ERRORLEVEL.VSUL_INFORMATIONAL, Strings.UpgradedToolsVersion);
            }

            // Referencing an interpreter by GUID
            bool interpreterChanged  = false;
            var  msbuildInterpreters = new Dictionary <Guid, string>();

            foreach (var i in projectXml.ItemGroups.SelectMany(g => g.Items).Where(i => i.ItemType == "Interpreter"))
            {
                var id = i.Metadata.LastOrDefault(m => m.Name == "Id");
                if (id != null)
                {
                    Guid guid;
                    if (Guid.TryParse(id.Value, out guid))
                    {
                        msbuildInterpreters[guid] = i.Include?.Trim('/', '\\');
                    }
                }

                var mdBase = i.Metadata.LastOrDefault(m => m.Name == "BaseInterpreter");
                if (mdBase == null)
                {
                    continue;
                }
                var mdVer = i.Metadata.LastOrDefault(m => m.Name == "Version");
                if (mdVer == null)
                {
                    log(__VSUL_ERRORLEVEL.VSUL_ERROR, Strings.UpgradedInterpreterReferenceFailed);
                    continue;
                }

                var newId = MapInterpreterId(mdBase.Value, mdVer.Value, null);
                if (newId != null)
                {
                    mdBase.Value       = newId;
                    interpreterChanged = true;
                }
            }

            var interpreterId      = projectXml.Properties.LastOrDefault(p => p.Name == "InterpreterId");
            var interpreterVersion = projectXml.Properties.LastOrDefault(p => p.Name == "InterpreterVersion");

            if (interpreterId != null && interpreterVersion != null)
            {
                var newId = MapInterpreterId(interpreterId.Value, interpreterVersion.Value, msbuildInterpreters);
                if (newId != null)
                {
                    interpreterId.Value = newId;
                    interpreterVersion.Parent.RemoveChild(interpreterVersion);
                    interpreterChanged = true;
                }
            }

            foreach (var i in projectXml.ItemGroups.SelectMany(g => g.Items).Where(i => i.ItemType == "InterpreterReference"))
            {
                var newId = MapInterpreterId(i.Include, null, null);
                if (newId != null)
                {
                    i.Include          = newId;
                    interpreterChanged = true;
                }
            }

            if (interpreterChanged)
            {
                log(__VSUL_ERRORLEVEL.VSUL_INFORMATIONAL, Strings.UpgradedInterpreterReference);
            }

            // Importing a targets file from 2.1 Beta
            var bottleImports = projectXml.Imports.Where(p => p.Project.Equals(Ptvs21BetaBottleTargets, StringComparison.OrdinalIgnoreCase)).ToList();
            var flaskImports  = projectXml.Imports.Where(p => p.Project.Equals(Ptvs21BetaFlaskTargets, StringComparison.OrdinalIgnoreCase)).ToList();

            foreach (var import in bottleImports.Concat(flaskImports))
            {
                import.Project = WebTargets;
            }

            if (bottleImports.Any())
            {
                var globals = projectXml.PropertyGroups.FirstOrDefault() ?? projectXml.AddPropertyGroup();
                AddOrSetProperty(globals, "PythonDebugWebServerCommandArguments", "--debug $(CommandLineArguments)");
                AddOrSetProperty(globals, "PythonWsgiHandler", "{StartupModule}.wsgi_app()");
                log(__VSUL_ERRORLEVEL.VSUL_INFORMATIONAL, Strings.UpgradedBottleImports);
            }
            if (flaskImports.Any())
            {
                var globals = projectXml.PropertyGroups.FirstOrDefault() ?? projectXml.AddPropertyGroup();
                AddOrSetProperty(globals, "PythonWsgiHandler", "{StartupModule}.wsgi_app");
                log(__VSUL_ERRORLEVEL.VSUL_INFORMATIONAL, Strings.UpgradedFlaskImports);
            }

            var commonPropsImports = projectXml.Imports.Where(p => p.Project.Equals(CommonProps, StringComparison.OrdinalIgnoreCase)).ToList();

            foreach (var p in commonPropsImports)
            {
                projectXml.RemoveChild(p);
                log(__VSUL_ERRORLEVEL.VSUL_INFORMATIONAL, Strings.UpgradedRemoveCommonProps);
            }

            if (projectXml.Imports.Count == 1 && projectXml.Imports.First().Project.Equals(CommonTargets, StringComparison.OrdinalIgnoreCase))
            {
                projectXml.RemoveChild(projectXml.Imports.First());
                var group = projectXml.AddPropertyGroup();
                if (!projectXml.Properties.Any(p => p.Name == "VisualStudioVersion"))
                {
                    group.AddProperty("VisualStudioVersion", "10.0").Condition = "'$(VisualStudioVersion)' == ''";
                }
                group.AddProperty("PtvsTargetsFile", PtvsTargets);
                projectXml.AddImport("$(PtvsTargetsFile)").Condition = "Exists($(PtvsTargetsFile))";
                projectXml.AddImport(CommonTargets).Condition        = "!Exists($(PtvsTargetsFile))";
                log(__VSUL_ERRORLEVEL.VSUL_INFORMATIONAL, Strings.UpgradedRemoveCommonTargets);
            }
        }
        protected override void OnClosed(EventArgs e)
        {
            if (_savedChanges)
            {
                // Make sure the current document has the necessary
                // extensions loaded.
                // UNDONE: We should be able to do this with the document
                // closed or open as text as well via a registered service
                // on the ORMDesignerPackage, but this is sufficient for now.
                Dictionary <string, string> requiredExtensions = null;
                string[] loadedExtensions = null;
                foreach (IORMGenerator selectedGenerator in _mainBranch.SelectedGenerators)
                {
                    foreach (string requiredExtension in selectedGenerator.GetRequiredExtensionsForInputFormat("ORM"))
                    {
                        if (loadedExtensions == null)
                        {
                            loadedExtensions = (new ORMExtensionManager(_projectItem)).GetLoadedExtensions(_serviceProvider);
                        }
                        if (Array.BinarySearch <string>(loadedExtensions, requiredExtension) < 0)
                        {
                            if (requiredExtensions == null)
                            {
                                requiredExtensions = new Dictionary <string, string>();
                            }
                            else if (requiredExtensions.ContainsKey(requiredExtension))
                            {
                                continue;
                            }
                            requiredExtensions.Add(requiredExtension, requiredExtension);
                        }
                    }
                }
                if (requiredExtensions != null)
                {
                    _savedChanges = ORMExtensionManager.EnsureExtensions(_projectItem, _serviceProvider, requiredExtensions.Values);
                }
            }
            if (_savedChanges)
            {
                // Delete the removed items from the project
                if (_removedItems != null)
                {
                    EnvDTE.ProjectItems subItems = _projectItem.ProjectItems;
                    foreach (string itemName in _removedItems.Keys)
                    {
                        try
                        {
                            EnvDTE.ProjectItem subItem = subItems.Item(itemName);
                            if (subItem != null)
                            {
                                subItem.Delete();
                            }
                        }
                        catch (ArgumentException)
                        {
                            // Swallow
                        }
                    }
                }
                // throw away the original build item group
                if (_originalItemGroup != null)
                {
                    try
                    {
#if VISUALSTUDIO_10_0
                        _project.RemoveChild(_originalItemGroup);
#else
                        _project.RemoveItemGroup(_originalItemGroup);
#endif
                    }
                    catch (InvalidOperationException)
                    {
                        // Swallow
                    }
                }

#if VISUALSTUDIO_10_0
                Dictionary <string, ProjectItemElement> removeItems = new Dictionary <string, ProjectItemElement>();
#else
                Dictionary <string, BuildItem> removeItems = new Dictionary <string, BuildItem>();
#endif
                string tmpFile = null;
                try
                {
                    EnvDTE.ProjectItems projectItems = _projectItem.ProjectItems;
#if VISUALSTUDIO_10_0
                    string itemDirectory = (new FileInfo((string)_project.FullPath)).DirectoryName;
                    foreach (ProjectItemElement item in _itemGroup.Items)
#else
                    string itemDirectory = (new FileInfo((string)_project.FullFileName)).DirectoryName;
                    foreach (BuildItem item in this._itemGroup)
#endif
                    {
                        string filePath = string.Concat(itemDirectory, Path.DirectorySeparatorChar, item.Include);
                        string fileName = (new FileInfo(item.Include)).Name;
                        if (File.Exists(filePath))
                        {
                            try
                            {
                                projectItems.AddFromFile(filePath);
                            }
                            catch (ArgumentException)
                            {
                                // Swallow
                            }
                        }
                        else
                        {
                            if (tmpFile == null)
                            {
                                tmpFile = Path.GetTempFileName();
                            }
                            EnvDTE.ProjectItem projectItem = projectItems.AddFromTemplate(tmpFile, fileName);
                            string             customTool  = item.GetMetadata(ITEMMETADATA_GENERATOR);
                            if (!string.IsNullOrEmpty(customTool))
                            {
                                projectItem.Properties.Item("CustomTool").Value = customTool;
                            }
                        }
                        removeItems[item.Include] = null;
                    }
                }
                finally
                {
                    if (tmpFile != null)
                    {
                        File.Delete(tmpFile);
                    }
                }

#if VISUALSTUDIO_10_0
                foreach (ProjectItemGroupElement group in this._project.ItemGroups)
#else
                foreach (BuildItemGroup group in this._project.ItemGroups)
#endif
                {
                    if (group.Condition.Trim() == this._itemGroup.Condition.Trim())
                    {
                        continue;
                    }
#if VISUALSTUDIO_10_0
                    foreach (ProjectItemElement item in group.Items)
#else
                    foreach (BuildItem item in group)
#endif
                    {
                        if (removeItems.ContainsKey(item.Include))
                        {
                            removeItems[item.Include] = item;
                        }
                    }
                }
                foreach (string key in removeItems.Keys)
                {
#if VISUALSTUDIO_10_0
                    ProjectItemElement      removeItem;
                    ProjectElementContainer removeFrom;
                    if (null != (removeItem = removeItems[key]) &&
                        null != (removeFrom = removeItem.Parent))
                    {
                        removeFrom.RemoveChild(removeItem);
                    }
#else
                    BuildItem removeItem = removeItems[key];
                    if (removeItem != null)
                    {
                        _project.RemoveItem(removeItem);
                    }
#endif
                }

                VSLangProj.VSProjectItem vsProjectItem = _projectItem.Object as VSLangProj.VSProjectItem;
                if (vsProjectItem != null)
                {
                    vsProjectItem.RunCustomTool();
                }
            }
            else
            {
#if VISUALSTUDIO_10_0
                _project.RemoveChild(_itemGroup);
#else
                _project.RemoveItemGroup(_itemGroup);
#endif
            }
            base.OnClosed(e);
        }
        protected override void UpgradeProject(
            ref ProjectRootElement projectXml,
            ref ProjectRootElement userProjectXml,
            Action <__VSUL_ERRORLEVEL, string> log
            )
        {
            Version version;

            // ToolsVersion less than 4.0 (or unspecified) is not supported, so
            // set it to 4.0.
            if (!Version.TryParse(projectXml.ToolsVersion, out version) ||
                version < new Version(4, 0))
            {
                projectXml.ToolsVersion = "4.0";
                log(__VSUL_ERRORLEVEL.VSUL_INFORMATIONAL, SR.GetString(SR.UpgradedToolsVersion));
            }

            // Importing a targets file from 2.1 Beta
            var bottleImports = projectXml.Imports.Where(p => p.Project.Equals(Ptvs21BetaBottleTargets, StringComparison.OrdinalIgnoreCase)).ToList();
            var flaskImports  = projectXml.Imports.Where(p => p.Project.Equals(Ptvs21BetaFlaskTargets, StringComparison.OrdinalIgnoreCase)).ToList();

            foreach (var import in bottleImports.Concat(flaskImports))
            {
                import.Project = WebTargets;
            }

            if (bottleImports.Any())
            {
                var globals = projectXml.PropertyGroups.FirstOrDefault() ?? projectXml.AddPropertyGroup();
                AddOrSetProperty(globals, "PythonDebugWebServerCommandArguments", "--debug $(CommandLineArguments)");
                AddOrSetProperty(globals, "PythonWsgiHandler", "{StartupModule}.wsgi_app()");
                log(__VSUL_ERRORLEVEL.VSUL_INFORMATIONAL, SR.GetString(SR.UpgradedBottleImports));
            }
            if (flaskImports.Any())
            {
                var globals = projectXml.PropertyGroups.FirstOrDefault() ?? projectXml.AddPropertyGroup();
                AddOrSetProperty(globals, "PythonWsgiHandler", "{StartupModule}.wsgi_app");
                log(__VSUL_ERRORLEVEL.VSUL_INFORMATIONAL, SR.GetString(SR.UpgradedFlaskImports));
            }

            var commonPropsImports = projectXml.Imports.Where(p => p.Project.Equals(CommonProps, StringComparison.OrdinalIgnoreCase)).ToList();

            foreach (var p in commonPropsImports)
            {
                projectXml.RemoveChild(p);
                log(__VSUL_ERRORLEVEL.VSUL_INFORMATIONAL, SR.GetString(SR.UpgradedRemoveCommonProps));
            }

            if (projectXml.Imports.Count == 1 && projectXml.Imports.First().Project.Equals(CommonTargets, StringComparison.OrdinalIgnoreCase))
            {
                projectXml.RemoveChild(projectXml.Imports.First());
                var group = projectXml.AddPropertyGroup();
                if (!projectXml.Properties.Any(p => p.Name == "VisualStudioVersion"))
                {
                    group.AddProperty("VisualStudioVersion", "10.0").Condition = "'$(VisualStudioVersion)' == ''";
                }
                group.AddProperty("PtvsTargetsFile", PtvsTargets);
                projectXml.AddImport("$(PtvsTargetsFile)").Condition = "Exists($(PtvsTargetsFile))";
                projectXml.AddImport(CommonTargets).Condition        = "!Exists($(PtvsTargetsFile))";
                log(__VSUL_ERRORLEVEL.VSUL_INFORMATIONAL, SR.GetString(SR.UpgradedRemoveCommonTargets));
            }

#if !DEV12_OR_LATER
            if (userProjectXml != null)
            {
                if (!Version.TryParse(userProjectXml.ToolsVersion, out version) ||
                    version > new Version(4, 0))
                {
                    userProjectXml.ToolsVersion = "4.0";
                    log(__VSUL_ERRORLEVEL.VSUL_INFORMATIONAL, SR.GetString(SR.UpgradedUserToolsVersion));
                }
            }
#endif
        }