diff --git a/.gitignore b/.gitignore index 2b233164..7e38ee53 100644 --- a/.gitignore +++ b/.gitignore @@ -32,8 +32,8 @@ .DS_Store .idea -/ide_plugins/vs/vs2012/CoatiPlugin/CoatiPlugin/bin -/ide_plugins/vs/vs2012/CoatiPlugin/CoatiPlugin/obj +/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/bin +/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/obj *.coatidb *.suo diff --git a/bin/test/data/log/test_log.txt b/bin/test/data/log/test_log.txt index 05aca32c..de1d1319 100644 --- a/bin/test/data/log/test_log.txt +++ b/bin/test/data/log/test_log.txt @@ -83,7 +83,7 @@ Edge.cpp ERROR: Nodes are not plain copies. INFO: handle TestMessage INFO: handle TestMessage INFO: handle TestMessage -NetworkProtocolHelper.cpp ERROR: Failed to parse message, invalid type token +NetworkProtocolHelper.cpp ERROR: Failed to parse message, invalid type token: foo. Expected setActiveToken NetworkProtocolHelper.cpp ERROR: Failed to parse setActiveToken message, invalid token count Settings.cpp WARNING: File for Settings not found: data/SettingsTestSuite/wrong_settings.xml Settings.cpp WARNING: File for Settings not found: data/SettingsTestSuite/wrong_settings.xml diff --git a/ide_plugins/vs/BeforeDeployCheck.ckl b/ide_plugins/vs/BeforeDeployCheck.ckl index d99dc7aa..7049f694 100644 --- a/ide_plugins/vs/BeforeDeployCheck.ckl +++ b/ide_plugins/vs/BeforeDeployCheck.ckl @@ -84,3 +84,13 @@ -Click Create -Close Progress Bar before CDB is finished -Check no new CDB was created +-Switch to Coati + -Keep Visual Studio running + -Open the 'New Project From Visual Studio Solution' + -Click 'Create CDB' button + -Check 'Create Compilation Database' dialog opens + -Create a new CDB with Settings of your choice + -Wait for CDB to be finished + -Click 'Yes' in the 'CDB finished' dialog + -Switch back to Coati + -Check prefilled data is correct \ No newline at end of file diff --git a/ide_plugins/vs/coati_plugin_vs.vsix b/ide_plugins/vs/coati_plugin_vs.vsix index dd2e0e83..fa292cf9 100644 Binary files a/ide_plugins/vs/coati_plugin_vs.vsix and b/ide_plugins/vs/coati_plugin_vs.vsix differ diff --git a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/CoatiPlugin.csproj b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/CoatiPlugin.csproj index 2023db6f..c249f638 100644 --- a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/CoatiPlugin.csproj +++ b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/CoatiPlugin.csproj @@ -138,7 +138,7 @@ - + True diff --git a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/CoatiPluginPackage.cs b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/CoatiPluginPackage.cs index e7a34d64..21248e76 100644 --- a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/CoatiPluginPackage.cs +++ b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/CoatiPluginPackage.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.IO; using EnvDTE; +using System.Windows.Forms; namespace CoatiSoftware.CoatiPlugin { @@ -109,6 +110,8 @@ namespace CoatiSoftware.CoatiPlugin private SolutionEvents _solutionEvents = null; + private bool _validSolutionLoaded = false; + public uint ServerPort { get @@ -147,6 +150,8 @@ namespace CoatiSoftware.CoatiPlugin System.Threading.Thread _serverThread = null; + + public CoatiPluginPackage() {} @@ -159,16 +164,18 @@ namespace CoatiSoftware.CoatiPlugin Utility.FileUtility._errorCallback = new Utility.FileUtility.ErrorCallback(OnFileUtilityError); + // register callbacks for changes of plugin settings OptionPageGrid._serverPortChangeCallback = new OptionPageGrid.Callback(OnServerPortChanged); OptionPageGrid._clientPortChangeCallback = new OptionPageGrid.Callback(OnClientPortChanged); OptionPageGrid._loggingToggled = new OptionPageGrid.Callback(OnLoggingToggled); OptionPageGrid._obfuscationToggled = new OptionPageGrid.Callback(OnObfuscationToggled); + // register the plugin UI elements OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService; if ( null != mcs ) { CommandID setActiveTokenCommandID = new CommandID(GuidList.guidCoatiPluginCmdSet, (int)PkgCmdIDList.cmdidCoatiSetActiveToken); - CommandID createProjectID = new CommandID(GuidList.guidCoatiPluginCmdSet, (int)PkgCmdIDList.cmdidCoatiCreateProject); // cmdidCoatiCreateProject + CommandID createProjectID = new CommandID(GuidList.guidCoatiPluginCmdSet, (int)PkgCmdIDList.cmdidCoatiCreateProject); CommandID createCDBID = new CommandID(GuidList.guidCoatiPluginCmdSet, (int)PkgCmdIDList.cmdidCoatiCreateCDB); _menuItemSetActiveToken = new MenuCommand(MenuItemCallback, setActiveTokenCommandID); @@ -184,8 +191,8 @@ namespace CoatiSoftware.CoatiPlugin mcs.AddCommand(_menuItemCreateCDB); } + // register callbacks to enable/disable interaction for eligible solutions DTE dte = (DTE)GetService(typeof(DTE)); - _solutionEvents = dte.Events.SolutionEvents; _solutionEvents.Opened += OnSolutionOpened; @@ -200,6 +207,7 @@ namespace CoatiSoftware.CoatiPlugin try { + // the coati ui should only be enabled when the solution contains C/C++ projects DTE dte = (DTE)GetService(typeof(DTE)); List languages = Utility.SolutionUtility.GetSolutionLanguages(dte); @@ -220,9 +228,13 @@ namespace CoatiSoftware.CoatiPlugin _menuItemSetActiveToken.Enabled = true; _menuItemCreateProject.Enabled = true; _menuItemCreateCDB.Enabled = true; + + _validSolutionLoaded = true; } else { + _validSolutionLoaded = false; + Logging.Logging.LogInfo("No C/C++ project was detected"); } } @@ -240,6 +252,8 @@ namespace CoatiSoftware.CoatiPlugin _menuItemSetActiveToken.Enabled = false; _menuItemCreateProject.Enabled = false; _menuItemCreateCDB.Enabled = false; + + _validSolutionLoaded = false; } private void InitNetwork() @@ -293,11 +307,37 @@ namespace CoatiSoftware.CoatiPlugin { if(creationResult._cdb != null && creationResult._cdbDirectory.Length > 0 && creationResult._cdbName.Length > 0) { - WriteCDBToFile(creationResult._cdb, creationResult._cdbDirectory, creationResult._cdbName); + if(WriteCDBToFile(creationResult._cdb, creationResult._cdbDirectory, creationResult._cdbName)) + { + string title = "CDB finished"; + string text = "The CDB '" + creationResult._cdbName + "' was created at directory \"" + creationResult._cdbDirectory + "\"\n"; + text += "Do you want to auto-import it in Coati now?"; - //string message = NetworkProtocolUtility.createCreateProjectMessage(creationResult._cdbDirectory + "\\" + creationResult._cdbName, creationResult._headerDirectories); + DialogResult result = MessageBox.Show(text, title, MessageBoxButtons.YesNo, MessageBoxIcon.Warning); - //Utility.AsynchronousClient.Send(message); + if (result == DialogResult.Yes) + { + string message = Utility.NetworkProtocolUtility.CreateCreateProjectMessage(creationResult._cdbDirectory + "\\" + creationResult._cdbName + ".json", creationResult._headerDirectories); + + Utility.AsynchronousClient.Send(message); + } + } + else + { + string title = "Error"; + string text = "Failed to write CDB '" + creationResult._cdbName + "' to directory \"" + creationResult._cdbDirectory + "\"\n"; + + if (LoggingEnabled) + { + text += "See log for details."; + } + else + { + text += "Consider enabling logging to provide additional information (Tools->Options->Coati)."; + } + + DialogResult result = MessageBox.Show(text, title, MessageBoxButtons.OK, MessageBoxIcon.Warning); + } } else { @@ -305,7 +345,7 @@ namespace CoatiSoftware.CoatiPlugin } } - private void WriteCDBToFile(SolutionParser.CompilationDatabase cdb, string directory, string fileName) + private bool WriteCDBToFile(SolutionParser.CompilationDatabase cdb, string directory, string fileName) { try { @@ -314,35 +354,17 @@ namespace CoatiSoftware.CoatiPlugin } catch(Exception e) { - string foo = "Error"; - string bar = "Failed to write CDB '" + fileName + "' to directory \"" + directory + "\"\n"; - bar += "See log for details."; - - Wizard.WindowMessage wm = new Wizard.WindowMessage(); - wm.Title = foo; - wm.Message = bar; - wm.RefreshWindow(); - wm.ShowDialog(); - - bar = "Failed to write CDB '" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(fileName) + "' to directory \"" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(directory) + "\"\n"; - Logging.Logging.LogError(bar); + string text = "Failed to write CDB '" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(fileName) + "' to directory \"" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(directory) + "\"\n"; + Logging.Logging.LogError(text); Logging.Logging.LogError("Exception: " + e.Message); - return; + return false; } - string title = "CDB finished"; - string message = "The CDB '" + fileName + "' was created at directory \"" + directory + "\"\n"; - message += "You can now use it in Coati."; - - Wizard.WindowMessage windowMessage = new Wizard.WindowMessage(); - windowMessage.Title = title; - windowMessage.Message = message; - windowMessage.RefreshWindow(); - windowMessage.ShowDialog(); - - message = "The CDB '" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(fileName) + "' was created at directory \"" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(directory) + "\"\n"; + string message = "The CDB '" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(fileName) + "' was created at directory \"" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(directory) + "\"\n"; Logging.Logging.LogInfo(message); + + return true; } private void MenuItemCallback(object sender, EventArgs e) @@ -361,7 +383,7 @@ namespace CoatiSoftware.CoatiPlugin int lineNumber = Utility.FileUtility.GetActiveLineNumber(dte); int columnNumber = Utility.FileUtility.GetActiveColumnNumber(dte); - string message = NetworkProtocolUtility.createActivateTokenMessage(filePath + fileName, lineNumber, columnNumber); + string message = Utility.NetworkProtocolUtility.CreateActivateTokenMessage(filePath + fileName, lineNumber, columnNumber); Utility.AsynchronousClient.Send(message); } @@ -371,8 +393,7 @@ namespace CoatiSoftware.CoatiPlugin } else if(menuCommand.CommandID.ID == (int)PkgCmdIDList.cmdidCoatiCreateProject) { - // CreateCoatiProjectOld(); - + // show hint to use CDB methad (only for CDB beta) and create project on ok Wizard.WindowMessage windowMessage = new Wizard.WindowMessage(); windowMessage.Title = "Hint"; windowMessage.Message = "Consider using 'Create CDB' if errors arise during Coati's indexing. This will become standard in the future."; @@ -383,6 +404,7 @@ namespace CoatiSoftware.CoatiPlugin } } + // will be removed once the CDB project creation is fully integrated private void CreateCoatiProjectOld() { DTE dte = (DTE)GetService(typeof(DTE)); @@ -401,7 +423,7 @@ namespace CoatiSoftware.CoatiPlugin if (solutionName.Length > 0) { - string message = NetworkProtocolUtility.createCreateProjectMessage(solutionName); + string message = Utility.NetworkProtocolUtility.CreateCreateProjectMessage(solutionName); Utility.AsynchronousClient.Send(message); } @@ -413,16 +435,30 @@ namespace CoatiSoftware.CoatiPlugin private void OnNetworkReadCallback(string message) { - NetworkProtocolUtility.CursorPosition cursorPosition = NetworkProtocolUtility.parseSetCursorMessage(message); - if (cursorPosition.Valid) - { - cursorPosition.ColumnNumber += 1; // VS counts columns starting at 1, coati starts at 0 - DTE dte = (DTE)GetService(typeof(DTE)); - if (Utility.FileUtility.OpenSourceFile(dte, cursorPosition.FilePath)) - { - Utility.FileUtility.GoToLine(dte, cursorPosition.LineNumber, cursorPosition.ColumnNumber); + Utility.NetworkProtocolUtility.MESSAGE_TYPE messageType = Utility.NetworkProtocolUtility.GetMessageType(message); - Utility.SystemUtility.GetWindowFocus(); + if(messageType == Utility.NetworkProtocolUtility.MESSAGE_TYPE.MOVE_CURSOR) + { + Utility.NetworkProtocolUtility.CursorPosition cursorPosition = Utility.NetworkProtocolUtility.ParseSetCursorMessage(message); + if (cursorPosition.Valid) + { + cursorPosition.ColumnNumber += 1; // VS counts columns starting at 1, coati starts at 0 + DTE dte = (DTE)GetService(typeof(DTE)); + if (Utility.FileUtility.OpenSourceFile(dte, cursorPosition.FilePath)) + { + Utility.FileUtility.GoToLine(dte, cursorPosition.LineNumber, cursorPosition.ColumnNumber); + + Utility.SystemUtility.GetWindowFocus(); + } + } + } + else if(messageType == Utility.NetworkProtocolUtility.MESSAGE_TYPE.CREATE_CDB) + { + if(_validSolutionLoaded) + { + DTE dte = (DTE)GetService(typeof(DTE)); + + CreateCompilationDatabase(dte); } } } @@ -521,7 +557,7 @@ namespace CoatiSoftware.CoatiPlugin string solutionName = System.IO.Path.GetFileNameWithoutExtension(dte.Solution.FullName); window.m_solutionFileName = solutionName; - bool containsCFiles = true; // Utility.SolutionUtility.ContainsCFiles(dte); // takes ridiculously long + bool containsCFiles = true; // Utility.SolutionUtility.ContainsCFiles(dte); // takes ridiculously long, I'd rather just display the option by default window.m_containsCFiles = containsCFiles; window.UpdateGUI(); diff --git a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/NetworkProtocolUtility.cs b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/NetworkProtocolUtility.cs deleted file mode 100644 index fd2a5a4b..00000000 --- a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/NetworkProtocolUtility.cs +++ /dev/null @@ -1,172 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace CoatiSoftware.CoatiPlugin -{ - class NetworkProtocolUtility - { - private static string s_divider = ">>"; - private static string s_setActiveTokenPrefix = "setActiveToken"; - private static string s_moveCursorPrefix = "moveCursor"; - private static string s_endOfMessageToken = ""; - - private static string s_createProjectPrefix = "createProject"; - private static string s_createCDBProjectPrefix = "createCDBProject"; - private static string s_ideId = "vs"; - - public class CursorPosition - { - private string _filePath = ""; - private int _lineNumber = 0; - private int _columnNumber = 0; - private bool _valid = false; - - public string FilePath - { - get { return _filePath; } - set { _filePath = value; } - } - - public int LineNumber - { - get { return _lineNumber; } - set { _lineNumber = value; } - } - - public int ColumnNumber - { - get { return _columnNumber; } - set { _columnNumber = value; } - } - - public bool Valid - { - get { return _valid; } - set { _valid = value; } - } - } - - public static string createActivateTokenMessage(string filePath, int lineNumber, int columnNumber) - { - string message = s_setActiveTokenPrefix; - - message += s_divider; - - message += filePath; - - message += s_divider; - - message += lineNumber.ToString(); - - message += s_divider; - - message += columnNumber.ToString(); - - message += s_endOfMessageToken; - - return message; - } - - public static string createCreateProjectMessage(string solutionPath) - { - string message = s_createProjectPrefix; - - message += s_divider; - - message += solutionPath; - - message += s_divider; - - message += s_ideId; - - message += s_endOfMessageToken; - - return message; - } - - public static string createCreateProjectMessage(string cdbPath, List headerPaths) - { - string message = s_createCDBProjectPrefix; - - message += s_divider; - - message += cdbPath; - - message += s_divider; - - foreach(string path in headerPaths) - { - message += path; - - message += s_divider; - } - - message += s_endOfMessageToken; - - return message; - } - - public static CursorPosition parseSetCursorMessage(string message) - { - CursorPosition result = new CursorPosition(); - - // remove eof token right away - if(message.IndexOf(s_endOfMessageToken) > -1) - { - message = message.Substring(0, message.IndexOf(s_endOfMessageToken)); - } - - int pos = message.IndexOf(s_moveCursorPrefix); - - if (pos < 0) - { - return result; - } - - message = message.Substring(pos + s_moveCursorPrefix.Length + s_divider.Length); - - pos = message.IndexOf(s_divider); - - if (pos < 0) - { - return result; - } - - string filePath = message.Substring(0, pos); - result.FilePath = filePath; - - message = message.Substring(pos+2); - - pos = message.IndexOf(s_divider); - - if (pos < 0) - { - return result; - } - - string sLineNumber = message.Substring(0, pos); - int lineNumber = 0; - bool valid = int.TryParse(sLineNumber, out lineNumber); - if (valid) - { - result.LineNumber = lineNumber; - } - - message = message.Substring(pos+2); - - string sColumnNumber = message; - int columnNumber = 0; - valid = int.TryParse(sColumnNumber, out columnNumber); - if (valid) - { - result.ColumnNumber = columnNumber; - result.Valid = true; - } - - return result; - } - } -} diff --git a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Utility/NetworkProtocolUtility.cs b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Utility/NetworkProtocolUtility.cs new file mode 100644 index 00000000..93a3b277 --- /dev/null +++ b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Utility/NetworkProtocolUtility.cs @@ -0,0 +1,237 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CoatiSoftware.CoatiPlugin.Utility +{ + class NetworkProtocolUtility + { + private static string s_divider = ">>"; + private static string s_setActiveTokenPrefix = "setActiveToken"; + private static string s_moveCursorPrefix = "moveCursor"; + private static string s_endOfMessageToken = ""; + + private static string s_createProjectPrefix = "createProject"; + private static string s_createCDBProjectPrefix = "createCDBProject"; + private static string s_ideId = "vs"; + + private static string s_createCDB = "createCDB"; + + public enum MESSAGE_TYPE + { + UNKNOWN = 0, + MOVE_CURSOR, + CREATE_CDB + } + + public class CursorPosition + { + private string _filePath = ""; + private int _lineNumber = 0; + private int _columnNumber = 0; + private bool _valid = false; + + public string FilePath + { + get { return _filePath; } + set { _filePath = value; } + } + + public int LineNumber + { + get { return _lineNumber; } + set { _lineNumber = value; } + } + + public int ColumnNumber + { + get { return _columnNumber; } + set { _columnNumber = value; } + } + + public bool Valid + { + get { return _valid; } + set { _valid = value; } + } + } + + public static string CreateActivateTokenMessage(string filePath, int lineNumber, int columnNumber) + { + string message = s_setActiveTokenPrefix; + + message += s_divider; + + message += filePath; + + message += s_divider; + + message += lineNumber.ToString(); + + message += s_divider; + + message += columnNumber.ToString(); + + message += s_endOfMessageToken; + + return message; + } + + public static string CreateCreateProjectMessage(string solutionPath) + { + string message = s_createProjectPrefix; + + message += s_divider; + + message += solutionPath; + + message += s_divider; + + message += s_ideId; + + message += s_endOfMessageToken; + + return message; + } + + public static string CreateCreateProjectMessage(string cdbPath, List headerPaths) + { + string message = s_createCDBProjectPrefix; + + message += s_divider; + + message += cdbPath; + + message += s_divider; + + foreach(string path in headerPaths) + { + message += path; + + message += s_divider; + } + + message += s_ideId; + + message += s_endOfMessageToken; + + return message; + } + + public static MESSAGE_TYPE GetMessageType(string message) + { + List tokens = GetMessageTokens(message); + + if (tokens.Count > 0) + { + if(tokens[0] == s_createCDB) + { + return MESSAGE_TYPE.CREATE_CDB; + } + else if(tokens[0] == s_moveCursorPrefix) + { + return MESSAGE_TYPE.MOVE_CURSOR; + } + else + { + return MESSAGE_TYPE.UNKNOWN; + } + } + + return MESSAGE_TYPE.UNKNOWN; + } + + public static CursorPosition ParseSetCursorMessage(string message) + { + CursorPosition result = new CursorPosition(); + + List tokens = GetMessageTokens(message); + + if(tokens.Count != 4) + { + Logging.Logging.LogError("Invalid message: " + message); + Logging.Logging.LogError("Invalid token count for 'move cursor' message. Expected 4, but got " + tokens.Count.ToString()); + return result; + } + + if(tokens[0] != s_moveCursorPrefix) + { + Logging.Logging.LogError("Invalid message: " + message); + Logging.Logging.LogError("Invalid message type. Expected '" + s_moveCursorPrefix + "' but got '" + tokens[0] + "'"); + return result; + } + + result.FilePath = tokens[1]; + + int lineNumber = 0; + if(int.TryParse(tokens[2], out lineNumber)) + { + result.LineNumber = lineNumber; + } + else + { + Logging.Logging.LogError("Invalid message: " + message); + Logging.Logging.LogError("Failed to parse line number"); + return result; + } + + int columnNumber = 0; + if(int.TryParse(tokens[3], out columnNumber)) + { + result.ColumnNumber = columnNumber; + } + else + { + Logging.Logging.LogError("Invalid message: " + message); + Logging.Logging.LogError("Failed to parse column number"); + return result; + } + + result.Valid = true; + return result; + } + + private static List GetMessageTokens(string message) + { + List tokens = new List(); + + if(RemoveEOMString(ref message)) + { + tokens = message.Split(s_divider.ToCharArray()).ToList(); + + // removing empty strings + List cleanTokens = new List(); + foreach(string token in tokens) + { + if(token.Length > 0) + { + cleanTokens.Add(token); + } + } + + tokens = cleanTokens; + } + else + { + Logging.Logging.LogError(""); + } + + return tokens; + } + + // returns false if no EOM string was found + private static bool RemoveEOMString(ref string message) + { + if (message.IndexOf(s_endOfMessageToken) > -1) + { + message = message.Substring(0, message.IndexOf(s_endOfMessageToken)); + + return true; + } + + return false; + } + } +} diff --git a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Utility/NetworkUtility.cs b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Utility/NetworkUtility.cs index e384ee49..1b86307f 100644 --- a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Utility/NetworkUtility.cs +++ b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Utility/NetworkUtility.cs @@ -173,23 +173,35 @@ namespace CoatiSoftware.CoatiPlugin.Utility Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - IAsyncResult ar = client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client); - if (!connectDone.WaitOne(2000)) + try { - client.EndConnect(ar); - client.Shutdown(SocketShutdown.Both); - client.Close(); + IAsyncResult ar = client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client); + if (!connectDone.WaitOne(2000)) + { + client.EndConnect(ar); + client.Shutdown(SocketShutdown.Both); + client.Close(); - Logging.Logging.LogWarning("Connection timed out, message was not sent"); + Logging.Logging.LogWarning("Connection timed out, message was not sent"); - return; + return; + } + + Send(client, message); + sendDone.WaitOne(); + } + catch(Exception e) + { + Logging.Logging.LogError("Exception: " + e.Message); + } + finally + { + if(client.Connected) + { + client.Shutdown(SocketShutdown.Both); + client.Close(); + } } - - Send(client, message); - sendDone.WaitOne(); - - client.Shutdown(SocketShutdown.Both); - client.Close(); } private static void ConnectCallback(IAsyncResult ar) diff --git a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Utility/SolutionUtility.cs b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Utility/SolutionUtility.cs index b6553f4c..5a68283c 100644 --- a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Utility/SolutionUtility.cs +++ b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Utility/SolutionUtility.cs @@ -31,7 +31,7 @@ namespace CoatiSoftware.CoatiPlugin.Utility public string Name = ""; public Project Project = null; - public Object Foo = null; + public Object UserData = null; public virtual NodeType GetNodeType() { throw (new NotImplementedException()); } } diff --git a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Wizard/ProjectSetupWindow.cs b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Wizard/ProjectSetupWindow.cs index d84dcaa1..c970bacb 100644 --- a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Wizard/ProjectSetupWindow.cs +++ b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Wizard/ProjectSetupWindow.cs @@ -108,14 +108,14 @@ namespace CoatiSoftware.CoatiPlugin.Wizard if(node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.PROJECT) { TreeNode treeNode = new TreeNode(node.Name); - node.Foo = treeNode; + node.UserData = treeNode; treeViewProjects.Nodes.Add(treeNode); } else if(node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.FOLDER) { TreeNode[] subNodes = GetSubNodes(node as Utility.SolutionUtility.SolutionStructure.FolderNode); TreeNode treeNode = new TreeNode(node.Name, subNodes); - node.Foo = treeNode; + node.UserData = treeNode; treeViewProjects.Nodes.Add(treeNode); } } @@ -130,14 +130,14 @@ namespace CoatiSoftware.CoatiPlugin.Wizard if(node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.PROJECT) { TreeNode treeNode = new TreeNode(node.Name); - node.Foo = treeNode; + node.UserData = treeNode; result.Add(treeNode); } else if(node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.FOLDER) { TreeNode[] subNodes = GetSubNodes(node as Utility.SolutionUtility.SolutionStructure.FolderNode); TreeNode treeNode = new TreeNode(node.Name, subNodes); - node.Foo = treeNode; + node.UserData = treeNode; result.Add(treeNode); } } @@ -297,12 +297,12 @@ namespace CoatiSoftware.CoatiPlugin.Wizard { Utility.SolutionUtility.SolutionStructure.Node node = nodeStack.Pop(); - bool include = (node.Foo as TreeNode).Checked; + bool include = (node.UserData as TreeNode).Checked; string name = node.Name; if(node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.PROJECT - && (node.Foo as TreeNode).Checked == true) + && (node.UserData as TreeNode).Checked == true) { solutionProjects.Add(node.Project); } diff --git a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/source.extension.vsixmanifest b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/source.extension.vsixmanifest index 7e0e4380..23634a66 100644 --- a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/source.extension.vsixmanifest +++ b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/source.extension.vsixmanifest @@ -1,7 +1,7 @@  - + CoatiPlugin This package allows Coati to communicate with Visual Studio and vice versa. https://www.coati.io/ diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 3ac70abd..8449b85a 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -281,6 +281,7 @@ add_files( utility/messaging/type/MessageGraphNodeBundleSplit.h utility/messaging/type/MessageGraphNodeExpand.h utility/messaging/type/MessageGraphNodeMove.h + utility/messaging/type/MessageIDECreateCDB.h utility/messaging/type/MessageInterruptTasks.h utility/messaging/type/MessageLoadProject.h utility/messaging/type/MessageMoveIDECursor.h @@ -307,7 +308,7 @@ add_files( utility/messaging/type/MessageWindowClosed.h utility/messaging/type/MessageWindowFocus.h utility/messaging/type/MessageZoom.h - + utility/messaging/Message.h utility/messaging/MessageBase.h utility/messaging/MessageInterruptTasksCounter.cpp diff --git a/src/lib/component/controller/IDECommunicationController.cpp b/src/lib/component/controller/IDECommunicationController.cpp index 039fc5d0..61c03c45 100644 --- a/src/lib/component/controller/IDECommunicationController.cpp +++ b/src/lib/component/controller/IDECommunicationController.cpp @@ -44,6 +44,10 @@ void IDECommunicationController::handleIncomingMessage(const std::string& messag { handleSetActiveTokenMessage(NetworkProtocolHelper::parseSetActiveTokenMessage(message)); } + else if (type == NetworkProtocolHelper::MESSAGE_TYPE::CREATE_CDB_MESSAGE) + { + handleCreateCDBProjectMessage(NetworkProtocolHelper::parseCreateCDBProjectMessage(message)); + } else { handleCreateProjectMessage(NetworkProtocolHelper::parseCreateProjectMessage(message)); @@ -139,9 +143,37 @@ void IDECommunicationController::handleCreateProjectMessage(const NetworkProtoco } } +void IDECommunicationController::handleCreateCDBProjectMessage(const NetworkProtocolHelper::CreateCDBProjectMessage& message) +{ + if (message.valid) + { + std::shared_ptr msg = std::make_shared(); + msg->setSolutionPath(message.cdbFileLocation); + msg->setHeaderPaths(message.headerPaths); + msg->ideId = message.ideId; + + bool foo = msg->fromCDB(); + + MessageDispatchWhenLicenseValid(msg).dispatch(); + } + else + { + LOG_ERROR_STREAM(<< "Unable to parse provided CDB, invalid data received"); + } +} + +void IDECommunicationController::handleMessage(MessageIDECreateCDB* message) +{ + std::string networkMessage = NetworkProtocolHelper::buildCreateCDBMessage(); + + MessageStatus("Requesting IDE to create CDB.").dispatch(); + + sendMessage(networkMessage); +} + void IDECommunicationController::handleMessage(MessageMoveIDECursor* message) { - std::string networkMessage = NetworkProtocolHelper::buildMessage( + std::string networkMessage = NetworkProtocolHelper::buildSetIDECursorMessage( message->FilePosition, message->Row, message->Column ); diff --git a/src/lib/component/controller/IDECommunicationController.h b/src/lib/component/controller/IDECommunicationController.h index 102da9c4..de348226 100644 --- a/src/lib/component/controller/IDECommunicationController.h +++ b/src/lib/component/controller/IDECommunicationController.h @@ -7,6 +7,7 @@ #include "component/controller/helper/NetworkProtocolHelper.h" #include "utility/messaging/MessageListener.h" +#include "utility/messaging/type/MessageIDECreateCDB.h" #include "utility/messaging/type/MessageMoveIDECursor.h" #include "utility/messaging/type/MessagePluginPortChange.h" @@ -14,6 +15,7 @@ class StorageAccess; class IDECommunicationController : public Controller + , public MessageListener , public MessageListener , public MessageListener { @@ -35,7 +37,9 @@ public: private: void handleSetActiveTokenMessage(const NetworkProtocolHelper::SetActiveTokenMessage& message); void handleCreateProjectMessage(const NetworkProtocolHelper::CreateProjectMessage& message); + void handleCreateCDBProjectMessage(const NetworkProtocolHelper::CreateCDBProjectMessage& message); + virtual void handleMessage(MessageIDECreateCDB* message); virtual void handleMessage(MessageMoveIDECursor* message); virtual void handleMessage(MessagePluginPortChange* message); virtual void sendMessage(const std::string& message) const = 0; diff --git a/src/lib/component/controller/helper/NetworkProtocolHelper.cpp b/src/lib/component/controller/helper/NetworkProtocolHelper.cpp index 3d9806af..76911e91 100644 --- a/src/lib/component/controller/helper/NetworkProtocolHelper.cpp +++ b/src/lib/component/controller/helper/NetworkProtocolHelper.cpp @@ -14,6 +14,8 @@ std::string NetworkProtocolHelper::m_setActiveTokenPrefix = "setActiveToken"; std::string NetworkProtocolHelper::m_moveCursorPrefix = "moveCursor"; std::string NetworkProtocolHelper::m_endOfMessageToken = ""; std::string NetworkProtocolHelper::m_createProjectPrefix = "createProject"; +std::string NetworkProtocolHelper::m_createCDBProjectPrefix = "createCDBProject"; +std::string NetworkProtocolHelper::m_createCDBPrefix = "createCDB"; NetworkProtocolHelper::MESSAGE_TYPE NetworkProtocolHelper::getMessageType(const std::string& message) { @@ -29,6 +31,10 @@ NetworkProtocolHelper::MESSAGE_TYPE NetworkProtocolHelper::getMessageType(const { return MESSAGE_TYPE::CREATE_PROJECT; } + else if (subMessages[0] == m_createCDBProjectPrefix) + { + return MESSAGE_TYPE::CREATE_CDB_MESSAGE; + } else { return MESSAGE_TYPE::UNKNOWN; @@ -74,7 +80,7 @@ NetworkProtocolHelper::SetActiveTokenMessage NetworkProtocolHelper::parseSetActi } else { - LOG_ERROR_STREAM(<< "Failed to parse message, invalid type token"); + LOG_ERROR_STREAM(<< "Failed to parse message, invalid type token: " << subMessages[0] << ". Expected " << m_setActiveTokenPrefix); } } @@ -111,18 +117,88 @@ NetworkProtocolHelper::CreateProjectMessage NetworkProtocolHelper::parseCreatePr networkMessage.valid = true; } + else + { + LOG_WARNING_STREAM(<< "Failed to parse ide ID string. Is " << ideId); + } } } else { - LOG_ERROR_STREAM(<< "Failed to parse message, invalid type token"); + LOG_ERROR_STREAM(<< "Failed to parse message, invalid type token: " << subMessages[0] << ". Expected " << m_createProjectPrefix); } } return networkMessage; } -std::string NetworkProtocolHelper::buildMessage(const std::string& fileLocation, const unsigned int row, const unsigned int column) +NetworkProtocolHelper::CreateCDBProjectMessage NetworkProtocolHelper::parseCreateCDBProjectMessage(const std::string& message) +{ + std::vector subMessages = divideMessage(message); + + NetworkProtocolHelper::CreateCDBProjectMessage networkMessage; + + if (subMessages.size() > 0) + { + if (subMessages[0] == m_createCDBProjectPrefix) + { + if (subMessages.size() < 4) + { + LOG_ERROR_STREAM(<< "Failed to parse createCDBProject message, too few tokens"); + } + else + { + int subMessageCount = subMessages.size(); + + std::string cdbPath = subMessages[1]; + if (cdbPath.length() > 0) + { + networkMessage.cdbFileLocation = cdbPath; + } + else + { + LOG_WARNING_STREAM(<< "CDB file path is not set."); + } + + std::vector headerPaths; + for (int i = 2; i < subMessageCount - 2; i++) + { + if (subMessages[i].length() > 0) + { + headerPaths.push_back(subMessages[i]); + } + } + networkMessage.headerPaths = headerPaths; + + std::string ideId = subMessages[subMessageCount - 2]; + if (ideId.length() > 0) + { + std::string nonConstId = ideId; + boost::algorithm::to_lower(nonConstId); + + networkMessage.ideId = nonConstId; + } + else + { + LOG_WARNING_STREAM(<< "Failed to parse ide ID string. Is " << ideId); + } + + if (networkMessage.cdbFileLocation.length() > 0 && networkMessage.ideId.length() > 0) + { + networkMessage.valid = true; + } + } + } + else + { + LOG_ERROR_STREAM(<< "Failed to parse message, invalid type token: " << subMessages[0] << ". Expected " << m_createCDBProjectPrefix); + } + } + + return networkMessage; +} + +std::string NetworkProtocolHelper::buildSetIDECursorMessage(const std::string& fileLocation, const unsigned int row, const unsigned int column) { std::stringstream messageStream; @@ -138,6 +214,16 @@ std::string NetworkProtocolHelper::buildMessage(const std::string& fileLocation, return messageStream.str(); } +std::string NetworkProtocolHelper::buildCreateCDBMessage() +{ + std::stringstream messageStream; + + messageStream << m_createCDBPrefix; + messageStream << m_endOfMessageToken; + + return messageStream.str(); +} + std::vector NetworkProtocolHelper::divideMessage(const std::string& message) { std::vector result; diff --git a/src/lib/component/controller/helper/NetworkProtocolHelper.h b/src/lib/component/controller/helper/NetworkProtocolHelper.h index 9bf1b087..45d7d7cf 100644 --- a/src/lib/component/controller/helper/NetworkProtocolHelper.h +++ b/src/lib/component/controller/helper/NetworkProtocolHelper.h @@ -37,19 +37,38 @@ public: bool valid; }; + struct CreateCDBProjectMessage + { + public: + CreateCDBProjectMessage() + : cdbFileLocation("") + , headerPaths() + , ideId("") + , valid(false) + {} + + std::string cdbFileLocation; + std::vector headerPaths; + std::string ideId; + bool valid; + }; + enum MESSAGE_TYPE { UNKNOWN = 0, SET_ACTIVE_TOKEN, - CREATE_PROJECT + CREATE_PROJECT, + CREATE_CDB_MESSAGE }; static MESSAGE_TYPE getMessageType(const std::string& message); static SetActiveTokenMessage parseSetActiveTokenMessage(const std::string& message); static CreateProjectMessage parseCreateProjectMessage(const std::string& message); + static CreateCDBProjectMessage parseCreateCDBProjectMessage(const std::string& message); - static std::string buildMessage(const std::string& fileLocation, const unsigned int row, const unsigned int column); + static std::string buildSetIDECursorMessage(const std::string& fileLocation, const unsigned int row, const unsigned int column); + static std::string buildCreateCDBMessage(); private: static std::vector divideMessage(const std::string& message); @@ -64,6 +83,8 @@ private: static std::string m_moveCursorPrefix; static std::string m_endOfMessageToken; static std::string m_createProjectPrefix; + static std::string m_createCDBProjectPrefix; + static std::string m_createCDBPrefix; }; #endif // NETWORK_PROTOCOL_HELPER_H \ No newline at end of file diff --git a/src/lib/utility/messaging/type/MessageIDECreateCDB.h b/src/lib/utility/messaging/type/MessageIDECreateCDB.h new file mode 100644 index 00000000..79174634 --- /dev/null +++ b/src/lib/utility/messaging/type/MessageIDECreateCDB.h @@ -0,0 +1,24 @@ +#ifndef MESSAGE_IDE_CREATE_CDB_H +#define MESSAGE_IDE_CREATE_CDB_H + +#include "utility/messaging/Message.h" + +class MessageIDECreateCDB : public Message +{ +public: + MessageIDECreateCDB() + { + } + + static const std::string getStaticType() + { + return "MessageIDECreateCDB"; + } + + virtual void print(std::ostream& os) const + { + os << "Create CDB from current solution"; + } +}; + +#endif // MESSAGE_IDE_CREATE_CDB_H \ No newline at end of file diff --git a/src/lib/utility/messaging/type/MessageProjectNew.h b/src/lib/utility/messaging/type/MessageProjectNew.h index 6670b203..1f2b5cb4 100644 --- a/src/lib/utility/messaging/type/MessageProjectNew.h +++ b/src/lib/utility/messaging/type/MessageProjectNew.h @@ -9,6 +9,7 @@ class MessageProjectNew public: MessageProjectNew() : solutionPath("") + , headerPaths() , ideId("") { } @@ -23,12 +24,38 @@ public: return solutionPath.size() > 0; } + bool fromCDB() const + { + if (solutionPath.length() > 0) + { + size_t pos = solutionPath.find_last_of('.'); + if (pos != std::string::npos) + { + std::string extension = solutionPath.substr(pos + 1); + + return (extension == "json"); + } + else + { + return false; + } + } + + return false; + } + void setSolutionPath(const std::string& path) { solutionPath = path; } + void setHeaderPaths(const std::vector& headerPaths) + { + this->headerPaths = headerPaths; + } + std::string solutionPath; + std::vector headerPaths; std::string ideId; }; diff --git a/src/lib_gui/qt/network/QtTcpWrapper.cpp b/src/lib_gui/qt/network/QtTcpWrapper.cpp index a08be9e9..008ef207 100644 --- a/src/lib_gui/qt/network/QtTcpWrapper.cpp +++ b/src/lib_gui/qt/network/QtTcpWrapper.cpp @@ -1,4 +1,5 @@ #include "QtTcpWrapper.h" +#include "qdatastream.h" #include "utility/logging/logging.h" @@ -100,12 +101,32 @@ void QtTcpWrapper::acceptConnection() void QtTcpWrapper::startRead() { - char buffer[1024] = { 0 }; + QByteArray byteArray; + while (m_tcpClient->atEnd() == false) + { + QByteArray data = m_tcpClient->read(128); + byteArray += data; + } + + /*QDataStream stream(&byteArray, QIODevice::ReadOnly); + QString string; + stream >> string;*/ + + QString string = QString::fromUtf8(byteArray); + + if (m_readCallback != NULL) + { + std::string message = string.toStdString(); + m_readCallback(message); + } + + /*char buffer[1024] = { 0 }; m_tcpClient->read(buffer, m_tcpClient->bytesAvailable()); + m_tcpClient->close(); if (m_readCallback != NULL) { m_readCallback(buffer); - } + }*/ } diff --git a/src/lib_gui/qt/view/QtMainView.cpp b/src/lib_gui/qt/view/QtMainView.cpp index 9e9c42b1..d68585ac 100644 --- a/src/lib_gui/qt/view/QtMainView.cpp +++ b/src/lib_gui/qt/view/QtMainView.cpp @@ -5,6 +5,7 @@ QtMainView::QtMainView() : m_editProjectFunctor(std::bind(&QtMainView::doEditProject, this)) , m_createNewProjectFromSolutionFunctor(std::bind(&QtMainView::doCreateNewProjectFromSolution, this, std::placeholders::_1, std::placeholders::_2)) + , m_createNewProjectFromCDBFunctor(std::bind(&QtMainView::doCreateNewProjectFromCDB, this, std::placeholders::_1, std::placeholders::_2)) , m_showStartScreenFunctor(std::bind(&QtMainView::doShowStartScreen, this)) , m_hideStartScreenFunctor(std::bind(&QtMainView::doHideStartScreen, this)) , m_setTitleFunctor(std::bind(&QtMainView::doSetTitle, this, std::placeholders::_1)) @@ -117,7 +118,14 @@ void QtMainView::handleMessage(MessageProjectNew* message) { if (message->ideId.size() != 0 && message->solutionPath.size() != 0) { - m_createNewProjectFromSolutionFunctor(message->ideId, message->solutionPath); + if (message->fromCDB() == false) + { + m_createNewProjectFromSolutionFunctor(message->ideId, message->solutionPath); + } + else + { + m_createNewProjectFromCDBFunctor(message->solutionPath, message->headerPaths); + } } } @@ -136,6 +144,11 @@ void QtMainView::doCreateNewProjectFromSolution(const std::string& ideId, const m_window->newProjectFromSolution(ideId, solutionPath); } +void QtMainView::doCreateNewProjectFromCDB(const std::string& filePath, const std::vector& headerPaths) +{ + m_window->newProjectFromCDB(filePath, headerPaths); +} + void QtMainView::doShowStartScreen() { m_window->showStartScreen(); diff --git a/src/lib_gui/qt/view/QtMainView.h b/src/lib_gui/qt/view/QtMainView.h index 3f64280d..6c29e982 100644 --- a/src/lib_gui/qt/view/QtMainView.h +++ b/src/lib_gui/qt/view/QtMainView.h @@ -58,6 +58,7 @@ private: void doEditProject(); void doCreateNewProjectFromSolution(const std::string& ideId, const std::string& solutionPath); + void doCreateNewProjectFromCDB(const std::string& filePath, const std::vector& headerPaths); void doShowStartScreen(); void doHideStartScreen(); void doSetTitle(const std::string& title); @@ -70,6 +71,7 @@ private: QtThreadedFunctor<> m_editProjectFunctor; QtThreadedFunctor m_createNewProjectFromSolutionFunctor; + QtThreadedFunctor&> m_createNewProjectFromCDBFunctor; QtThreadedFunctor<> m_showStartScreenFunctor; QtThreadedFunctor<> m_hideStartScreenFunctor; QtThreadedFunctor m_setTitleFunctor; diff --git a/src/lib_gui/qt/window/QtMainWindow.cpp b/src/lib_gui/qt/window/QtMainWindow.cpp index 8df1ec1a..83cb3d29 100644 --- a/src/lib_gui/qt/window/QtMainWindow.cpp +++ b/src/lib_gui/qt/window/QtMainWindow.cpp @@ -436,6 +436,12 @@ void QtMainWindow::newProjectFromSolution(const std::string& ideId, const std::s wizzard->newProjectFromSolution(ideId, solutionPath); } +void QtMainWindow::newProjectFromCDB(const std::string& filePath, const std::vector& headerPaths) +{ + QtProjectWizzard* wizzard = createWindow(); + wizzard->newProjectFromCDB(filePath, headerPaths); +} + void QtMainWindow::openProject() { QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", "Coati Project Files (*.coatiproject)"); diff --git a/src/lib_gui/qt/window/QtMainWindow.h b/src/lib_gui/qt/window/QtMainWindow.h index ace75244..2be46f94 100644 --- a/src/lib_gui/qt/window/QtMainWindow.h +++ b/src/lib_gui/qt/window/QtMainWindow.h @@ -110,6 +110,7 @@ public slots: void newProject(); void newProjectFromSolution(const std::string& ideId, const std::string& solutionPath); + void newProjectFromCDB(const std::string& filePath, const std::vector& headerPaths); void openProject(); void editProject(); diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzard.cpp b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzard.cpp index 56dd6222..49593785 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzard.cpp +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzard.cpp @@ -116,6 +116,26 @@ void QtProjectWizzard::newProjectFromSolution(const std::string& ideId, const st } } +void QtProjectWizzard::newProjectFromCDB(const std::string& filePath, const std::vector& headerPaths) +{ + FilePath fp(filePath); + + std::vector hp; + for (int i = 0; i < headerPaths.size(); i++) + { + hp.push_back(FilePath(headerPaths[i])); + } + + std::shared_ptr settings = std::make_shared(); + settings->setLanguage(LanguageType::LANGUAGE_CPP); + settings->setProjectName(fp.withoutExtension().fileName()); + settings->setProjectFileLocation(fp.parentDirectory()); + settings->setCompilationDatabasePath(fp); + settings->setSourcePaths(hp); + m_settings = settings; + emptyProjectCDBVS(); +} + void QtProjectWizzard::refreshProjectFromSolution(const std::string& ideId, const std::string& visualStudioSolutionPath) { if (m_parserManager->canParseSolution(ideId)) @@ -323,7 +343,7 @@ void QtProjectWizzard::selectedProjectType(LanguageType languageType, QtProjectW break; case QtProjectWizzardContentSelect::PROJECT_MANAGED: - { + /*{ std::string fileEndings = "("; for (unsigned int i = 0; i < m_parserManager->getParserCount(); i++) { @@ -346,7 +366,12 @@ void QtProjectWizzard::selectedProjectType(LanguageType languageType, QtProjectW } } break; - } + }*/ + + m_settings = std::make_shared(); + m_settings->setLanguage(languageType); + emptyProjectCDBVS(); + break; case QtProjectWizzardContentSelect::PROJECT_CDB: m_settings = std::make_shared(); @@ -428,6 +453,13 @@ void QtProjectWizzard::frameworkSearchPaths() connect(window, SIGNAL(next()), this, SLOT(showSummary())); } +void QtProjectWizzard::emptyProjectCDBVS() +{ + QtProjectWizzardWindow* window = createWindowWithContent(); + + connect(window, SIGNAL(next()), this, SLOT(headerPathsCDB())); +} + void QtProjectWizzard::emptyProjectCDB() { QtProjectWizzardWindow* window = createWindowWithContent(); diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzard.h b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzard.h index 68ae9f5a..cc63b857 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzard.h +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzard.h @@ -34,6 +34,7 @@ public slots: void newProject(); void newProjectFromSolution(const std::string& ideId, const std::string& visualStudioSolutionPath); + void newProjectFromCDB(const std::string& filePath, const std::vector& headerPaths); void refreshProjectFromSolution(const std::string& ideId, const std::string& visualStudioSolutionPath); void editProject(const FilePath& settingsPath); @@ -72,6 +73,8 @@ private slots: void headerSearchPathsDone(); void frameworkSearchPaths(); + void emptyProjectCDBVS(); + void emptyProjectCDB(); void headerPathsCDB(); diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentData.cpp b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentData.cpp index 980f9066..36a1c9a3 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentData.cpp +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentData.cpp @@ -5,6 +5,7 @@ #include "settings/CxxProjectSettings.h" +#include "utility/messaging/type/MessageIDECreateCDB.h" #include "utility/logging/logging.h" QtProjectWizzardContentData::QtProjectWizzardContentData(std::shared_ptr settings, QtProjectWizzardWindow* window) @@ -257,3 +258,81 @@ bool QtProjectWizzardContentDataCDB::check() void QtProjectWizzardContentDataCDB::refreshClicked() { } + + + + +QtProjectWizzardContentDataCDBVS::QtProjectWizzardContentDataCDBVS(std::shared_ptr settings, QtProjectWizzardWindow* window) + : QtProjectWizzardContentDataCDB(settings, window) +{ +} + +void QtProjectWizzardContentDataCDBVS::populate(QGridLayout* layout, int& row) +{ + if (!isInForm()) + { + layout->setRowMinimumHeight(row, 15); + row++; + } + + QLabel* nameLabel = createFormLabel("Create Compilation Database"); + layout->addWidget(nameLabel, row, QtProjectWizzardWindow::FRONT_COL); + + addHelpButton("To create a new Compilation Database from a Visual Studio Solution, this Solution has to be open in Visual Studio.\n\ +Coati will call Visual Studio to open the 'Create Compilation Database' dialog.\ + Please follow the instructions in Visual Studio to complete the process.\n\ +Note: Coati's Visual Studio plugin has to be installed. Visual Studio has to be running with an eligible Solution, containing C/C++ projects, loaded.", layout, row); + + QLabel* descriptionLabel = createFormLabel("Call Visual Studio to create a Compilation Database from the loaded Solution."); + descriptionLabel->setObjectName("description"); + descriptionLabel->setAlignment(Qt::AlignmentFlag::AlignLeft); + layout->addWidget(descriptionLabel, row, QtProjectWizzardWindow::BACK_COL); + row++; + + QPushButton* button = new QPushButton("Create CDB"); + button->setObjectName("windowButton"); + layout->addWidget(button, row, QtProjectWizzardWindow::BACK_COL); + row++; + + QLabel* skipLabel = createFormLabel("*Skip this step if you already have a Compilation Database for your Solution."); + skipLabel->setObjectName("description"); + skipLabel->setAlignment(Qt::AlignmentFlag::AlignLeft); + layout->addWidget(skipLabel, row, QtProjectWizzardWindow::BACK_COL); + row++; + + + QFrame* separator = new QFrame(); + separator->setFrameShape(QFrame::HLine); + + QPalette palette = separator->palette(); + palette.setColor(QPalette::WindowText, Qt::lightGray); + separator->setPalette(palette); + + layout->addWidget(separator, row++, 0, 1, -1); + + + connect(button, SIGNAL(clicked()), this, SLOT(handleVSCDBClicked())); + + addNameAndLocation(layout, row); + + layout->setRowMinimumHeight(row++, 20); + + QString name = "Compilation Database"; + QString filter = "JSON Compilation Database (*.json)"; + addBuildFilePicker(layout, row, name, filter); + + if (!isInForm()) + { + layout->setRowMinimumHeight(row, 15); + layout->setRowStretch(row, 1); + } +} + +void QtProjectWizzardContentDataCDBVS::refreshClicked() +{ +} + +void QtProjectWizzardContentDataCDBVS::handleVSCDBClicked() +{ + MessageIDECreateCDB().dispatch(); +} diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentData.h b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentData.h index c64eda18..16402232 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentData.h +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentData.h @@ -55,4 +55,19 @@ private slots: void refreshClicked(); }; +class QtProjectWizzardContentDataCDBVS + : public QtProjectWizzardContentDataCDB +{ + Q_OBJECT + +public: + QtProjectWizzardContentDataCDBVS(std::shared_ptr settings, QtProjectWizzardWindow* window); + + virtual void populate(QGridLayout* layout, int& row) override; + +private slots: + void refreshClicked(); + void handleVSCDBClicked(); +}; + #endif // QT_PROJECT_WIZZARD_CONTENT_DATA_H diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardWindow.cpp b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardWindow.cpp index 7223595f..d4d2c8a4 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardWindow.cpp +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardWindow.cpp @@ -44,7 +44,7 @@ void QtProjectWizzardWindow::populateWindow(QWidget* widget) { QGridLayout* layout = new QGridLayout(); layout->setContentsMargins(0, 0, 0, 0); - + layout->setColumnStretch(QtProjectWizzardWindow::FRONT_COL, 1); layout->setColumnStretch(QtProjectWizzardWindow::BACK_COL, 3); diff --git a/web/blog/images/vs_plugin_upgrade/dialog_0.png b/web/blog/images/vs_plugin_upgrade/dialog_0.png new file mode 100644 index 00000000..dac982ba Binary files /dev/null and b/web/blog/images/vs_plugin_upgrade/dialog_0.png differ diff --git a/web/blog/images/vs_plugin_upgrade/dialog_1.png b/web/blog/images/vs_plugin_upgrade/dialog_1.png new file mode 100644 index 00000000..2b50aac3 Binary files /dev/null and b/web/blog/images/vs_plugin_upgrade/dialog_1.png differ diff --git a/web/blog/images/vs_plugin_upgrade/dialog_2.png b/web/blog/images/vs_plugin_upgrade/dialog_2.png new file mode 100644 index 00000000..e5f0d66f Binary files /dev/null and b/web/blog/images/vs_plugin_upgrade/dialog_2.png differ