From ca47896204482bf4a6979e3838bf7f09f61cebeb Mon Sep 17 00:00:00 2001
From: giy <giy@omp-system.ru>
Date: Fri, 02 Sep 2022 14:16:56 +0300
Subject: [PATCH] Обновление до версии 2.9.0

---
 QtVsTools.Core/HelperFunctions.cs |  629 ++++++++++++++------------------------------------------
 1 files changed, 162 insertions(+), 467 deletions(-)

diff --git a/QtVsTools.Core/HelperFunctions.cs b/QtVsTools.Core/HelperFunctions.cs
index b6fe0ff..a07fa89 100644
--- a/QtVsTools.Core/HelperFunctions.cs
+++ b/QtVsTools.Core/HelperFunctions.cs
@@ -1,6 +1,6 @@
 /****************************************************************************
 **
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
 ** Contact: https://www.qt.io/licensing/
 **
 ** This file is part of the Qt VS Tools.
@@ -26,10 +26,6 @@
 **
 ****************************************************************************/
 
-using EnvDTE;
-using Microsoft.VisualStudio.VCProjectEngine;
-using Microsoft.Win32;
-using QtVsTools.Core.QtMsBuild;
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
@@ -40,105 +36,31 @@
 using System.Text;
 using System.Text.RegularExpressions;
 using System.Windows.Forms;
+using Microsoft.VisualStudio.Shell;
+using Microsoft.VisualStudio.VCProjectEngine;
+#if VS2017
+using Microsoft.Win32;
+#endif
+using EnvDTE;
 
 using Process = System.Diagnostics.Process;
 
 namespace QtVsTools.Core
 {
+    using QtMsBuild;
+
     public static class HelperFunctions
     {
-        public static string FindQtDirWithTools(Project project)
-        {
-            var versionManager = QtVersionManager.The();
-            string projectQtVersion = null;
-            if (IsQtProject(project))
-                projectQtVersion = versionManager.GetProjectQtVersion(project);
-            return FindQtDirWithTools(projectQtVersion);
-        }
-
-        public static string FindQtDirWithTools(string projectQtVersion)
-        {
-            string tool = null;
-            return FindQtDirWithTools(tool, projectQtVersion);
-        }
-
-        public static string FindQtDirWithTools(string tool, string projectQtVersion)
-        {
-            if (!string.IsNullOrEmpty(tool)) {
-                if (!tool.StartsWith("\\bin\\", StringComparison.OrdinalIgnoreCase))
-                    tool = "\\bin\\" + tool;
-                if (!tool.EndsWith(".exe", StringComparison.OrdinalIgnoreCase))
-                    tool += ".exe";
-            }
-
-            var versionManager = QtVersionManager.The();
-            string qtDir = null;
-            if (projectQtVersion != null)
-                qtDir = versionManager.GetInstallPath(projectQtVersion);
-
-            if (qtDir == null)
-                qtDir = Environment.GetEnvironmentVariable("QTDIR");
-
-            var found = false;
-            if (tool == null) {
-                found = File.Exists(qtDir + "\\bin\\designer.exe")
-                    && File.Exists(qtDir + "\\bin\\linguist.exe");
-            } else {
-                found = File.Exists(qtDir + tool);
-            }
-            if (!found) {
-                VersionInformation exactlyMatchingVersion = null;
-                VersionInformation matchingVersion = null;
-                VersionInformation somehowMatchingVersion = null;
-                var viProjectQtVersion = versionManager.GetVersionInfo(projectQtVersion);
-                foreach (var qtVersion in versionManager.GetVersions()) {
-                    var vi = versionManager.GetVersionInfo(qtVersion);
-                    if (tool == null) {
-                        found = File.Exists(vi.qtDir + "\\bin\\designer.exe")
-                            && File.Exists(vi.qtDir + "\\bin\\linguist.exe");
-                    } else {
-                        found = File.Exists(vi.qtDir + tool);
-                    }
-                    if (!found)
-                        continue;
-
-                    if (viProjectQtVersion != null
-                        && vi.qtMajor == viProjectQtVersion.qtMajor
-                        && vi.qtMinor == viProjectQtVersion.qtMinor) {
-                        exactlyMatchingVersion = vi;
-                        break;
-                    }
-                    if (matchingVersion == null
-                        && viProjectQtVersion != null
-                        && vi.qtMajor == viProjectQtVersion.qtMajor) {
-                        matchingVersion = vi;
-                    }
-                    if (somehowMatchingVersion == null)
-                        somehowMatchingVersion = vi;
-                }
-
-                if (exactlyMatchingVersion != null)
-                    qtDir = exactlyMatchingVersion.qtDir;
-                else if (matchingVersion != null)
-                    qtDir = matchingVersion.qtDir;
-                else if (somehowMatchingVersion != null)
-                    qtDir = somehowMatchingVersion.qtDir;
-                else
-                    qtDir = null;
-            }
-            return qtDir;
-        }
-
         static readonly HashSet<string> _sources = new HashSet<string>(new[] { ".c", ".cpp", ".cxx" },
             StringComparer.OrdinalIgnoreCase);
-        static public bool IsSourceFile(string fileName)
+        public static bool IsSourceFile(string fileName)
         {
             return _sources.Contains(Path.GetExtension(fileName));
         }
 
         static readonly HashSet<string> _headers = new HashSet<string>(new[] { ".h", ".hpp", ".hxx" },
             StringComparer.OrdinalIgnoreCase);
-        static public bool IsHeaderFile(string fileName)
+        public static bool IsHeaderFile(string fileName)
         {
             return _headers.Contains(Path.GetExtension(fileName));
         }
@@ -173,23 +95,28 @@
             return ".qml".Equals(Path.GetExtension(fileName), StringComparison.OrdinalIgnoreCase);
         }
 
-        static public void SetDebuggingEnvironment(Project prj)
+        public static void SetDebuggingEnvironment(Project prj)
         {
+            ThreadHelper.ThrowIfNotOnUIThread();
             SetDebuggingEnvironment(prj, string.Empty);
         }
 
-        static public void SetDebuggingEnvironment(Project prj, string solutionConfig)
+        public static void SetDebuggingEnvironment(Project prj, string solutionConfig)
         {
+            ThreadHelper.ThrowIfNotOnUIThread();
             SetDebuggingEnvironment(prj, "PATH=$(QTDIR)\\bin;$(PATH)", false, solutionConfig);
         }
 
-        static public void SetDebuggingEnvironment(Project prj, string envpath, bool overwrite)
+        public static void SetDebuggingEnvironment(Project prj, string envpath, bool overwrite)
         {
+            ThreadHelper.ThrowIfNotOnUIThread();
             SetDebuggingEnvironment(prj, envpath, overwrite, string.Empty);
         }
 
-        static public void SetDebuggingEnvironment(Project prj, string envpath, bool overwrite, string solutionConfig)
+        public static void SetDebuggingEnvironment(Project prj, string envpath, bool overwrite, string solutionConfig)
         {
+            ThreadHelper.ThrowIfNotOnUIThread();
+
             if (QtProject.GetFormatVersion(prj) >= Resources.qtMinFormatVersion_Settings)
                 return;
 
@@ -252,28 +179,29 @@
             }
         }
 
-        public static bool IsProjectInSolution(DTE dteObject, string fullName)
+        public static Project ProjectFromSolution(DTE dteObject, string fullName)
         {
-            var fi = new FileInfo(fullName);
+            ThreadHelper.ThrowIfNotOnUIThread();
 
+            fullName = new FileInfo(fullName).FullName;
             foreach (var p in ProjectsInSolution(dteObject)) {
-                if (p.FullName.ToLower() == fi.FullName.ToLower())
-                    return true;
+                if (p.FullName.Equals(fullName, StringComparison.OrdinalIgnoreCase))
+                    return p;
             }
-            return false;
+            return null;
         }
 
         /// <summary>
         /// Returns the normalized file path of a given file.
         /// </summary>
         /// <param name="name">file name</param>
-        static public string NormalizeFilePath(string name)
+        public static string NormalizeFilePath(string name)
         {
             var fi = new FileInfo(name);
             return fi.FullName;
         }
 
-        static public string NormalizeRelativeFilePath(string path)
+        public static string NormalizeRelativeFilePath(string path)
         {
             if (path == null)
                 return ".\\";
@@ -299,7 +227,7 @@
             return path;
         }
 
-        static public bool IsAbsoluteFilePath(string path)
+        public static bool IsAbsoluteFilePath(string path)
         {
             path = path.Trim();
             if (path.Length >= 2 && path[1] == ':')
@@ -316,7 +244,7 @@
         /// </summary>
         /// <param name="streamReader"></param>
         /// <returns>the composite string</returns>
-        static private string ReadProFileLine(StreamReader streamReader)
+        private static string ReadProFileLine(StreamReader streamReader)
         {
             var line = streamReader.ReadLine();
             if (line == null)
@@ -337,7 +265,7 @@
         /// </summary>
         /// <param name="profile">full name of .pro file to read</param>
         /// <returns>true if this is a subdirs file</returns>
-        static public bool IsSubDirsFile(string profile)
+        public static bool IsSubDirsFile(string profile)
         {
             StreamReader sr = null;
             try {
@@ -407,55 +335,6 @@
         }
 
         /// <summary>
-        /// Replaces a string in the commandLine, description, outputs and additional dependencies
-        /// in all Custom build tools of the project
-        /// </summary>
-        /// <param name="project">Project</param>
-        /// <param name="oldString">String, which is going to be replaced</param>
-        /// <param name="oldString">String, which is going to replace the other one</param>
-        /// <returns></returns>
-        public static void ReplaceInCustomBuildTools(Project project, string oldString, string replaceString)
-        {
-            var vcPro = (VCProject)project.Object;
-            if (vcPro == null)
-                return;
-
-            var qtMsBuild = new QtMsBuildContainer(new VCPropertyStorageProvider());
-            qtMsBuild.BeginSetItemProperties();
-            foreach (VCFile vcfile in (IVCCollection)vcPro.Files) {
-                foreach (VCFileConfiguration config in (IVCCollection)vcfile.FileConfigurations) {
-                    try {
-                        if (vcfile.ItemType == "CustomBuild") {
-                            var tool = GetCustomBuildTool(config);
-                            if (tool == null)
-                                continue;
-
-                            tool.CommandLine = tool.CommandLine
-                                .Replace(oldString, replaceString,
-                                StringComparison.OrdinalIgnoreCase);
-                            tool.Description = tool.Description
-                                .Replace(oldString, replaceString,
-                                StringComparison.OrdinalIgnoreCase);
-                            tool.Outputs = tool.Outputs
-                                .Replace(oldString, replaceString,
-                                StringComparison.OrdinalIgnoreCase);
-                            tool.AdditionalDependencies = tool.AdditionalDependencies
-                                .Replace(oldString, replaceString,
-                                StringComparison.OrdinalIgnoreCase);
-                        } else {
-                            var tool = new QtCustomBuildTool(config, qtMsBuild);
-                            tool.CommandLine = tool.CommandLine
-                                .Replace(oldString, replaceString,
-                                StringComparison.OrdinalIgnoreCase);
-                        }
-                    } catch (Exception) {
-                    }
-                }
-            }
-            qtMsBuild.EndSetItemProperties();
-        }
-
-        /// <summary>
         /// Since VS2010 it is possible to have VCCustomBuildTools without commandlines
         /// for certain filetypes. We are not interested in them and thus try to read the
         /// tool's commandline. If this causes an exception, we ignore it.
@@ -463,23 +342,19 @@
         /// </summary>
         /// <param name="config">File configuration</param>
         /// <returns></returns>
-        static public VCCustomBuildTool GetCustomBuildTool(VCFileConfiguration config)
+        public static VCCustomBuildTool GetCustomBuildTool(VCFileConfiguration config)
         {
-            var file = config.File as VCFile;
-            if (file == null || file.ItemType != "CustomBuild")
-                return null;
-
-            var tool = config.Tool as VCCustomBuildTool;
-            if (tool == null)
-                return null;
-
-            try {
-                // TODO: The return value is not used at all?
-                var cmdLine = tool.CommandLine;
-            } catch {
-                return null;
+            if (config.File is VCFile file
+                && file.ItemType == "CustomBuild"
+                && config.Tool is VCCustomBuildTool tool) {
+                    try {
+                        _ = tool.CommandLine;
+                    } catch {
+                        return null;
+                    }
+                    return tool;
             }
-            return tool;
+            return null;
         }
 
         /// <summary>
@@ -488,8 +363,10 @@
         /// has to be "CustomBuild"
         /// </summary>
         /// <param name="projectItem">Project Item which needs to have custom build tool</param>
-        static public void EnsureCustomBuildToolAvailable(ProjectItem projectItem)
+        public static void EnsureCustomBuildToolAvailable(ProjectItem projectItem)
         {
+            ThreadHelper.ThrowIfNotOnUIThread();
+
             foreach (Property prop in projectItem.Properties) {
                 if (prop.Name == "ItemType") {
                     if ((string)prop.Value != "CustomBuild")
@@ -499,169 +376,10 @@
             }
         }
 
-        /// <summary>
-        /// As Qmake -tp vc Adds the full path to the additional dependencies
-        /// we need to do the same when toggling project kind to qmake generated.
-        /// </summary>
-        /// <returns></returns>
-        private static string AddFullPathToAdditionalDependencies(string qtDir, string additionalDependencies)
-        {
-            var returnString = additionalDependencies;
-            returnString =
-                Regex.Replace(returnString, "Qt(\\S+5?)\\.lib", qtDir + "\\lib\\Qt${1}.lib");
-            returnString =
-                Regex.Replace(returnString, "(qtmaind?5?)\\.lib", qtDir + "\\lib\\${1}.lib");
-            returnString =
-                Regex.Replace(returnString, "(enginiod?5?)\\.lib", qtDir + "\\lib\\${1}.lib");
-            return returnString;
-        }
-
-        /// <summary>
-        /// Toggles the kind of a project. If the project is a QMake generated project (qmake -tp vc)
-        /// it is transformed to an Qt VS Tools project and vice versa.
-        /// </summary>
-        /// <param name="project">Project</param>
-        /// <returns></returns>
-        public static void ToggleProjectKind(Project project)
-        {
-            if (QtProject.GetFormatVersion(project) >= Resources.qtMinFormatVersion_Settings)
-                return;
-
-            string qtDir = null;
-            var vcPro = (VCProject)project.Object;
-            if (!IsQMakeProject(project))
-                return;
-            if (IsQtProject(project)) {
-                // TODO: qtPro is never used.
-                var qtPro = QtProject.Create(project);
-                var vm = QtVersionManager.The();
-                qtDir = vm.GetInstallPath(project);
-
-                foreach (var global in (string[])project.Globals.VariableNames) {
-                    if (global.StartsWith("Qt5Version", StringComparison.Ordinal))
-                        project.Globals.set_VariablePersists(global, false);
-                }
-
-                foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) {
-                    var compiler = CompilerToolWrapper.Create(config);
-                    var linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool");
-                    var librarian = (VCLibrarianTool)((IVCCollection)config.Tools).Item("VCLibrarianTool");
-                    if (compiler != null) {
-                        var additionalIncludes = compiler.GetAdditionalIncludeDirectories();
-                        additionalIncludes = additionalIncludes.Replace("$(QTDIR)", qtDir,
-                            StringComparison.OrdinalIgnoreCase);
-                        compiler.SetAdditionalIncludeDirectories(additionalIncludes);
-                    }
-                    if (linker != null) {
-                        linker.AdditionalLibraryDirectories = linker.AdditionalLibraryDirectories.
-                            Replace("$(QTDIR)", qtDir, StringComparison.OrdinalIgnoreCase);
-                        linker.AdditionalDependencies = AddFullPathToAdditionalDependencies(qtDir, linker.AdditionalDependencies);
-                    } else {
-                        librarian.AdditionalLibraryDirectories = librarian.AdditionalLibraryDirectories
-                            .Replace("$(QTDIR)", qtDir, StringComparison.OrdinalIgnoreCase);
-                        librarian.AdditionalDependencies = AddFullPathToAdditionalDependencies(qtDir, librarian.AdditionalDependencies);
-                    }
-                }
-
-                ReplaceInCustomBuildTools(project, "$(QTDIR)", qtDir);
-            } else {
-                qtDir = GetQtDirFromQMakeProject(project);
-
-                var vm = QtVersionManager.The();
-                var qtVersion = vm.GetQtVersionFromInstallDir(qtDir);
-                if (qtVersion == null)
-                    qtVersion = vm.GetDefaultVersion();
-                if (qtDir == null)
-                    qtDir = vm.GetInstallPath(qtVersion);
-                var vi = vm.GetVersionInfo(qtVersion);
-                var platformName = vi.GetVSPlatformName();
-                vm.SaveProjectQtVersion(project, qtVersion, platformName);
-                var qtPro = QtProject.Create(project);
-                if (!qtPro.SelectSolutionPlatform(platformName) || !qtPro.HasPlatform(platformName)) {
-                    var newProject = false;
-                    qtPro.CreatePlatform("Win32", platformName, null, vi, ref newProject);
-                    if (!qtPro.SelectSolutionPlatform(platformName))
-                        Messages.Print("Can't select the platform " + platformName + ".");
-                }
-
-                var activeConfig = project.ConfigurationManager.ActiveConfiguration.ConfigurationName;
-                var activeVCConfig = (VCConfiguration)((IVCCollection)qtPro.VCProject.Configurations).Item(activeConfig);
-                if (activeVCConfig.ConfigurationType == ConfigurationTypes.typeDynamicLibrary) {
-                    var compiler = CompilerToolWrapper.Create(activeVCConfig);
-                    var linker = (VCLinkerTool)((IVCCollection)activeVCConfig.Tools).Item("VCLinkerTool");
-                    var ppdefs = compiler.GetPreprocessorDefinitions();
-                    if (ppdefs != null
-                        && ppdefs.IndexOf("QT_PLUGIN", StringComparison.Ordinal) > -1
-                        && ppdefs.IndexOf("QDESIGNER_EXPORT_WIDGETS", StringComparison.Ordinal) > -1
-                        && ppdefs.IndexOf("QtDesigner", StringComparison.Ordinal) > -1
-                        && linker.AdditionalDependencies != null
-                        && linker.AdditionalDependencies.IndexOf("QtDesigner", StringComparison.Ordinal) > -1) {
-                        qtPro.MarkAsDesignerPluginProject();
-                    }
-                }
-
-                CleanupQMakeDependencies(project);
-
-                foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) {
-                    var compiler = CompilerToolWrapper.Create(config);
-                    var linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool");
-
-                    if (compiler != null) {
-                        var additionalIncludes = compiler.AdditionalIncludeDirectories;
-                        if (additionalIncludes != null) {
-                            ReplaceDirectory(ref additionalIncludes, qtDir, "$(QTDIR)", project);
-                            compiler.AdditionalIncludeDirectories = additionalIncludes;
-                        }
-                    }
-                    if (linker != null) {
-                        var linkerToolWrapper = new LinkerToolWrapper(linker);
-                        var paths = linkerToolWrapper.AdditionalLibraryDirectories;
-                        if (paths != null) {
-                            ReplaceDirectory(ref paths, qtDir, "$(QTDIR)", project);
-                            linkerToolWrapper.AdditionalLibraryDirectories = paths;
-                        }
-                    }
-                }
-
-                ReplaceInCustomBuildTools(project, qtDir, "$(QTDIR)");
-                qtPro.TranslateFilterNames();
-            }
-            project.Save(project.FullName);
-        }
-
-        /// <summary>
-        /// Replaces every occurrence of oldDirectory with replacement in the array of strings.
-        /// Parameter oldDirectory must be an absolute path.
-        /// This function converts relative directories to absolute paths internally
-        /// and replaces them, if necessary. If no replacement is done, the path isn't altered.
-        /// </summary>
-        /// <param name="project">The project is needed to convert relative paths to absolute paths.</param>
-        private static void ReplaceDirectory(ref List<string> paths, string oldDirectory, string replacement, Project project)
-        {
-            for (var i = 0; i < paths.Count; ++i) {
-                var dirName = paths[i];
-                if (dirName.StartsWith("\"", StringComparison.Ordinal) && dirName.EndsWith("\"", StringComparison.Ordinal)) {
-                    dirName = dirName.Substring(1, dirName.Length - 2);
-                }
-                if (!Path.IsPathRooted(dirName)) {
-                    // convert to absolute path
-                    dirName = Path.Combine(Path.GetDirectoryName(project.FullName), dirName);
-                    dirName = Path.GetFullPath(dirName);
-                    var alteredDirName = dirName.Replace(oldDirectory, replacement, StringComparison
-                        .OrdinalIgnoreCase);
-                    if (alteredDirName == dirName)
-                        continue;
-                    dirName = alteredDirName;
-                } else {
-                    dirName = dirName.Replace(oldDirectory, replacement, StringComparison
-                        .OrdinalIgnoreCase);
-                }
-                paths[i] = dirName;
-            }
-        }
-
         public static string GetQtDirFromQMakeProject(Project project)
         {
+            ThreadHelper.ThrowIfNotOnUIThread();
+
             var vcProject = project.Object as VCProject;
             if (vcProject == null)
                 return null;
@@ -742,13 +460,25 @@
         }
 
         /// <summary>
-        /// Return true if the project is a Qt project, otherwise false.
+        /// Return true if the project is a VS tools project; false otherwise.
         /// </summary>
         /// <param name="proj">project</param>
-        /// <returns></returns>
-        public static bool IsQtProject(VCProject proj)
+        public static bool IsVsToolsProject(Project proj)
         {
-            if (!IsQMakeProject(proj))
+            ThreadHelper.ThrowIfNotOnUIThread(); // C++ Project Type GUID
+            if (proj == null || proj.Kind != "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}")
+                return false;
+            return IsVsToolsProject(proj.Object as VCProject);
+        }
+
+        /// <summary>
+        /// Return true if the project is a VS tools project; false otherwise.
+        /// </summary>
+        /// <param name="proj">project</param>
+        public static bool IsVsToolsProject(VCProject proj)
+        {
+            ThreadHelper.ThrowIfNotOnUIThread();
+            if (!IsQtProject(proj))
                 return false;
 
             if (QtProject.GetFormatVersion(proj) >= Resources.qtMinFormatVersion_Settings)
@@ -759,95 +489,39 @@
                 return false;
 
             foreach (var global in envPro.Globals.VariableNames as string[]) {
-                if (global.StartsWith("Qt5Version", StringComparison.Ordinal) && envPro.Globals.get_VariablePersists(global))
+                if (global.StartsWith("Qt5Version", StringComparison.Ordinal)
+                    && envPro.Globals.get_VariablePersists(global)) {
                     return true;
+                }
             }
             return false;
         }
 
         /// <summary>
-        /// Returns true if the specified project is a Qt Project.
+        /// Return true if the project is a Qt project; false otherwise.
         /// </summary>
         /// <param name="proj">project</param>
         public static bool IsQtProject(Project proj)
         {
-            try {
-                if (proj != null && proj.Kind == "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}")
-                    return IsQtProject(proj.Object as VCProject);
-            } catch { }
-            return false;
+            ThreadHelper.ThrowIfNotOnUIThread(); //C++ Project Type GUID
+            if (proj == null || proj.Kind != "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}")
+                return false;
+            return IsQtProject(proj.Object as VCProject);
         }
 
         /// <summary>
-        /// Return true if the project is a QMake -tp vc project, otherwise false.
+        /// Return true if the project is a Qt project; false otherwise.
         /// </summary>
         /// <param name="proj">project</param>
-        /// <returns></returns>
-        public static bool IsQMakeProject(VCProject proj)
+        public static bool IsQtProject(VCProject proj)
         {
             if (proj == null)
                 return false;
             var keyword = proj.keyword;
-            if (keyword == null ||
-                (!keyword.StartsWith(Resources.qtProjectV2Keyword, StringComparison.Ordinal)
-                && !keyword.StartsWith(Resources.qtProjectKeyword, StringComparison.Ordinal))) {
+            if (string.IsNullOrEmpty(keyword))
                 return false;
-            }
-
-            return true;
-        }
-
-        /// <summary>
-        /// Returns true if the specified project is a QMake -tp vc Project.
-        /// </summary>
-        /// <param name="proj">project</param>
-        public static bool IsQMakeProject(Project proj)
-        {
-            try {
-                if (proj != null && proj.Kind == "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}")
-                    return IsQMakeProject(proj.Object as VCProject);
-            } catch { }
-            return false;
-        }
-
-        public static void CleanupQMakeDependencies(Project project)
-        {
-            var vcPro = (VCProject)project.Object;
-            // clean up qmake mess
-            var rxp1 = new Regex("\\bQt\\w+d?5?\\.lib\\b");
-            var rxp2 = new Regex("\\bQAx\\w+\\.lib\\b");
-            var rxp3 = new Regex("\\bqtmaind?.lib\\b");
-            var rxp4 = new Regex("\\benginiod?.lib\\b");
-            foreach (VCConfiguration cfg in (IVCCollection)vcPro.Configurations) {
-                var linker = (VCLinkerTool)((IVCCollection)cfg.Tools).Item("VCLinkerTool");
-                if (linker == null || linker.AdditionalDependencies == null)
-                    continue;
-                var linkerWrapper = new LinkerToolWrapper(linker);
-                var deps = linkerWrapper.AdditionalDependencies;
-                var newDeps = new List<string>();
-                foreach (var lib in deps) {
-                    var m1 = rxp1.Match(lib);
-                    var m2 = rxp2.Match(lib);
-                    var m3 = rxp3.Match(lib);
-                    var m4 = rxp4.Match(lib);
-                    if (m1.Success)
-                        newDeps.Add(m1.ToString());
-                    else if (m2.Success)
-                        newDeps.Add(m2.ToString());
-                    else if (m3.Success)
-                        newDeps.Add(m3.ToString());
-                    else if (m4.Success)
-                        newDeps.Add(m4.ToString());
-                    else
-                        newDeps.Add(lib);
-                }
-                // Remove Duplicates
-                var uniques = new Dictionary<string, int>();
-                foreach (var dep in newDeps)
-                    uniques[dep] = 1;
-                var uniqueList = new List<string>(uniques.Keys);
-                linkerWrapper.AdditionalDependencies = uniqueList;
-            }
+            return keyword.StartsWith(Resources.qtProjectKeyword, StringComparison.Ordinal)
+                || keyword.StartsWith(Resources.qtProjectV2Keyword, StringComparison.Ordinal);
         }
 
         /// <summary>
@@ -951,6 +625,30 @@
             }
         }
 
+        /// <summary>
+        /// Converts all directory separators of the path to the alternate character
+        /// directory separator. For instance, FromNativeSeparators("c:\\winnt\\system32")
+        /// returns "c:/winnt/system32".
+        /// </summary>
+        /// <param name="path">The path to convert.</param>
+        /// <returns>Returns path using '/' as file separator.</returns>
+        public static string FromNativeSeparators(string path)
+        {
+            return path.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
+        }
+
+        /// <summary>
+        /// Converts all alternate directory separators characters of the path to the native
+        /// directory separator. For instance, ToNativeSeparators("c:/winnt/system32")
+        /// returns "c:\\winnt\\system32".
+        /// </summary>
+        /// <param name="path">The path to convert.</param>
+        /// <returns>Returns path using '\' as file separator.</returns>
+        public static string ToNativeSeparator(string path)
+        {
+            return path.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
+        }
+
         public static string ChangePathFormat(string path)
         {
             return path.Replace('\\', '/');
@@ -981,6 +679,8 @@
 
         public static void CollapseFilter(UIHierarchyItem item, UIHierarchy hierarchy, string nodeToCollapseFilter)
         {
+            ThreadHelper.ThrowIfNotOnUIThread();
+
             if (string.IsNullOrEmpty(nodeToCollapseFilter))
                 return;
 
@@ -994,6 +694,8 @@
 
         public static void CollapseFilter(UIHierarchyItem item, UIHierarchy hierarchy)
         {
+            ThreadHelper.ThrowIfNotOnUIThread();
+
             var subItems = item.UIHierarchyItems;
             if (subItems != null) {
                 foreach (UIHierarchyItem innerItem in subItems) {
@@ -1042,7 +744,7 @@
 
         public static List<string> GetProjectFiles(Project pro, FilesToList filter)
         {
-            var fileList = new List<string>();
+            ThreadHelper.ThrowIfNotOnUIThread();
 
             VCProject vcpro;
             try {
@@ -1052,6 +754,7 @@
                 return null;
             }
 
+            var fileList = new List<string>();
             var configurationName = pro.ConfigurationManager.ActiveConfiguration.ConfigurationName;
 
             foreach (VCFile vcfile in (IVCCollection)vcpro.Files) {
@@ -1120,21 +823,24 @@
         /// <param name="fileName"></param>
         public static void RemoveFileInProject(VCProject vcpro, string fileName)
         {
-            var qtProj = QtProject.Create(vcpro);
-            var fi = new FileInfo(fileName);
+            ThreadHelper.ThrowIfNotOnUIThread();
 
+            fileName = new FileInfo(fileName).FullName;
             foreach (VCFile vcfile in (IVCCollection)vcpro.Files) {
-                if (vcfile.FullPath.ToLower() == fi.FullName.ToLower()) {
+                if (vcfile.FullPath.Equals(fileName, StringComparison.OrdinalIgnoreCase)) {
                     vcpro.RemoveFile(vcfile);
-                    qtProj.MoveFileToDeletedFolder(vcfile);
+                    QtProject.Create(vcpro)?.MoveFileToDeletedFolder(vcfile);
                 }
             }
         }
 
         public static Project GetSelectedProject(DTE dteObject)
         {
+            ThreadHelper.ThrowIfNotOnUIThread();
+
             if (dteObject == null)
                 return null;
+
             Array prjs = null;
             try {
                 prjs = (Array)dteObject.ActiveSolutionProjects;
@@ -1146,30 +852,23 @@
                 return null;
 
             // don't handle multiple selection... use the first one
-            if (prjs.GetValue(0) is Project)
-                return (Project)prjs.GetValue(0);
+            if (prjs.GetValue(0) is Project project)
+                return project;
             return null;
         }
 
         public static Project GetActiveDocumentProject(DTE dteObject)
         {
-            if (dteObject == null)
-                return null;
-            var doc = dteObject.ActiveDocument;
-            if (doc == null)
-                return null;
-
-            if (doc.ProjectItem == null)
-                return null;
-
-            return doc.ProjectItem.ContainingProject;
+            ThreadHelper.ThrowIfNotOnUIThread();
+            return dteObject?.ActiveDocument?.ProjectItem?.ContainingProject;
         }
 
         public static Project GetSingleProjectInSolution(DTE dteObject)
         {
+            ThreadHelper.ThrowIfNotOnUIThread();
+
             var projectList = ProjectsInSolution(dteObject);
-            if (dteObject == null || dteObject.Solution == null ||
-                    projectList.Count != 1)
+            if (projectList.Count != 1)
                 return null; // no way to know which one to select
 
             return projectList[0];
@@ -1182,22 +881,24 @@
         /// </summary>
         public static Project GetSelectedQtProject(DTE dteObject)
         {
+            ThreadHelper.ThrowIfNotOnUIThread();
+
             // can happen sometimes shortly after starting VS
-            if (dteObject == null || dteObject.Solution == null
-                || ProjectsInSolution(dteObject).Count == 0)
+            if (ProjectsInSolution(dteObject).Count == 0)
                 return null;
 
-            Project pro;
-
-            if ((pro = GetSelectedProject(dteObject)) == null) {
+            var pro = GetSelectedProject(dteObject);
+            if (pro == null) {
                 if ((pro = GetSingleProjectInSolution(dteObject)) == null)
                     pro = GetActiveDocumentProject(dteObject);
             }
-            return IsQtProject(pro) ? pro : null;
+            return IsVsToolsProject(pro) ? pro : null;
         }
 
         public static VCFile[] GetSelectedFiles(DTE dteObject)
         {
+            ThreadHelper.ThrowIfNotOnUIThread();
+
             if (GetSelectedQtProject(dteObject) == null)
                 return null;
 
@@ -1239,6 +940,8 @@
 
         public static RccOptions ParseRccOptions(string cmdLine, VCFile qrcFile)
         {
+            ThreadHelper.ThrowIfNotOnUIThread();
+
             var pro = VCProjectToProject((VCProject)qrcFile.project);
 
             var rccOpts = new RccOptions(pro, qrcFile);
@@ -1261,11 +964,17 @@
 
         public static Project VCProjectToProject(VCProject vcproj)
         {
+            ThreadHelper.ThrowIfNotOnUIThread();
             return (Project)vcproj.Object;
         }
 
         public static List<Project> ProjectsInSolution(DTE dteObject)
         {
+            ThreadHelper.ThrowIfNotOnUIThread();
+
+            if (dteObject == null)
+                return new List<Project>();
+
             var projects = new List<Project>();
             var solution = dteObject.Solution;
             if (solution != null) {
@@ -1287,6 +996,8 @@
 
         private static void addSubProjects(Project prj, ref List<Project> projects)
         {
+            ThreadHelper.ThrowIfNotOnUIThread();
+
             // If the actual object of the project is null then the project was probably unloaded.
             if (prj.Object == null)
                 return;
@@ -1303,6 +1014,8 @@
 
         private static void addSubProjects(ProjectItems subItems, ref List<Project> projects)
         {
+            ThreadHelper.ThrowIfNotOnUIThread();
+
             if (subItems == null)
                 return;
 
@@ -1393,21 +1106,6 @@
             return true;
         }
 
-        public static string FindFileInPATH(string fileName)
-        {
-            var envPATH = Environment.ExpandEnvironmentVariables("%PATH%");
-            var directories = envPATH.Split(';');
-            foreach (var directory in directories) {
-                var fullFilePath = directory;
-                if (!fullFilePath.EndsWith("\\", StringComparison.Ordinal))
-                    fullFilePath += '\\';
-                fullFilePath += fileName;
-                if (File.Exists(fullFilePath))
-                    return fullFilePath;
-            }
-            return null;
-        }
-
         /// <summary>
         /// This method copies the specified directory and all its child directories and files to
         /// the specified destination. The destination directory is created if it does not exist.
@@ -1453,13 +1151,14 @@
             string platformName,
             string filePath = null)
         {
+            ThreadHelper.ThrowIfNotOnUIThread();
+
             if (project == null
                 || string.IsNullOrEmpty(configName)
                 || string.IsNullOrEmpty(platformName))
                 return false;
 
             var vcProject = project.Object as VCProject;
-
             if (filePath == null) {
                 var vcConfig = (from VCConfiguration _config
                                 in (IVCCollection)vcProject.Configurations
@@ -1503,12 +1202,10 @@
             VCProject vcProj = null;
             VCFile vcFile = null;
             string configName = "", platformName = "";
-            var vcConfig = config as VCConfiguration;
-            if (vcConfig != null) {
+            if (config is VCConfiguration vcConfig) {
                 vcProj = vcConfig.project as VCProject;
                 configName = vcConfig.ConfigurationName;
-                var vcPlatform = vcConfig.Platform as VCPlatform;
-                if (vcPlatform != null)
+                if (vcConfig.Platform is VCPlatform vcPlatform)
                     platformName = vcPlatform.Name;
                 try {
                     expanded = vcConfig.Evaluate(expanded);
@@ -1520,11 +1217,9 @@
                 vcFile = vcFileConfig.File as VCFile;
                 if (vcFile != null)
                     vcProj = vcFile.project as VCProject;
-                var vcProjConfig = vcFileConfig.ProjectConfiguration as VCConfiguration;
-                if (vcProjConfig != null) {
+                if (vcFileConfig.ProjectConfiguration is VCConfiguration vcProjConfig) {
                     configName = vcProjConfig.ConfigurationName;
-                    var vcPlatform = vcProjConfig.Platform as VCPlatform;
-                    if (vcPlatform != null)
+                    if (vcProjConfig.Platform is VCPlatform vcPlatform)
                         platformName = vcPlatform.Name;
                 }
                 try {
@@ -1637,6 +1332,7 @@
             return true;
         }
 
+#if VS2017
         private static string GetRegistrySoftwareString(string subKeyName, string valueName)
         {
             var keyName = new StringBuilder();
@@ -1644,28 +1340,25 @@
             if (System.Environment.Is64BitOperatingSystem && IntPtr.Size == 4)
                 keyName.Append(@"WOW6432Node\");
             keyName.Append(subKeyName);
-
             try {
                 using (var key = Registry.LocalMachine.OpenSubKey(keyName.ToString(), false)) {
                     if (key == null)
                         return ""; //key not found
-
                     RegistryValueKind valueKind = key.GetValueKind(valueName);
                     if (valueKind != RegistryValueKind.String
                         && valueKind != RegistryValueKind.ExpandString) {
                         return ""; //wrong value kind
                     }
-
                     Object objValue = key.GetValue(valueName);
                     if (objValue == null)
                         return ""; //error getting value
-
                     return objValue.ToString();
                 }
             } catch {
                 return "";
             }
         }
+#endif
 
         public static string GetWindows10SDKVersion()
         {
@@ -1713,11 +1406,6 @@
             string vcPath = Path.Combine(vsPath, "VC");
 #endif
             return vcPath;
-        }
-
-        public static bool SetVCVars(ProcessStartInfo startInfo)
-        {
-            return SetVCVars(null, startInfo);
         }
 
         public static bool SetVCVars(VersionInformation VersionInfo, ProcessStartInfo startInfo)
@@ -1820,8 +1508,21 @@
                     }
                 }
             }
+
+            // Get PATH
             string envPath = startInfo.EnvironmentVariables["PATH"];
-            string clPath = envPath.Split(';')
+
+            // Remove invalid chars
+            envPath = string.Join("", envPath.Split(Path.GetInvalidPathChars()));
+
+            // Split into list of paths
+            var paths = envPath
+                .Split(';')
+                .Where(x => !string.IsNullOrEmpty(x))
+                .Select(x => x.Trim());
+
+            // Check if cl.exe is in PATH
+            string clPath = paths
                 .Select(path => Path.Combine(path, "cl.exe"))
                 .Where(pathToCl => File.Exists(pathToCl))
                 .FirstOrDefault();
@@ -1872,12 +1573,6 @@
             } else {
                 return canonicalPath;
             }
-        }
-
-        public static bool PathEquals(string path1, string path2)
-        {
-            return (CanonicalPath(path1).Equals(CanonicalPath(path2),
-                StringComparison.InvariantCultureIgnoreCase));
         }
 
         public static bool PathIsRelativeTo(string path, string subPath)

--
Gitblit v1.9.1