Commit a8a23793 authored by Christian Hergert's avatar Christian Hergert

clang: add api/ipc/test for getting the highlight index

parent 2855b6e8
Pipeline #9410 failed with stage
in 17 minutes and 24 seconds
......@@ -599,6 +599,72 @@ handle_complete (JsonrpcServer *server,
client_op_ref (op));
}
/* Get Highlight Index {{{1 */
static void
handle_get_highlight_index_cb (IdeClang *clang,
GAsyncResult *result,
gpointer user_data)
{
g_autoptr(ClientOp) op = user_data;
g_autoptr(IdeHighlightIndex) index = NULL;
g_autoptr(GVariant) ret = NULL;
g_autoptr(GError) error = NULL;
g_assert (IDE_IS_CLANG (clang));
g_assert (G_IS_ASYNC_RESULT (result));
g_assert (op != NULL);
if ((index = ide_clang_get_highlight_index_finish (clang, result, &error)))
ret = ide_highlight_index_to_variant (index);
if (!ret)
client_op_error (op, error);
else
client_op_reply (op, ret);
}
static void
handle_get_highlight_index (JsonrpcServer *server,
JsonrpcClient *client,
const gchar *method,
GVariant *id,
GVariant *params,
IdeClang *clang)
{
g_autoptr(GPtrArray) argv = NULL;
g_autoptr(ClientOp) op = NULL;
g_auto(GStrv) flags = NULL;
const gchar *path;
gboolean r;
g_assert (JSONRPC_IS_SERVER (server));
g_assert (JSONRPC_IS_CLIENT (client));
g_assert (g_str_equal (method, "clang/getHighlightIndex"));
g_assert (id != NULL);
g_assert (IDE_IS_CLANG (clang));
op = client_op_new (client, id);
r = JSONRPC_MESSAGE_PARSE (params,
"path", JSONRPC_MESSAGE_GET_STRING (&path),
"flags", JSONRPC_MESSAGE_GET_STRV (&flags)
);
if (!r)
{
client_op_bad_params (op);
return;
}
ide_clang_get_highlight_index_async (clang,
path,
(const gchar * const *)flags,
op->cancellable,
(GAsyncReadyCallback)handle_get_highlight_index_cb,
client_op_ref (op));
}
/* Initialize {{{1 */
static void
......@@ -696,6 +762,7 @@ main (gint argc,
ADD_HANDLER ("clang/getSymbolTree", handle_get_symbol_tree);
ADD_HANDLER ("clang/indexFile", handle_index_file);
ADD_HANDLER ("clang/locateSymbol", handle_locate_symbol);
ADD_HANDLER ("clang/getHighlightIndex", handle_get_highlight_index);
#undef ADD_HANDLER
......
......@@ -25,6 +25,11 @@
#include "ide-clang.h"
#include "ide-clang-util.h"
#define IDE_CLANG_HIGHLIGHTER_TYPE "c:type"
#define IDE_CLANG_HIGHLIGHTER_FUNCTION_NAME "def:function"
#define IDE_CLANG_HIGHLIGHTER_ENUM_NAME "def:constant"
#define IDE_CLANG_HIGHLIGHTER_MACRO_NAME "c:macro-name"
struct _IdeClang
{
GObject parent;
......@@ -1778,4 +1783,182 @@ ide_clang_get_symbol_tree_finish (IdeClang *self,
return ide_task_propagate_pointer (IDE_TASK (result), error);
}
/* Get Highlight Index {{{1 */
typedef struct
{
GFile *workdir;
gchar *path;
gchar **argv;
gint argc;
} GetHighlightIndex;
static void
get_highlight_index_free (gpointer data)
{
GetHighlightIndex *state = data;
g_clear_object (&state->workdir);
g_clear_pointer (&state->path, g_free);
g_clear_pointer (&state->argv, g_strfreev);
g_slice_free (GetHighlightIndex, state);
}
static enum CXChildVisitResult
build_index_visitor (CXCursor cursor,
CXCursor parent,
CXClientData user_data)
{
IdeHighlightIndex *highlight = user_data;
enum CXCursorKind kind;
const gchar *style_name = NULL;
g_assert (highlight != NULL);
kind = clang_getCursorKind (cursor);
switch ((int)kind)
{
case CXCursor_TypedefDecl:
case CXCursor_TypeAliasDecl:
case CXCursor_StructDecl:
case CXCursor_ClassDecl:
style_name = IDE_CLANG_HIGHLIGHTER_TYPE;
break;
case CXCursor_FunctionDecl:
style_name = IDE_CLANG_HIGHLIGHTER_FUNCTION_NAME;
break;
case CXCursor_EnumDecl:
style_name = IDE_CLANG_HIGHLIGHTER_ENUM_NAME;
clang_visitChildren (cursor, build_index_visitor, user_data);
break;
case CXCursor_EnumConstantDecl:
style_name = IDE_CLANG_HIGHLIGHTER_ENUM_NAME;
break;
case CXCursor_MacroDefinition:
style_name = IDE_CLANG_HIGHLIGHTER_MACRO_NAME;
break;
default:
break;
}
if (style_name != NULL)
{
g_auto(CXString) cxstr = {0};
const gchar *word;
cxstr = clang_getCursorSpelling (cursor);
word = clang_getCString (cxstr);
ide_highlight_index_insert (highlight, word, (gpointer)style_name);
}
return CXChildVisit_Continue;
}
static void
ide_clang_get_highlight_index_worker (IdeTask *task,
gpointer source_object,
gpointer task_data,
GCancellable *cancellable)
{
static const gchar *common_defines[] = { "NULL", "MIN", "MAX", "__LINE__", "__FILE__" };
GetHighlightIndex *state = task_data;
g_autoptr(IdeHighlightIndex) highlight = NULL;
g_auto(CXIndex) index = NULL;
g_auto(CXTranslationUnit) unit = NULL;
enum CXErrorCode code;
CXCursor cursor;
g_assert (IDE_IS_TASK (task));
g_assert (IDE_IS_CLANG (source_object));
g_assert (state != NULL);
g_assert (state->path != NULL);
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
index = clang_createIndex (0, 0);
code = clang_parseTranslationUnit2 (index,
state->path,
(const char * const *)state->argv,
state->argc,
NULL,
0,
clang_defaultEditingTranslationUnitOptions (),
&unit);
if (code != CXError_Success)
{
ide_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_FAILED,
"Failed to locate symbol at position");
return;
}
highlight = ide_highlight_index_new ();
for (guint i = 0; i < G_N_ELEMENTS (common_defines); i++)
ide_highlight_index_insert (highlight, common_defines[i], "c:common-defines");
ide_highlight_index_insert (highlight, "TRUE", "c:boolean");
ide_highlight_index_insert (highlight, "FALSE", "c:boolean");
ide_highlight_index_insert (highlight, "g_autoptr", "c:storage-class");
ide_highlight_index_insert (highlight, "g_auto", "c:storage-class");
ide_highlight_index_insert (highlight, "g_autofree", "c:storage-class");
cursor = clang_getTranslationUnitCursor (unit);
clang_visitChildren (cursor, build_index_visitor, highlight);
ide_task_return_pointer (task,
g_steal_pointer (&highlight),
(GDestroyNotify)ide_highlight_index_unref);
}
void
ide_clang_get_highlight_index_async (IdeClang *self,
const gchar *path,
const gchar * const *argv,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_autoptr(IdeTask) task = NULL;
g_autofree gchar *parent = NULL;
GetHighlightIndex *state;
g_return_if_fail (IDE_IS_CLANG (self));
g_return_if_fail (path != NULL);
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
state = g_slice_new0 (GetHighlightIndex);
state->path = g_strdup (path);
state->argv = ide_clang_cook_flags (argv);
state->argc = state->argv ? g_strv_length (state->argv) : 0;
if (self->workdir != NULL)
state->workdir = g_object_ref (self->workdir);
else
state->workdir = g_file_new_for_path ((parent = g_path_get_dirname (path)));
task = ide_task_new (self, cancellable, callback, user_data);
ide_task_set_source_tag (task, ide_clang_get_highlight_index_async);
ide_task_set_kind (task, IDE_TASK_KIND_COMPILER);
ide_task_set_task_data (task, state, get_highlight_index_free);
ide_task_run_in_thread (task, ide_clang_get_highlight_index_worker);
}
IdeHighlightIndex *
ide_clang_get_highlight_index_finish (IdeClang *self,
GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (IDE_IS_CLANG (self), NULL);
g_return_val_if_fail (IDE_IS_TASK (result), NULL);
return ide_task_propagate_pointer (IDE_TASK (result), error);
}
/* vim:set foldmethod=marker: */
......@@ -26,68 +26,77 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (IdeClang, ide_clang, IDE, CLANG, GObject)
IdeClang *ide_clang_new (void);
void ide_clang_set_workdir (IdeClang *self,
GFile *workdir);
void ide_clang_index_file_async (IdeClang *self,
const gchar *path,
const gchar * const *argv,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GPtrArray *ide_clang_index_file_finish (IdeClang *self,
GAsyncResult *result,
GError **error);
void ide_clang_complete_async (IdeClang *self,
const gchar *path,
guint line,
guint column,
const gchar * const *argv,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GVariant *ide_clang_complete_finish (IdeClang *self,
GAsyncResult *result,
GError **error);
void ide_clang_diagnose_async (IdeClang *self,
const gchar *path,
const gchar * const *argv,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GPtrArray *ide_clang_diagnose_finish (IdeClang *self,
GAsyncResult *result,
GError **error);
void ide_clang_find_nearest_scope_async (IdeClang *self,
const gchar *path,
const gchar * const *argv,
guint line,
guint column,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
IdeSymbol *ide_clang_find_nearest_scope_finish (IdeClang *self,
GAsyncResult *result,
GError **error);
void ide_clang_locate_symbol_async (IdeClang *self,
const gchar *path,
const gchar * const *argv,
guint line,
guint column,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
IdeSymbol *ide_clang_locate_symbol_finish (IdeClang *self,
GAsyncResult *result,
GError **error);
void ide_clang_get_symbol_tree_async (IdeClang *self,
const gchar *path,
const gchar * const *argv,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GVariant *ide_clang_get_symbol_tree_finish (IdeClang *self,
GAsyncResult *result,
GError **error);
IdeClang *ide_clang_new (void);
void ide_clang_set_workdir (IdeClang *self,
GFile *workdir);
void ide_clang_index_file_async (IdeClang *self,
const gchar *path,
const gchar * const *argv,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GPtrArray *ide_clang_index_file_finish (IdeClang *self,
GAsyncResult *result,
GError **error);
void ide_clang_complete_async (IdeClang *self,
const gchar *path,
guint line,
guint column,
const gchar * const *argv,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GVariant *ide_clang_complete_finish (IdeClang *self,
GAsyncResult *result,
GError **error);
void ide_clang_diagnose_async (IdeClang *self,
const gchar *path,
const gchar * const *argv,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GPtrArray *ide_clang_diagnose_finish (IdeClang *self,
GAsyncResult *result,
GError **error);
void ide_clang_find_nearest_scope_async (IdeClang *self,
const gchar *path,
const gchar * const *argv,
guint line,
guint column,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
IdeSymbol *ide_clang_find_nearest_scope_finish (IdeClang *self,
GAsyncResult *result,
GError **error);
void ide_clang_locate_symbol_async (IdeClang *self,
const gchar *path,
const gchar * const *argv,
guint line,
guint column,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
IdeSymbol *ide_clang_locate_symbol_finish (IdeClang *self,
GAsyncResult *result,
GError **error);
void ide_clang_get_symbol_tree_async (IdeClang *self,
const gchar *path,
const gchar * const *argv,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GVariant *ide_clang_get_symbol_tree_finish (IdeClang *self,
GAsyncResult *result,
GError **error);
void ide_clang_get_highlight_index_async (IdeClang *self,
const gchar *path,
const gchar * const *argv,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
IdeHighlightIndex *ide_clang_get_highlight_index_finish (IdeClang *self,
GAsyncResult *result,
GError **error);
G_END_DECLS
......@@ -22,6 +22,8 @@ static void test_index_file (JsonrpcClient *client,
GTask *task);
static void test_symtree (JsonrpcClient *client,
GTask *task);
static void test_highlight (JsonrpcClient *client,
GTask *task);
static gchar **flags;
static const gchar *path;
......@@ -34,8 +36,48 @@ static TestFunc test_funcs[] = {
test_index_file,
test_locate,
test_symtree,
test_highlight,
};
static void
test_highlight_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
JsonrpcClient *client = (JsonrpcClient *)object;
g_autoptr(GTask) task = user_data;
g_autoptr(GVariant) reply = NULL;
g_autoptr(GError) error = NULL;
g_assert (G_IS_TASK (task));
if (!jsonrpc_client_call_finish (client, result, &reply, &error))
g_error ("getHighlightIndex: %s", error->message);
g_printerr ("getHighlightIndex: %s\n", g_variant_print (reply, TRUE));
g_task_return_boolean (task, TRUE);
}
static void
test_highlight (JsonrpcClient *client,
GTask *task)
{
g_autoptr(GVariant) params = NULL;
params = JSONRPC_MESSAGE_NEW (
"path", JSONRPC_MESSAGE_PUT_STRING (path),
"flags", JSONRPC_MESSAGE_PUT_STRV ((const gchar * const *)flags)
);
jsonrpc_client_call_async (client,
"clang/getHighlightIndex",
params,
NULL,
test_highlight_cb,
g_object_ref (task));
}
static void
test_symtree_cb (GObject *object,
GAsyncResult *result,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment