Beispiel #1
0
        public bool ValidateSDK(InstalledSDK sdk)
        {
            sdk.Owner = this;

            IProject project = PluginBase.CurrentProject;
            string path = sdk.Path;
            if (project != null)
                path = PathHelper.ResolvePath(path, Path.GetDirectoryName(project.ProjectPath));
            else
                path = PathHelper.ResolvePath(path);

            try
            {
                if (path == null || !Directory.Exists(path))
                {
                    //ErrorManager.ShowInfo("Path not found:\n" + sdk.Path);
                    return false;
                }
            }
            catch (Exception ex)
            {
                ErrorManager.ShowInfo("Invalid path (" + ex.Message + "):\n" + sdk.Path);
                return false;
            }

            string[] lookup = new string[] {
                Path.Combine(path, "CHANGES.txt"),
                Path.Combine(path, Path.Combine("doc", "CHANGES.txt"))
            };
            string descriptor = null;
            foreach(string p in lookup)
                if (File.Exists(p)) {
                    descriptor = p;
                    break;
                }
            if (descriptor != null)
            {
                string raw = File.ReadAllText(descriptor);
                Match mVer = Regex.Match(raw, "[0-9\\-]+\\s*:\\s*([0-9.]+)");
                if (mVer.Success)
                {
                    sdk.Version = mVer.Groups[1].Value;
                    sdk.Name = "Haxe " + sdk.Version;
                    return true;
                }
                else ErrorManager.ShowInfo("Invalid changes.txt file:\n" + descriptor);
            }
            else if (File.Exists(Path.Combine(path, "haxe.exe")))
            {
                sdk.Version = "0.0";
                sdk.Name = "Haxe ?";
            }
            else ErrorManager.ShowInfo("No change.txt found:\n" + descriptor);
            return false;
        }
Beispiel #2
0
 /// <summary>
 /// Fix some settings values when the context has been created
 /// </summary>
 private void ValidateSettings()
 {
     if (settingObject.InstalledSDKs == null || settingObject.InstalledSDKs.Length == 0 || PluginBase.MainForm.RefreshConfig)
     {
         string externalSDK;
         InstalledSDK sdk;
         List<InstalledSDK> sdks = new List<InstalledSDK>();
         externalSDK = Environment.ExpandEnvironmentVariables("%HAXEPATH%");
         if (!String.IsNullOrEmpty(externalSDK) && Directory.Exists(PathHelper.ResolvePath(externalSDK)))
         {
             InstalledSDKContext.Current = this;
             sdk = new InstalledSDK(this);
             sdk.Path = externalSDK;
             sdks.Add(sdk);
         }
         if (settingObject.InstalledSDKs != null)
         {
             char[] slashes = new char[] { '/', '\\' };
             foreach (InstalledSDK oldSdk in settingObject.InstalledSDKs)
             {
                 string oldPath = oldSdk.Path.TrimEnd(slashes);
                 foreach (InstalledSDK newSdk in sdks)
                 {
                     string newPath = newSdk.Path.TrimEnd(slashes);
                     if (newPath.Equals(oldPath, StringComparison.OrdinalIgnoreCase))
                     {
                         sdks.Remove(newSdk);
                         break;
                     }
                 }
             }
             sdks.InsertRange(0, settingObject.InstalledSDKs);
         }
         settingObject.InstalledSDKs = sdks.ToArray();
     }
     else foreach (InstalledSDK sdk in settingObject.InstalledSDKs) ValidateSDK(sdk);
     if (settingObject.CompletionServerPort == 0)
     {
         settingObject.CompletionServerPort = 6000;
         settingObject.CompletionMode = HaxeCompletionModeEnum.CompletionServer;
     }
     settingObject.OnClasspathChanged += SettingObjectOnClasspathChanged;
 }
 static public InstalledSDK MatchSDK(InstalledSDK[] sdks, IProject project)
 {
     return MatchSDK(sdks, project.PreferredSDK);
 }
        static public InstalledSDK MatchSDK(InstalledSDK[] sdks, string preferredSDK)
        {
            if (sdks == null) sdks = new InstalledSDK[] { };

            // default sdk
            if (String.IsNullOrEmpty(preferredSDK))
            {
                LatestSDKMatchQuality = -1;
                foreach (InstalledSDK sdk in sdks)
                    if (sdk.IsValid) return sdk;
                return InstalledSDK.INVALID_SDK;
            }

            string[] parts = (";;" + preferredSDK).Split(';'); // name;version
            
            // match name
            string name = parts[parts.Length - 3];
            if (name != "")
                foreach (InstalledSDK sdk in sdks)
                    if (sdk.IsValid && sdk.Name == name)
                    {
                        LatestSDKMatchQuality = 0;
                        return sdk;
                    }

            // match version
            string version = parts[parts.Length - 2];
            if (version != "")
            {
                InstalledSDK bestMatch = null;
                int bestScore = int.MaxValue;
                foreach (InstalledSDK sdk in sdks)
                {
                    if (!sdk.IsValid) continue;
                    int score = CompareVersions(sdk.Version ?? "", version);
                    if (score < bestScore)
                    {
                        bestScore = score;
                        bestMatch = sdk;
                    }
                }
                if (bestMatch != null)
                {
                    LatestSDKMatchQuality = bestScore;
                    return bestMatch;
                }
            }

            // new SDK from path
            string sdkPath = parts[parts.Length - 1];
            if (sdks.Length > 0) InstalledSDKContext.Current = sdks[0].Owner;
            else TraceManager.AddAsync("Warning: compilation may fail if you do not have any (non-custom) SDK configured for the language", -3);
            InstalledSDK newSdk = new InstalledSDK();
            InstalledSDKContext.Current = null;
            newSdk.Path = sdkPath;
            LatestSDKMatchQuality = -1;
            return newSdk;
        }
