logic: vs plugin upgrade

Updated documentation and removed obsolete plugin ui
This commit is contained in:
Manuel Dobusch
2016-11-29 14:06:02 +01:00
parent e1968eaaac
commit d24e5b5bbd
13 changed files with 279 additions and 11 deletions
+2
View File
@@ -12,6 +12,8 @@
* Boost 1.59
* Botan 1.11.34
also something about java, but who knows...
#### Environment Variables
* QT_DIR - .../Qt/Qt5.6.0/5.6/<IDE>
Binary file not shown.
@@ -66,6 +66,7 @@
</Button>
-->
<!--
<Button guid="guidCoatiPluginCmdSet" id="cmdidCoatiCreateProject" priority="0x0100" type="Button">
<Parent guid="guidCoatiPluginCmdSet" id="SubMenu" />
<Icon guid="icon" id="icon0" />
@@ -73,12 +74,13 @@
<ButtonText>Create Coati Project</ButtonText>
</Strings>
</Button>
-->
<Button guid="guidCoatiPluginCmdSet" id="cmdidCoatiCreateCDB" priority="0x0100" type="Button">
<Parent guid="guidCoatiPluginCmdSet" id="SubMenu" />
<Icon guid="icon" id="icon0" />
<Strings>
<ButtonText>Create CDB (Beta)</ButtonText>
<ButtonText>Create CDB</ButtonText>
</Strings>
</Button>
@@ -198,6 +198,8 @@ namespace CoatiSoftware.CoatiPlugin
_solutionEvents.Opened += OnSolutionOpened;
_solutionEvents.AfterClosing += OnSolutionClosed;
SendPing();
Logging.Logging.LogInfo("Initialization done");
}
@@ -287,6 +289,13 @@ namespace CoatiSoftware.CoatiPlugin
Logging.Logging.LogInfo("Logging initialized");
}
private void SendPing()
{
string message = Utility.NetworkProtocolUtility.CreatePingMessage();
Utility.AsynchronousClient.Send(message);
}
private void OnCreateProject(List<EnvDTE.Project> projects, string configurationName, string platformName, string targetDir, string fileName, string cStandard)
{
Wizard.WindowCreateCDB createCDB = new Wizard.WindowCreateCDB();
@@ -461,6 +470,10 @@ namespace CoatiSoftware.CoatiPlugin
CreateCompilationDatabase(dte);
}
}
else if(messageType == Utility.NetworkProtocolUtility.MESSAGE_TYPE.PING)
{
SendPing();
}
}
private void OnNetworkErrorCallback(string message)
@@ -13,17 +13,20 @@ namespace CoatiSoftware.CoatiPlugin.Utility
private static string s_moveCursorPrefix = "moveCursor";
private static string s_endOfMessageToken = "<EOM>";
private static string s_createProjectPrefix = "createProject";
private static string s_createProjectPrefix = "createProject"; // deprecate
private static string s_createCDBProjectPrefix = "createCDBProject";
private static string s_ideId = "vs";
private static string s_createCDB = "createCDB";
private static string s_createCDBPrefix = "createCDB";
private static string s_pingPrefix = "ping";
public enum MESSAGE_TYPE
{
UNKNOWN = 0,
MOVE_CURSOR,
CREATE_CDB
CREATE_CDB,
PING
}
public class CursorPosition
@@ -58,6 +61,24 @@ namespace CoatiSoftware.CoatiPlugin.Utility
}
}
public class Ping
{
private string _id = "";
private bool _valid = false;
public string Id
{
get { return _id; }
set { _id = value; }
}
public bool Valid
{
get { return _valid; }
set { _valid = value; }
}
}
public static string CreateActivateTokenMessage(string filePath, int lineNumber, int columnNumber)
{
string message = s_setActiveTokenPrefix;
@@ -120,20 +141,37 @@ namespace CoatiSoftware.CoatiPlugin.Utility
return message;
}
public static string CreatePingMessage()
{
string message = s_pingPrefix;
message += s_divider;
message += s_ideId;
message += s_endOfMessageToken;
return message;
}
public static MESSAGE_TYPE GetMessageType(string message)
{
List<string> tokens = GetMessageTokens(message);
if (tokens.Count > 0)
{
if(tokens[0] == s_createCDB)
if (tokens[0] == s_createCDBPrefix)
{
return MESSAGE_TYPE.CREATE_CDB;
}
else if(tokens[0] == s_moveCursorPrefix)
else if (tokens[0] == s_moveCursorPrefix)
{
return MESSAGE_TYPE.MOVE_CURSOR;
}
else if (tokens[0] == s_pingPrefix)
{
return MESSAGE_TYPE.PING;
}
else
{
return MESSAGE_TYPE.UNKNOWN;
@@ -193,6 +231,32 @@ namespace CoatiSoftware.CoatiPlugin.Utility
return result;
}
public static Ping ParsePingMessage(string message)
{
Ping result = new Ping();
List<string> tokens = GetMessageTokens(message);
if(tokens.Count != 2)
{
Logging.Logging.LogError("Invalid message: " + message);
Logging.Logging.LogError("Invalid token count for 'ping' message. Expected 2, but got " + tokens.Count.ToString());
return result;
}
if (tokens[0] != s_pingPrefix)
{
Logging.Logging.LogError("Invalid message: " + message);
Logging.Logging.LogError("Invalid message type. Expected '" + s_pingPrefix + "' but got '" + tokens[0] + "'");
return result;
}
result.Id = tokens[1];
result.Valid = true;
return result;
}
private static List<string> GetMessageTokens(string message)
{
List<string> tokens = new List<string>();
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
<Metadata>
<Identity Id="acf15780-03b5-440e-a41e-db79b7043fc2" Version="0.8.25" Language="en-US" Publisher="Coati Software OG" />
<Identity Id="acf15780-03b5-440e-a41e-db79b7043fc2" Version="0.8.28" Language="en-US" Publisher="Coati Software OG" />
<DisplayName>CoatiPlugin</DisplayName>
<Description xml:space="preserve">This package allows Coati to communicate with Visual Studio and vice versa.</Description>
<MoreInfo>https://www.coati.io/</MoreInfo>
+1
View File
@@ -276,6 +276,7 @@ add_files(
utility/messaging/type/MessageLoadProject.h
utility/messaging/type/MessageMoveIDECursor.h
utility/messaging/type/MessageNewErrors.h
utility/messaging/type/MessagePingReceived.h
utility/messaging/type/MessagePluginPortChange.h
utility/messaging/type/MessageProjectEdit.h
utility/messaging/type/MessageProjectNew.h
@@ -12,6 +12,7 @@
#include "utility/messaging/type/MessageProjectNew.h"
#include "utility/messaging/type/MessageStatus.h"
#include "utility/messaging/type/MessageActivateFile.h"
#include "utility/messaging/type/MessagePingReceived.h"
IDECommunicationController::IDECommunicationController(StorageAccess* storageAccess)
: m_storageAccess(storageAccess)
@@ -48,6 +49,10 @@ void IDECommunicationController::handleIncomingMessage(const std::string& messag
{
handleCreateCDBProjectMessage(NetworkProtocolHelper::parseCreateCDBProjectMessage(message));
}
else if (type == NetworkProtocolHelper::MESSAGE_TYPE::PING)
{
handlePing(NetworkProtocolHelper::parsePingMessage(message));
}
else
{
handleCreateProjectMessage(NetworkProtocolHelper::parseCreateProjectMessage(message));
@@ -152,8 +157,6 @@ void IDECommunicationController::handleCreateCDBProjectMessage(const NetworkProt
msg->setHeaderPaths(message.headerPaths);
msg->ideId = message.ideId;
bool foo = msg->fromCDB();
MessageDispatchWhenLicenseValid(msg).dispatch();
}
else
@@ -162,6 +165,32 @@ void IDECommunicationController::handleCreateCDBProjectMessage(const NetworkProt
}
}
void IDECommunicationController::handlePing(const NetworkProtocolHelper::PingMessage& message)
{
if (message.valid)
{
std::shared_ptr<MessagePingReceived> msg = std::make_shared<MessagePingReceived>();
msg->ideId = message.ideId;
std::string ideName = "unknown";
if (msg->ideId == "vs")
{
ideName = "Visual Studio";
}
// TODO: add the other ides
std::string message = ideName + " instance detected";
MessageStatus(message, false, false).dispatch();
MessageDispatchWhenLicenseValid(msg).dispatch();
}
else
{
LOG_ERROR_STREAM(<< "Can't handle ping, message is invalid");
}
}
void IDECommunicationController::handleMessage(MessageIDECreateCDB* message)
{
std::string networkMessage = NetworkProtocolHelper::buildCreateCDBMessage();
@@ -38,6 +38,7 @@ private:
void handleSetActiveTokenMessage(const NetworkProtocolHelper::SetActiveTokenMessage& message);
void handleCreateProjectMessage(const NetworkProtocolHelper::CreateProjectMessage& message);
void handleCreateCDBProjectMessage(const NetworkProtocolHelper::CreateCDBProjectMessage& message);
void handlePing(const NetworkProtocolHelper::PingMessage& message);
virtual void handleMessage(MessageIDECreateCDB* message);
virtual void handleMessage(MessageMoveIDECursor* message);
@@ -14,6 +14,7 @@ std::string NetworkProtocolHelper::m_endOfMessageToken = "<EOM>";
std::string NetworkProtocolHelper::m_createProjectPrefix = "createProject";
std::string NetworkProtocolHelper::m_createCDBProjectPrefix = "createCDBProject";
std::string NetworkProtocolHelper::m_createCDBPrefix = "createCDB";
std::string NetworkProtocolHelper::m_pingPrefix = "ping";
NetworkProtocolHelper::MESSAGE_TYPE NetworkProtocolHelper::getMessageType(const std::string& message)
{
@@ -33,6 +34,10 @@ NetworkProtocolHelper::MESSAGE_TYPE NetworkProtocolHelper::getMessageType(const
{
return MESSAGE_TYPE::CREATE_CDB_MESSAGE;
}
else if (subMessages[0] == m_pingPrefix)
{
return MESSAGE_TYPE::PING;
}
else
{
return MESSAGE_TYPE::UNKNOWN;
@@ -196,6 +201,48 @@ NetworkProtocolHelper::CreateCDBProjectMessage NetworkProtocolHelper::parseCreat
return networkMessage;
}
NetworkProtocolHelper::PingMessage NetworkProtocolHelper::parsePingMessage(const std::string& message)
{
std::vector<std::string> subMessages = divideMessage(message);
NetworkProtocolHelper::PingMessage pingMessage;
if (subMessages.size() > 0)
{
if (subMessages[0] == m_pingPrefix)
{
if (subMessages.size() < 2)
{
LOG_ERROR_STREAM(<< "Failed to parse PingMessage message, too few tokens");
}
else
{
std::string ideId = subMessages[1];
if (ideId.length() > 0)
{
std::string nonConstId = ideId;
boost::algorithm::to_lower(nonConstId);
pingMessage.ideId = ideId;
pingMessage.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: " << subMessages[0] << ". Expected " << m_pingPrefix);
}
}
return pingMessage;
}
std::string NetworkProtocolHelper::buildSetIDECursorMessage(const std::string& fileLocation, const unsigned int row, const unsigned int column)
{
std::stringstream messageStream;
@@ -222,6 +269,18 @@ std::string NetworkProtocolHelper::buildCreateCDBMessage()
return messageStream.str();
}
std::string NetworkProtocolHelper::buildPingMessage()
{
std::stringstream messageStream;
messageStream << m_pingPrefix;
messageStream << m_divider;
messageStream << "coati";
messageStream << m_endOfMessageToken;
return messageStream.str();
}
std::vector<std::string> NetworkProtocolHelper::divideMessage(const std::string& message)
{
std::vector<std::string> result;
@@ -53,12 +53,25 @@ public:
bool valid;
};
struct PingMessage
{
public:
PingMessage()
: ideId("")
, valid(false)
{}
std::string ideId;
bool valid;
};
enum MESSAGE_TYPE
{
UNKNOWN = 0,
SET_ACTIVE_TOKEN,
CREATE_PROJECT,
CREATE_CDB_MESSAGE
CREATE_CDB_MESSAGE,
PING
};
static MESSAGE_TYPE getMessageType(const std::string& message);
@@ -66,9 +79,11 @@ public:
static SetActiveTokenMessage parseSetActiveTokenMessage(const std::string& message);
static CreateProjectMessage parseCreateProjectMessage(const std::string& message);
static CreateCDBProjectMessage parseCreateCDBProjectMessage(const std::string& message);
static PingMessage parsePingMessage(const std::string& message);
static std::string buildSetIDECursorMessage(const std::string& fileLocation, const unsigned int row, const unsigned int column);
static std::string buildCreateCDBMessage();
static std::string buildPingMessage();
private:
static std::vector<std::string> divideMessage(const std::string& message);
@@ -85,6 +100,7 @@ private:
static std::string m_createProjectPrefix;
static std::string m_createCDBProjectPrefix;
static std::string m_createCDBPrefix;
static std::string m_pingPrefix;
};
#endif // NETWORK_PROTOCOL_HELPER_H
@@ -0,0 +1,23 @@
#ifndef MESSAGE_PING_RECEIVED_H
#define MESSAGE_PING_RECEIVED_H
#include "utility/messaging/Message.h"
class MessagePingReceived
: public Message<MessagePingReceived>
{
public:
MessagePingReceived()
: ideId("")
{
}
static const std::string getStaticType()
{
return "MessagePingReceived";
}
std::string ideId;
};
#endif // MESSAGE_PING_RECEIVED_H
+58
View File
@@ -1911,6 +1911,64 @@
</div>
</div>
<h2>IDE Communication Protocol</h2>
<p>Coati's IDE plugins communicate with Coati via sockets, using TCP. Coati implements a number of messages to provide an interface for the plugins.</p>
<p>This chapter explains the general structure of those messages, followed by a list of possible message types.</p>
<h3>Message Structure</h3>
<p>The basic structure of the messages used by Coati plugins consists of a prefix to identify the message type, followed by no, one, or multiple parameters and ends with an 'end-of-message' token. Parameters and tokens are seperated by a 'divider' token.</p>
<table class="table table-hover">
<thead>
<tr> <th>Name</th> <th>Token</th> <th>Description</th> </tr>
</thead>
<tbody>
<tr> <th scope="row">messageType</th> <th><a href="#MessageTypes">see below</a></th> <td>A string that determines how the message will be interpreted by Coati or the plugin</td> </tr>
<tr> <th scope="row">divider</th> <th><code>>></code></th> <td>Seperates the tokens of the message</td> </tr>
<tr> <th scope="row">parameter</th> <th><a href="#MessageTypes">see below</a></th> <td>Typically an integer or string</td> </tr>
<tr> <th scope="row">endOfMessage</th> <th><code>&lt;EOM&gt;</code></th> <td>Helps to determine the end of a message</td> </tr>
</tbody>
</table>
<p>Messages have the following form:</p>
<p><code>messageType&lt;&lt;parameter&lt;&lt;...&lt;&lt;parameter&lt;EOM&gt;</code></p>
<h3>Message Types</h3>
<p>Coati does implement a number of message types that can be used by Coati plugins. In the following is a list of the messages that Coati may send to plugins and messages that may be sent by a plugin to Coati.</p>
<p>Note that you can chose which messages you want to implement. Coati will not make problems if you chose to ignore certain messages.</p>
<strong>Incoming messages</strong>
<p>These messages may be received by a plugin.</p>
<table class="table table-hover">
<thead>
<tr> <th>Message</th> <th>Parameters</th> <th>Description</th> </tr>
</thead>
<tbody>
<tr> <th scope="row"><code>moveCursor</code></th> <th>fileLocation: string<br>row: integer<br>column: integer</th> <td>Set the cursor of your editor or IDE to the given file location.<br>Note that fileLocation is the absolute path and name of the target file.</td> </tr>
<tr> <th scope="row"><code>createCDB</code></th> <th></th> <td>Coati may send this message to prompt your plugin to create a Compilation Database (CDB). Once the CDB is ready you may want to respond with a <code>createCDBProject</code> message.</td> </tr>
<tr> <th scope="row"><code>ping</code></th> <th></th> <td>Coati may send a ping to determine if anybody is listening. Respond with a ping message yourself. Coati will not respond to this message.</td> </tr>
</tbody>
</table>
<strong>Outgoing messages</strong>
<p>Your plugin may send these messages to Coati.</p>
<table class="table table-hover">
<thead>
<tr> <th>Message</th> <th>Parameters</th> <th>Description</th> </tr>
</thead>
<tbody>
<tr> <th scope="row"><code>setActiveToken</code></th> <th>fileLocation: string<br>row: integer<br>column: integer</th> <td>Tells Coati to shift focus to the token located at the given position. Note that fileLocation is the absolute path and name of the target file.</td> </tr>
<tr> <th scope="row"><code>createCDBProject</code></th> <th>cdbPath: string<br>headerPaths: string</th> <td>If your plugin can provide a Compilation Database this message can prompt Coati to import it and display an appropriate dialog for the user. headerPaths is a list of the base project's header include paths. Seperate the single paths using the divider token. You can add as many paths as you need.</td> </tr>
<tr> <th scope="row"><code>ping</code></th> <th></th> <td>Your plugin may send this message to Coati to tell it it's listening.</td> </tr>
</tbody>
</table>
</div> <!-- .span9 !-->
</div> <!-- .row !-->
</div> <!-- .container-fluid !-->