Permalink
Browse files

Fix issue #1031. Detect if json.h is supported or not and turn off

json output for completions if it isn't.
  • Loading branch information...
Andersbakken committed Aug 22, 2017
1 parent 2f8cb12 commit 410c4e480964067cecc545bf36840c616e0cf497
Showing with 58 additions and 19 deletions.
  1. +2 −2 .travis.yml
  2. +26 −5 src/CompletionThread.cpp
  3. +17 −11 src/RClient.cpp
  4. +13 −1 src/RTags.h
View
@@ -13,15 +13,15 @@ git:
matrix:
include:
- env: COMPILER_VERSION=4.9
- env: COMPILER_VERSION=4.8
os: linux
compiler: g++
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.9
- g++-4.8
- gnupg
- env: COMPILER_VERSION=3.5
os: linux
View
@@ -24,9 +24,10 @@
#include <sstream>
#include <fstream>
#include "StringTokenizer.h"
#ifdef HAS_JSON_H
#include "rct/json/json.hpp"
using namespace nlohmann;
#endif
static uint64_t start = 0;
#define LOG() \
@@ -464,8 +465,10 @@ void CompletionThread::printCompletions(const List<std::unique_ptr<MatchResult>
bool xml = false;
bool elisp = false;
bool raw = false;
#ifdef HAS_JSON_H
bool send_json = false;
json j = {{"completions", json::array()}};
#endif
if (request->conn) {
auto output = std::make_shared<Output>();
output->connection = request->conn;
@@ -475,14 +478,16 @@ void CompletionThread::printCompletions(const List<std::unique_ptr<MatchResult>
elisp = true;
} else if (request->flags & XML) {
xml = true;
#ifdef HAS_JSON_H
} else if (request->flags & JSON) {
send_json = true;
#endif
} else {
raw = true;
}
request->conn.reset();
} else {
log([&xml, &elisp, &outputs, &raw, &send_json](const std::shared_ptr<LogOutput> &output) {
log([&](const std::shared_ptr<LogOutput> &output) {
// error() << "Got a dude" << output->testLog(RTags::DiagnosticsLevel);
if (output->testLog(RTags::DiagnosticsLevel)) {
auto out = std::make_shared<Output>();
@@ -493,9 +498,11 @@ void CompletionThread::printCompletions(const List<std::unique_ptr<MatchResult>
} else if (output->flags() & RTagsLogOutput::XML) {
out->flags |= CompletionThread::XML;
xml = true;
#ifdef HAS_JSON_H
} else if (output->flags() & RTagsLogOutput::JSON) {
out->flags |= CompletionThread::JSON;
send_json = true;
#endif
} else {
raw = true;
}
@@ -505,7 +512,10 @@ void CompletionThread::printCompletions(const List<std::unique_ptr<MatchResult>
}
if (!outputs.isEmpty()) {
String rawOut, xmlOut, jsonOut, elispOut;
String rawOut, xmlOut, elispOut;
#ifdef HAS_JSON_H
String jsonOut;
#endif
if (raw)
rawOut.reserve(16384);
if (xml) {
@@ -534,7 +544,8 @@ void CompletionThread::printCompletions(const List<std::unique_ptr<MatchResult>
rawOut += str;
if (xml)
xmlOut += str;
if (send_json)
#ifdef HAS_JSON_H
if (send_json) {
j["completions"] += {
{"completion", c->name},
{"signature", c->signature},
@@ -544,6 +555,8 @@ void CompletionThread::printCompletions(const List<std::unique_ptr<MatchResult>
{"annotation", c->annotation},
{"priority", c->priority}
};
}
#endif
if (elisp) {
elispOut += String::format<128>(" (list \"%s\" \"%s\" \"%s\" \"%s\")",
RTags::elispEscape(c->name).constData(),
@@ -560,17 +573,25 @@ void CompletionThread::printCompletions(const List<std::unique_ptr<MatchResult>
elispOut += ")))";
if (xml)
xmlOut += "]]></completions>\n";
#ifdef HAS_JSON_H
if (send_json)
jsonOut = j.dump(4);
#endif
EventLoop::mainEventLoop()->callLater([outputs, xmlOut, elispOut, rawOut, jsonOut]() {
EventLoop::mainEventLoop()->callLater([outputs, xmlOut, elispOut, rawOut
#ifdef HAS_JSON_H
, jsonOut
#endif
]() {
for (auto &it : outputs) {
if (it->flags & Elisp) {
it->send(elispOut);
} else if (it->flags & XML) {
it->send(xmlOut);
#ifdef HAS_JSON_H
} else if (it->flags & JSON) {
it->send(jsonOut);
#endif
} else {
it->send(rawOut);
}
View
@@ -187,7 +187,7 @@ class RCCommand
public:
RCCommand() {}
virtual ~RCCommand() {}
virtual bool exec(RClient *rc, const std::shared_ptr<Connection> &connection) = 0;
virtual RTags::ExitCode exec(RClient *rc, const std::shared_ptr<Connection> &connection) = 0;
virtual String description() const = 0;
};
@@ -202,8 +202,14 @@ class QueryCommand : public RCCommand
String query;
Flags<QueryMessage::Flag> extraQueryFlags;
virtual bool exec(RClient *rc, const std::shared_ptr<Connection> &connection) override
virtual RTags::ExitCode exec(RClient *rc, const std::shared_ptr<Connection> &connection) override
{
#ifndef HAS_JSON_H
if (type == QueryMessage::CodeCompleteAt && rc->queryFlags() & QueryMessage::JSON) {
fprintf(stdout, "{\"error\": \"JSON output for completions is not supported with this compiler\"}\n");
return RTags::ArgumentParseError;
}
#endif
QueryMessage msg(type);
msg.setCommandLine(rc->commandLine());
msg.setQuery(std::move(query));
@@ -220,7 +226,7 @@ class QueryCommand : public RCCommand
#ifdef RTAGS_HAS_LUA
msg.setVisitASTScripts(rc->visitASTScripts());
#endif
return connection->send(msg);
return connection->send(msg) ? RTags::Success : RTags::NetworkFailure;
}
virtual String description() const override
@@ -236,10 +242,10 @@ class QuitCommand : public RCCommand
: RCCommand(), mExitCode(exit)
{}
virtual bool exec(RClient *, const std::shared_ptr<Connection> &connection) override
virtual RTags::ExitCode exec(RClient *, const std::shared_ptr<Connection> &connection) override
{
const QuitMessage msg(mExitCode);
return connection->send(msg);
return connection->send(msg) ? RTags::Success : RTags::NetworkFailure;
}
virtual String description() const override
{
@@ -258,7 +264,7 @@ class RdmLogCommand : public RCCommand
: RCCommand(), mLevel(level)
{
}
virtual bool exec(RClient *rc, const std::shared_ptr<Connection> &connection) override
virtual RTags::ExitCode exec(RClient *rc, const std::shared_ptr<Connection> &connection) override
{
unsigned int flags = RTagsLogOutput::None;
if (rc->queryFlags() & QueryMessage::Elisp) {
@@ -274,7 +280,7 @@ class RdmLogCommand : public RCCommand
const LogLevel level = mLevel == Default ? rc->logLevel() : mLevel;
LogOutputMessage msg(level, flags);
msg.setCommandLine(rc->commandLine());
return connection->send(msg);
return connection->send(msg) ? RTags::Success : RTags::NetworkFailure;
}
virtual String description() const override
{
@@ -298,7 +304,7 @@ class CompileCommand : public RCCommand
String args;
Path cwd;
Path compileCommands;
virtual bool exec(RClient *rc, const std::shared_ptr<Connection> &connection) override
virtual RTags::ExitCode exec(RClient *rc, const std::shared_ptr<Connection> &connection) override
{
IndexMessage msg;
msg.setCommandLine(rc->commandLine());
@@ -310,7 +316,7 @@ class CompileCommand : public RCCommand
if (!rc->projectRoot().isEmpty())
msg.setProjectRoot(rc->projectRoot());
return connection->send(msg);
return connection->send(msg) ? RTags::Success : RTags::NetworkFailure;
}
virtual String description() const override
{
@@ -407,8 +413,8 @@ void RClient::exec()
for (int i=0; i<commandCount; ++i) {
const std::shared_ptr<RCCommand> &cmd = mCommands.at(i);
debug() << "running command " << cmd->description();
if (!cmd->exec(this, connection)) {
mExitCode = RTags::NetworkFailure;
mExitCode = cmd->exec(this, connection);
if (mExitCode != RTags::Success) {
break;
} else if (loop->exec(timeout()) != EventLoop::Success) {
mExitCode = RTags::TimeoutFailure;
View
@@ -16,6 +16,18 @@
#ifndef RTags_h
#define RTags_h
#if defined(__clang__)
#if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) >= 30400
#define HAS_JSON_H
#endif
#elif defined(__GNUC__)
#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40900
#define HAS_JSON_H
#endif
#else // other compiler, assume json.h is supported
#define HAS_JSON_H
#endif
#include <assert.h>
#include <ctype.h>
#include <typeinfo>
@@ -96,7 +108,7 @@ String versionString();
const LogLevel DiagnosticsLevel(-2);
const LogLevel Statistics(-3);
enum ExitCodes {
enum ExitCode {
Success = 0,
GeneralFailure = 32,
NetworkFailure = 33,

0 comments on commit 410c4e4

Please sign in to comment.