Beispiel #5
0
 /// <summary>
 /// Fix some settings values when the context has been created
 /// </summary>
 private void ValidateSettings()
 {
     if (settingObject.InstalledSDKs == null || settingObject.InstalledSDKs.Length == 0 || PluginBase.MainForm.RefreshConfig)
     {
         InstalledSDK sdk;
         List<InstalledSDK> sdks = new List<InstalledSDK>();
         string includedSDK;
         includedSDK = "Tools\\flexsdk";
         if (Directory.Exists(PathHelper.ResolvePath(includedSDK)))
         {
             InstalledSDKContext.Current = this;
             sdk = new InstalledSDK(this);
             sdk.Path = includedSDK;
             sdks.Add(sdk);
         }
         includedSDK = "Tools\\ascsdk";
         if (Directory.Exists(PathHelper.ResolvePath(includedSDK)))
         {
             InstalledSDKContext.Current = this;
             sdk = new InstalledSDK(this);
             sdk.Path = includedSDK;
             sdks.Add(sdk);
         }
         if (settingObject.InstalledSDKs != null)
         {
             char[] slashes = new char[] { '/', '\\' };
             foreach (InstalledSDK oldSdk in settingObject.InstalledSDKs)
             {
                 string oldPath = oldSdk.Path.TrimEnd(slashes);
                 foreach (InstalledSDK newSdk in sdks)
                 {
                     string newPath = newSdk.Path.TrimEnd(slashes);
                     if (newPath.Equals(oldPath, StringComparison.OrdinalIgnoreCase))
                     {
                         sdks.Remove(newSdk);
                         break;
                     }
                 }
             }
             sdks.InsertRange(0, settingObject.InstalledSDKs);
         }
         settingObject.InstalledSDKs = sdks.ToArray();
     }
     else foreach (InstalledSDK sdk in settingObject.InstalledSDKs) ValidateSDK(sdk);
     settingObject.OnClasspathChanged += SettingObjectOnClasspathChanged;
     settingObject.OnInstalledSDKsChanged += settingObjectOnInstalledSDKsChanged;
 }
 static public string GetCompilerPath(Project project, InstalledSDK sdk)
 {
     if (project == null) return null;
     project.CurrentSDK = PathHelper.ResolvePath(sdk.Path, project.Directory);
     if (project == PluginBase.CurrentProject) PluginBase.CurrentSDK = sdk;
     return project.CurrentSDK;
 }
Beispiel #7
0
        /// <summary>
        /// Fix some settings values when the context has been created
        /// </summary>
        private void ValidateSettings()
        {
            InstalledSDK sdk;
            List<InstalledSDK> sdks = new List<InstalledSDK>();
            string usersdks = Environment.ExpandEnvironmentVariables("%USERPROFILE%\\.loom\\sdks");
            if (Directory.Exists(usersdks))
                foreach(string dir in Directory.GetDirectories(usersdks))
                {
                    InstalledSDKContext.Current = this;
                    sdk = new InstalledSDK(this);
                    sdk.Path = dir;
                    sdks.Add(sdk);
                }

            if (settingObject.InstalledSDKs != null)
            {
                char[] slashes = new char[] { '/', '\\' };
                foreach (InstalledSDK oldSdk in settingObject.InstalledSDKs)
                {
                    string oldPath = oldSdk.Path.TrimEnd(slashes);
                    foreach (InstalledSDK newSdk in sdks)
                    {
                        string newPath = newSdk.Path.TrimEnd(slashes);
                        if (newPath.Equals(oldPath, StringComparison.OrdinalIgnoreCase))
                        {
                            sdks.Remove(newSdk);
                            break;
                        }
                    }
                }
                sdks.InsertRange(0, settingObject.InstalledSDKs);
            }
            settingObject.InstalledSDKs = sdks.ToArray();
            
            settingObject.OnClasspathChanged += SettingObjectOnClasspathChanged;
            settingObject.OnInstalledSDKsChanged += settingObjectOnInstalledSDKsChanged;
        }
Beispiel #8
0
        public bool ValidateSDK(InstalledSDK sdk)
        {
            sdk.Owner = this;
            
            IProject project = PluginBase.CurrentProject;
            string path = sdk.Path;
            if (project != null)
                path = PathHelper.ResolvePath(path, Path.GetDirectoryName(project.ProjectPath));
            else
                path = PathHelper.ResolvePath(path);
            
            try
            {
                if (path == null || (!Directory.Exists(path) && !File.Exists(path)))
                {
                    ErrorManager.ShowInfo("Path not found:\n" + sdk.Path);
                    return false;
                }
            }
            catch (Exception ex)
            {
                ErrorManager.ShowInfo("Invalid path (" + ex.Message + "):\n" + sdk.Path);
                return false;
            }

            if (!Directory.Exists(path)) path = Path.GetDirectoryName(path);
            string descriptor = Path.Combine(path, "changes.txt");
            if (File.Exists(descriptor))
            {
                string raw = File.ReadAllText(descriptor);
                Match mVer = Regex.Match(raw, "[0-9\\-]+\\s*:\\s*([0-9.]+)");
                if (mVer.Success)
                {
                    sdk.Version = mVer.Groups[1].Value;
                    sdk.Name = "MTASC " + sdk.Version;
                    return true;
                }
                else ErrorManager.ShowInfo("Invalid changes.txt file:\n" + descriptor);
            }
            else ErrorManager.ShowInfo("No changes.txt found:\n" + descriptor);
            return false;
        }
Beispiel #9
0
 /// <summary>
 /// Fix some settings values when the context has been created
 /// </summary>
 private void ValidateSettings()
 {
     if (settingObject.InstalledSDKs == null || settingObject.InstalledSDKs.Length == 0)
     {
         string includedSDK = "Tools\\mtasc";
         if (Directory.Exists(PathHelper.ResolvePath(includedSDK)))
         {
             InstalledSDK sdk = new InstalledSDK(this);
             sdk.Path = includedSDK;
             settingObject.InstalledSDKs = new InstalledSDK[] { sdk };
         }
     }
     else foreach (InstalledSDK sdk in settingObject.InstalledSDKs) ValidateSDK(sdk);
     
     settingObject.OnClasspathChanged += SettingObjectOnClasspathChanged;
 }
 public bool ValidateSDK(InstalledSDK sdk)
 {
     return true;
 }
Beispiel #11
0
        public bool ValidateSDK(InstalledSDK sdk)
        {
            sdk.Owner = this;
            string path = sdk.Path;
            if (path == null) return false;
            Match mBin = Regex.Match(path, "[/\\\\]bin$", RegexOptions.IgnoreCase);
            if (mBin.Success)
                sdk.Path = path = path.Substring(0, mBin.Index);

            IProject project = PluginBase.CurrentProject;
            if (project != null)
                path = PathHelper.ResolvePath(path, Path.GetDirectoryName(project.ProjectPath));
            else
                path = PathHelper.ResolvePath(path);

            try
            {
                if (path == null || !Directory.Exists(path))
                {
                    ErrorManager.ShowInfo("Path not found:\n" + sdk.Path);
                    return false;
                }
            }
            catch (Exception ex)
            {
                ErrorManager.ShowInfo("Invalid path (" + ex.Message + "):\n" + sdk.Path);
                return false;
            }

            string descriptor = Path.Combine(path, "flex-sdk-description.xml");
            if (!File.Exists(descriptor)) 
                descriptor = Path.Combine(path, "air-sdk-description.xml");

            if (File.Exists(descriptor))
            {
                string raw = File.ReadAllText(descriptor);
                Match mName = Regex.Match(raw, "<name>([^<]+)</name>");
                Match mVer = Regex.Match(raw, "<version>([^<]+)</version>");
                if (mName.Success && mVer.Success)
                {
                    sdk.Name = mName.Groups[1].Value;
                    sdk.Version = mVer.Groups[1].Value;

                    descriptor = Path.Combine(path, "AIR SDK Readme.txt");
                    if (sdk.Name.StartsWith("Flex") && File.Exists(descriptor))
                    {
                        raw = File.ReadAllText(descriptor);
                        Match mAIR = Regex.Match(raw, "Adobe AIR ([0-9.]+) SDK");
                        if (mAIR.Success)
                        {
                            sdk.Name += ", AIR " + mAIR.Groups[1].Value;
                            sdk.Version += ", " + mAIR.Groups[1].Value;
                        }
                    }
                    return true;
                }
                else ErrorManager.ShowInfo("Invalid SDK descriptor:\n" + descriptor);
            }
            else ErrorManager.ShowInfo("No SDK descriptor found:\n" + descriptor);
            return false;
        }
Beispiel #12
0
 /// <summary>
 /// Fix some settings values when the context has been created
 /// </summary>
 private void ValidateSettings()
 {
     if (settingObject.InstalledSDKs == null || settingObject.InstalledSDKs.Length == 0 || PluginBase.MainForm.RefreshConfig)
     {
         InstalledSDK sdk;
         List<InstalledSDK> sdks = new List<InstalledSDK>();
         string includedSDK;
         includedSDK = "Tools\\flexsdk";
         if (Directory.Exists(PathHelper.ResolvePath(includedSDK)))
         {
             InstalledSDKContext.Current = this;
             sdk = new InstalledSDK(this);
             sdk.Path = includedSDK;
             sdks.Add(sdk);
         }
         includedSDK = "Tools\\ascsdk";
         if (Directory.Exists(PathHelper.ResolvePath(includedSDK)))
         {
             InstalledSDKContext.Current = this;
             sdk = new InstalledSDK(this);
             sdk.Path = includedSDK;
             sdks.Add(sdk);
         }
         /* Resolve AppMan Flex SDKs */
         string appManDir = Path.Combine(PathHelper.BaseDir, @"Apps\flexsdk");
         if (Directory.Exists(appManDir))
         {
             string[] versionDirs = Directory.GetDirectories(appManDir);
             foreach (string versionDir in versionDirs)
             {
                 if (Directory.Exists(versionDir))
                 {
                     sdk = new InstalledSDK(this);
                     sdk.Path = versionDir;
                     sdks.Add(sdk);
                 }
             }
         }
         /* Resolve AppMan Flex+AIR SDKs */
         appManDir = Path.Combine(PathHelper.BaseDir, @"Apps\flexairsdk");
         if (Directory.Exists(appManDir))
         {
             string[] versionDirs = Directory.GetDirectories(appManDir);
             foreach (string versionDir in versionDirs)
             {
                 if (Directory.Exists(versionDir))
                 {
                     sdk = new InstalledSDK(this);
                     sdk.Path = versionDir;
                     sdks.Add(sdk);
                 }
             }
         }
         /* Resolve AppMan AIR SDKs */
         appManDir = Path.Combine(PathHelper.BaseDir, @"Apps\ascsdk");
         if (Directory.Exists(appManDir))
         {
             string[] versionDirs = Directory.GetDirectories(appManDir);
             foreach (string versionDir in versionDirs)
             {
                 if (Directory.Exists(versionDir))
                 {
                     sdk = new InstalledSDK(this);
                     sdk.Path = versionDir;
                     sdks.Add(sdk);
                 }
             }
         }
         //
         // TODO: Resolve Apache Flex SDK
         //
         if (settingObject.InstalledSDKs != null)
         {
             char[] slashes = new char[] { '/', '\\' };
             foreach (InstalledSDK oldSdk in settingObject.InstalledSDKs)
             {
                 string oldPath = oldSdk.Path.TrimEnd(slashes);
                 foreach (InstalledSDK newSdk in sdks)
                 {
                     string newPath = newSdk.Path.TrimEnd(slashes);
                     if (newPath.Equals(oldPath, StringComparison.OrdinalIgnoreCase))
                     {
                         sdks.Remove(newSdk);
                         break;
                     }
                 }
             }
             sdks.InsertRange(0, settingObject.InstalledSDKs);
         }
         settingObject.InstalledSDKs = sdks.ToArray();
     }
     else
     {
         foreach (InstalledSDK sdk in settingObject.InstalledSDKs)
         {
             sdk.Validate();
         }
     }
     settingObject.OnClasspathChanged += SettingObjectOnClasspathChanged;
     settingObject.OnInstalledSDKsChanged += settingObjectOnInstalledSDKsChanged;
 }
Beispiel #13
0
 public int Compare(InstalledSDK sdk)
 {
     return 0;
 }
Beispiel #14
0
        public bool ValidateSDK(InstalledSDK sdk)
        {
            sdk.Owner = this;

            IProject project = PluginBase.CurrentProject;
            string path = sdk.Path;
            if (project != null)
                path = PathHelper.ResolvePath(path, Path.GetDirectoryName(project.ProjectPath));
            else
                path = PathHelper.ResolvePath(path);

            try
            {
                if (path == null || (!Directory.Exists(path) && !File.Exists(path)))
                {
                    ErrorManager.ShowInfo("Path not found:\n" + sdk.Path);
                    return false;
                }
            }
            catch (Exception ex)
            {
                ErrorManager.ShowInfo("Invalid path (" + ex.Message + "):\n" + sdk.Path);
                return false;
            }

            if (!Directory.Exists(path)) path = Path.GetDirectoryName(path);
            string descriptor = Path.Combine(path, "Unity.exe");
            if (File.Exists(descriptor))
            {
                FileVersionInfo info = FileVersionInfo.GetVersionInfo(descriptor);
                sdk.Version = info.ProductVersion;
                sdk.Name = info.ProductName;
            }
            else ErrorManager.ShowInfo("Unity.exe found:\n" + descriptor);
            return false;
        }
Beispiel #15
0
        public bool ValidateSDK(InstalledSDK sdk)
        {
            sdk.Owner = this;
            string path = sdk.Path;
            Match mBin = Regex.Match(path, "[/\\\\]bin$", RegexOptions.IgnoreCase);
            if (mBin.Success)
                sdk.Path = path = path.Substring(0, mBin.Index);

            IProject project = PluginBase.CurrentProject;
            if (project != null)
                path = PathHelper.ResolvePath(path, Path.GetDirectoryName(project.ProjectPath));
            else
                path = PathHelper.ResolvePath(path);

            try
            {
                if (path == null || !Directory.Exists(path))
                {
                    ErrorManager.ShowInfo("Path not found:\n" + sdk.Path);
                    return false;
                }
            }
            catch (Exception ex)
            {
                ErrorManager.ShowInfo("Invalid path (" + ex.Message + "):\n" + sdk.Path);
                return false;
            }

            string descriptor = Path.Combine(path, "MIN_CLI_VERSION");

            if (File.Exists(descriptor))
            {
                string raw = File.ReadAllText(descriptor);
                Match mVer = Regex.Match(raw, "[0-9.]+");
                if (mVer.Success)
                {
                    sdk.Name = Path.GetFileName(path);
                    sdk.Version = mVer.Value;
                    return true;
                }
                else ErrorManager.ShowInfo("Invalid SDK descriptor:\n" + descriptor);
            }
            else ErrorManager.ShowInfo("No SDK descriptor found:\n" + descriptor);
            return false;
        }
Beispiel #16
0
 /// <summary>
 /// Fix some settings values when the context has been created
 /// </summary>
 private void ValidateSettings()
 {
     if (settingObject.InstalledSDKs == null || settingObject.InstalledSDKs.Length == 0)
     {
         List<InstalledSDK> allSdks = new List<InstalledSDK>();
         string includedSDK = "Tools\\mtasc";
         if (Directory.Exists(PathHelper.ResolvePath(includedSDK)))
         {
             InstalledSDK sdk = new InstalledSDK(this);
             sdk.Path = includedSDK;
             allSdks.Add(sdk);
         }
         string appManDir = Path.Combine(PathHelper.BaseDir, @"Data\AppMan\Archive\mtasc");
         if (Directory.Exists(appManDir))
         {
             string[] versionDirs = Directory.GetDirectories(appManDir);
             foreach (string versionDir in versionDirs)
             {
                 if (Directory.Exists(versionDir))
                 {
                     InstalledSDK sdk = new InstalledSDK(this);
                     sdk.Path = versionDir;
                     allSdks.Add(sdk);
                 }
             }
         }
         settingObject.InstalledSDKs = allSdks.ToArray();
     }
     else
     {
         foreach (InstalledSDK sdk in settingObject.InstalledSDKs)
         {
             sdk.Validate();
         }
     }
     settingObject.OnClasspathChanged += SettingObjectOnClasspathChanged;
 }
        public bool FDBuild(Project project, bool runOutput, bool releaseMode, InstalledSDK sdk)
        {
            string directory = Environment.CurrentDirectory;
            Environment.CurrentDirectory = project.Directory;

            string fdBuildDir = Path.Combine(PathHelper.ToolDir, "fdbuild");
            string fdBuildPath = Path.Combine(fdBuildDir, "fdbuild.exe");

            string arguments = " -ipc " + ipcName;
            if (sdk != null)
            {
                if (!string.IsNullOrEmpty(sdk.Version))
                    arguments += " -version \"" + sdk.Version.Replace(',', ';') + "\"";
                if (!string.IsNullOrEmpty(project.CurrentSDK))
                    arguments += " -compiler \"" + project.CurrentSDK + "\"";
            }

            if (releaseMode) arguments += " -notrace";
            arguments += " -library \"" + PathHelper.LibraryDir + "\"";

            foreach (string cp in PluginMain.Settings.GlobalClasspaths)
            {
                arguments += " -cp \"" + Environment.ExpandEnvironmentVariables(cp) + "\"";
            }

            if (project.TargetBuild != null)
                arguments += " -target \"" + project.TargetBuild + "\"";
            
            arguments = arguments.Replace("\\\"", "\""); // c# console args[] bugfix

            SetStatusBar(TextHelper.GetString("Info.BuildStarted"));
            pluginMain.UpdateUIStatus(ProjectManagerUIStatus.Building);

            // Apache Flex compat
            if (project.Language == "as3") 
            {
                string playerglobalHome = Environment.ExpandEnvironmentVariables("%PLAYERGLOBAL_HOME%");
                if (playerglobalHome.StartsWith("%")) setPlayerglobalHomeEnv = true;
                if (setPlayerglobalHomeEnv)
                {
                    Environment.SetEnvironmentVariable("PLAYERGLOBAL_HOME", Path.Combine(project.CurrentSDK, "frameworks/libs/player"));
                }
            }

            // Lets expose current sdk
            Environment.SetEnvironmentVariable("FD_CUR_SDK", project.CurrentSDK ?? "");

            // run FDBuild
            fdProcess.StartProcess(fdBuildPath, "\"" + project.ProjectPath + "\"" + arguments,
                project.Directory, delegate(bool success)
                {
                    pluginMain.UpdateUIStatus(ProjectManagerUIStatus.NotBuilding);
                    if (success)
                    {
                        SetStatusBar(TextHelper.GetString("Info.BuildSucceeded"));
                        AddTrustFile(project);
                        OnBuildComplete(project, runOutput);
                    }
                    else
                    {
                        SetStatusBar(TextHelper.GetString("Info.BuildFailed"));
                        OnBuildFailed(project, runOutput);
                    }
                    Environment.CurrentDirectory = directory;
                });
            return true;
        }
Beispiel #18
0
 public int Compare(InstalledSDK sdk)
 {
     return(0);
 }
Beispiel #19
0
        public static InstalledSDK MatchSDK(InstalledSDK[] sdks, string preferredSDK)
        {
            if (sdks == null) sdks = new InstalledSDK[] { };

            // default sdk
            if (String.IsNullOrEmpty(preferredSDK))
            {
                LatestSDKMatchQuality = -1;
                foreach (InstalledSDK sdk in sdks)
                    if (sdk.IsValid) return sdk;
                return InstalledSDK.INVALID_SDK;
            }

            string[] parts = (";;" + preferredSDK).Split(';'); // name;version

            // match name
            string name = parts[parts.Length - 3];
            if (name != "")
                foreach (InstalledSDK sdk in sdks)
                    if (sdk.IsValid && sdk.Name == name)
                    {
                        LatestSDKMatchQuality = 0;
                        return sdk;
                    }

            // match version
            string version = parts[parts.Length - 2];
            if (version != "")
            {
                InstalledSDK bestMatch = null;
                int bestScore = int.MaxValue;
                foreach (InstalledSDK sdk in sdks)
                {
                    if (!sdk.IsValid) continue;
                    int score = CompareVersions(sdk.Version ?? "", version);
                    if (score < bestScore)
                    {
                        bestScore = score;
                        bestMatch = sdk;
                    }
                }
                if (bestMatch != null)
                {
                    LatestSDKMatchQuality = bestScore;
                    return bestMatch;
                }
            }

            // new SDK from path
            if (sdks.Length > 0) InstalledSDKContext.Current = sdks[0].Owner;
            InstalledSDK newSdk = new InstalledSDK();
            InstalledSDKContext.Current = null;
            newSdk.Path = parts[parts.Length - 1];
            LatestSDKMatchQuality = -1;
            return newSdk;
        }