clang: Add support for compile command databases
Relies on having bear (https://github.com/rizsotto/Bear). Also refactor clang code to only have 1 instance per tab.
This commit is contained in:
parent
25d5c6b7e6
commit
f89f1bb0c6
|
@ -47,6 +47,7 @@ stamp-h1
|
|||
ar-lib
|
||||
test-driver
|
||||
test-suite.log
|
||||
compile_commands.json
|
||||
|
||||
# gettext crap
|
||||
ABOUT-NLS
|
||||
|
|
28
configure.ac
28
configure.ac
|
@ -31,6 +31,19 @@ AC_ARG_ENABLE([libclang],
|
|||
],
|
||||
[want_clang="yes"])
|
||||
|
||||
# Build EAR support
|
||||
AC_ARG_ENABLE([bear],
|
||||
[AS_HELP_STRING([--disable-bear], [Disable use of BuildEAR. @<:@default=enable@:>@])],
|
||||
[
|
||||
if test "x${enableval}" = "xyes" ; then
|
||||
want_bear="yes"
|
||||
else
|
||||
want_bear="no"
|
||||
fi
|
||||
],
|
||||
[want_bear="yes"])
|
||||
|
||||
|
||||
|
||||
### Checks for programs
|
||||
|
||||
|
@ -112,6 +125,12 @@ if test "${want_clang}" = "yes"; then
|
|||
AC_CHECK_HEADERS([clang-c/Index.h], [have_clang="yes"], [have_clang="no"])
|
||||
fi
|
||||
|
||||
if test "${want_bear}" = "yes"; then
|
||||
AC_MSG_WARN([Checking...])
|
||||
AC_CHECK_PROG([have_bear], [bear], [yes])
|
||||
AC_MSG_WARN([got ${have_bear}])
|
||||
fi
|
||||
|
||||
EFL_TESTS([${build_tests}])
|
||||
|
||||
# Checks for library functions.
|
||||
|
@ -133,6 +152,14 @@ fi
|
|||
CLANG_INCLUDE=`clang -E - -v < /dev/null 2>&1 | grep "^ /usr" | grep clang`
|
||||
AC_SUBST([CLANG_INCLUDE])
|
||||
|
||||
BEAR_COMMAND=""
|
||||
if test "${have_bear}" = "no"; then
|
||||
AC_MSG_WARN([Could not find a usable bear command. Please install bear (BuildEAR) to enable better support for complex make projects.])
|
||||
else
|
||||
BEAR_COMMAND="bear"
|
||||
fi
|
||||
AC_SUBST([BEAR_COMMAND])
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
data/Makefile
|
||||
|
@ -168,6 +195,7 @@ echo " CFLAGS.................: $CFLAGS"
|
|||
echo " LDFLAGS................: $LDFLAGS"
|
||||
echo " edje_cc................: ${edje_cc}"
|
||||
echo " highlighting (libclang): ${have_clang}"
|
||||
echo " compilation db (bear)..: ${have_bear}"
|
||||
echo
|
||||
echo "eolian_gen...............: ${eolian_gen}"
|
||||
echo
|
||||
|
|
|
@ -668,15 +668,15 @@ _edi_line_status_set(Edi_Editor *editor, unsigned int number, Elm_Code_Status_Ty
|
|||
static void
|
||||
_clang_load_highlighting(const char *path, Edi_Editor *editor)
|
||||
{
|
||||
CXFile cfile = clang_getFile(editor->tx_unit, path);
|
||||
CXFile cfile = clang_getFile(editor->clang_unit, path);
|
||||
|
||||
CXSourceRange range = clang_getRange(
|
||||
clang_getLocationForOffset(editor->tx_unit, cfile, 0),
|
||||
clang_getLocationForOffset(editor->tx_unit, cfile, eina_file_size_get(eina_file_open(path, EINA_FALSE))));
|
||||
clang_getLocationForOffset(editor->clang_unit, cfile, 0),
|
||||
clang_getLocationForOffset(editor->clang_unit, cfile, ecore_file_size(path)));
|
||||
|
||||
clang_tokenize(editor->tx_unit, range, &editor->tokens, &editor->token_count);
|
||||
clang_tokenize(editor->clang_unit, range, &editor->tokens, &editor->token_count);
|
||||
editor->cursors = (CXCursor *) malloc(editor->token_count * sizeof(CXCursor));
|
||||
clang_annotateTokens(editor->tx_unit, editor->tokens, editor->token_count, editor->cursors);
|
||||
clang_annotateTokens(editor->clang_unit, editor->tokens, editor->token_count, editor->cursors);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -689,7 +689,7 @@ _clang_show_highlighting(Edi_Editor *editor)
|
|||
Edi_Range range;
|
||||
Elm_Code_Token_Type type = ELM_CODE_TOKEN_TYPE_DEFAULT;
|
||||
|
||||
CXSourceRange tkrange = clang_getTokenExtent(editor->tx_unit, editor->tokens[i]);
|
||||
CXSourceRange tkrange = clang_getTokenExtent(editor->clang_unit, editor->tokens[i]);
|
||||
clang_getSpellingLocation(clang_getRangeStart(tkrange), NULL,
|
||||
&range.start.line, &range.start.col, NULL);
|
||||
clang_getSpellingLocation(clang_getRangeEnd(tkrange), NULL,
|
||||
|
@ -742,15 +742,15 @@ static void
|
|||
_clang_free_highlighting(Edi_Editor *editor)
|
||||
{
|
||||
free(editor->cursors);
|
||||
clang_disposeTokens(editor->tx_unit, editor->tokens, editor->token_count);
|
||||
clang_disposeTokens(editor->clang_unit, editor->tokens, editor->token_count);
|
||||
}
|
||||
|
||||
static void
|
||||
_clang_load_errors(const char *path EINA_UNUSED, Edi_Editor *editor)
|
||||
_clang_load_errors(Edi_Editor *editor)
|
||||
{
|
||||
Elm_Code *code;
|
||||
const char *filename;
|
||||
unsigned n = clang_getNumDiagnostics(editor->tx_unit);
|
||||
unsigned n = clang_getNumDiagnostics(editor->clang_unit);
|
||||
unsigned i = 0;
|
||||
|
||||
ecore_thread_main_loop_begin();
|
||||
|
@ -758,9 +758,9 @@ _clang_load_errors(const char *path EINA_UNUSED, Edi_Editor *editor)
|
|||
filename = elm_code_file_path_get(code->file);
|
||||
ecore_thread_main_loop_end();
|
||||
|
||||
for(i = 0, n = clang_getNumDiagnostics(editor->tx_unit); i != n; ++i)
|
||||
for(i = 0, n = clang_getNumDiagnostics(editor->clang_unit); i != n; ++i)
|
||||
{
|
||||
CXDiagnostic diag = clang_getDiagnostic(editor->tx_unit, i);
|
||||
CXDiagnostic diag = clang_getDiagnostic(editor->clang_unit, i);
|
||||
CXFile file;
|
||||
unsigned int line;
|
||||
CXString path;
|
||||
|
@ -809,9 +809,7 @@ _edi_clang_setup(void *data, Ecore_Thread *thread EINA_UNUSED)
|
|||
{
|
||||
Edi_Editor *editor;
|
||||
Elm_Code *code;
|
||||
const char *path, *args;
|
||||
char **clang_argv;
|
||||
unsigned int clang_argc;
|
||||
const char *path;
|
||||
|
||||
ecore_thread_main_loop_begin();
|
||||
|
||||
|
@ -821,18 +819,7 @@ _edi_clang_setup(void *data, Ecore_Thread *thread EINA_UNUSED)
|
|||
|
||||
ecore_thread_main_loop_end();
|
||||
|
||||
/* Clang */
|
||||
/* FIXME: index should probably be global. */
|
||||
args = "-I/usr/inclue/ " EFL_CFLAGS " " CLANG_INCLUDES " -Wall -Wextra";
|
||||
clang_argv = eina_str_split_full(args, " ", 0, &clang_argc);
|
||||
|
||||
editor->idx = clang_createIndex(0, 0);
|
||||
|
||||
/* FIXME: Possibly activate more options? */
|
||||
editor->tx_unit = clang_parseTranslationUnit(editor->idx, path, (const char *const *)clang_argv, (int)clang_argc, NULL, 0,
|
||||
clang_defaultEditingTranslationUnitOptions() | CXTranslationUnit_DetailedPreprocessingRecord);
|
||||
|
||||
_clang_load_errors(path, editor);
|
||||
_clang_load_errors(editor);
|
||||
_clang_load_highlighting(path, editor);
|
||||
_clang_show_highlighting(editor);
|
||||
}
|
||||
|
@ -843,8 +830,6 @@ _edi_clang_dispose(void *data, Ecore_Thread *thread EINA_UNUSED)
|
|||
Edi_Editor *editor = (Edi_Editor *)data;
|
||||
|
||||
_clang_free_highlighting(editor);
|
||||
clang_disposeTranslationUnit(editor->tx_unit);
|
||||
clang_disposeIndex(editor->idx);
|
||||
|
||||
editor->highlight_thread = NULL;
|
||||
editor->highlight_cancel = EINA_FALSE;
|
||||
|
|
|
@ -51,14 +51,11 @@ struct _Edi_Editor
|
|||
|
||||
#if HAVE_LIBCLANG
|
||||
/* Clang */
|
||||
CXIndex idx;
|
||||
CXTranslationUnit tx_unit;
|
||||
CXIndex clang_idx;
|
||||
CXTranslationUnit clang_unit;
|
||||
CXToken *tokens;
|
||||
CXCursor *cursors;
|
||||
unsigned int token_count;
|
||||
|
||||
CXIndex as_idx;
|
||||
CXTranslationUnit as_unit;
|
||||
#endif
|
||||
|
||||
Ecore_Thread *highlight_thread;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#if HAVE_LIBCLANG
|
||||
#include <clang-c/Index.h>
|
||||
#include <clang-c/CXCompilationDatabase.h>
|
||||
#endif
|
||||
|
||||
#include <Eina.h>
|
||||
|
@ -16,35 +17,92 @@
|
|||
#include "edi_private.h"
|
||||
|
||||
#if HAVE_LIBCLANG
|
||||
|
||||
static void
|
||||
_clang_commands_fallback_get(const char ***args, unsigned int *argc)
|
||||
{
|
||||
const char *argstr;
|
||||
|
||||
argstr = "-I/usr/include/ " EFL_CFLAGS " " CLANG_INCLUDES " -Wall -Wextra";
|
||||
*args = (const char **) eina_str_split_full(argstr, " ", 0, argc);
|
||||
}
|
||||
|
||||
static void
|
||||
_clang_commands_get(const char *path, const char ***args, unsigned int *argc)
|
||||
{
|
||||
CXCompilationDatabase_Error compilationDatabaseError;
|
||||
CXCompilationDatabase compilationDatabase = clang_CompilationDatabase_fromDirectory(edi_project_get(), &compilationDatabaseError );
|
||||
|
||||
if ( compilationDatabaseError == CXCompilationDatabase_CanNotLoadDatabase)
|
||||
{
|
||||
INF("Could not load compile_commands.json in %s", edi_project_get());
|
||||
_clang_commands_fallback_get(args, argc);
|
||||
return;
|
||||
}
|
||||
|
||||
CXCompileCommands compileCommands = clang_CompilationDatabase_getCompileCommands( compilationDatabase, path);
|
||||
CXCompileCommand compileCommand = clang_CompileCommands_getCommand( compileCommands, 0 );
|
||||
unsigned int numArguments = clang_CompileCommand_getNumArgs( compileCommand );
|
||||
|
||||
if (numArguments == 0)
|
||||
{
|
||||
INF("File %s not found in compile_commands.json", path);
|
||||
_clang_commands_fallback_get(args, argc);
|
||||
return;
|
||||
}
|
||||
|
||||
const char** arguments = malloc(sizeof(char*) * numArguments);
|
||||
|
||||
arguments[0] = CLANG_INCLUDES;
|
||||
for( unsigned int i = 1; numArguments > i + 4; i++ )
|
||||
{
|
||||
CXString argument = clang_CompileCommand_getArg( compileCommand, i + 1 );
|
||||
const char * strArgument = clang_getCString( argument );
|
||||
|
||||
arguments[i] = strdup(strArgument);
|
||||
|
||||
clang_disposeString( argument );
|
||||
}
|
||||
|
||||
*args = arguments;
|
||||
*argc = numArguments <= 4 ? 1 : numArguments - 4;
|
||||
|
||||
clang_CompilationDatabase_dispose(compilationDatabase);
|
||||
}
|
||||
|
||||
static void
|
||||
_clang_autosuggest_setup(Edi_Editor *editor)
|
||||
{
|
||||
Elm_Code *code;
|
||||
const char *path;
|
||||
char **clang_argv;
|
||||
const char *args;
|
||||
unsigned int clang_argc;
|
||||
const char **args;
|
||||
unsigned int argc, end_row, end_col;
|
||||
struct CXUnsavedFile unsaved_file;
|
||||
|
||||
code = elm_code_widget_code_get(editor->entry);
|
||||
path = elm_code_file_path_get(code->file);
|
||||
|
||||
end_row = elm_code_file_lines_get(code->file);
|
||||
end_col = elm_code_file_line_get(code->file, end_row)->length;
|
||||
|
||||
unsaved_file.Filename = path;
|
||||
unsaved_file.Contents = elm_code_widget_text_between_positions_get(
|
||||
editor->entry, 1, 1, end_row, end_col);
|
||||
unsaved_file.Length = strlen(unsaved_file.Contents);
|
||||
|
||||
//Initialize Clang
|
||||
args = "-I/usr/inclue/ " EFL_CFLAGS " " CLANG_INCLUDES " -Wall -Wextra";
|
||||
clang_argv = eina_str_split_full(args, " ", 0, &clang_argc);
|
||||
|
||||
editor->as_idx = clang_createIndex(0, 0);
|
||||
|
||||
editor->as_unit = clang_parseTranslationUnit(editor->as_idx, path,
|
||||
(const char *const *)clang_argv,
|
||||
(int)clang_argc, NULL, 0,
|
||||
clang_defaultEditingTranslationUnitOptions());
|
||||
_clang_commands_get(path, &args, &argc);
|
||||
editor->clang_idx = clang_createIndex(0, 0);
|
||||
editor->clang_unit = clang_parseTranslationUnit(editor->clang_idx, path,
|
||||
args, argc, NULL, 0, //&unsaved_file, 1,
|
||||
clang_defaultEditingTranslationUnitOptions() | CXTranslationUnit_DetailedPreprocessingRecord);
|
||||
}
|
||||
|
||||
static void
|
||||
_clang_autosuggest_dispose(Edi_Editor *editor)
|
||||
{
|
||||
clang_disposeTranslationUnit(editor->as_unit);
|
||||
clang_disposeIndex(editor->as_idx);
|
||||
clang_disposeTranslationUnit(editor->clang_unit);
|
||||
clang_disposeIndex(editor->clang_idx);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -112,7 +170,7 @@ _edi_language_c_lookup(Edi_Editor *editor, unsigned int row, unsigned int col)
|
|||
Elm_Code *code;
|
||||
const char *path = NULL;
|
||||
|
||||
if (!editor->as_unit)
|
||||
if (!editor->clang_unit)
|
||||
return list;
|
||||
|
||||
code = elm_code_widget_code_get(editor->entry);
|
||||
|
@ -124,7 +182,7 @@ _edi_language_c_lookup(Edi_Editor *editor, unsigned int row, unsigned int col)
|
|||
editor->entry, 1, 1, row, col);
|
||||
unsaved_file.Length = strlen(unsaved_file.Contents);
|
||||
|
||||
res = clang_codeCompleteAt(editor->as_unit, path, row, col,
|
||||
res = clang_codeCompleteAt(editor->clang_unit, path, row, col,
|
||||
&unsaved_file, 1,
|
||||
CXCodeComplete_IncludeMacros |
|
||||
CXCodeComplete_IncludeCodePatterns);
|
||||
|
@ -357,42 +415,20 @@ _edi_doc_dump(Edi_Language_Document *doc, CXComment comment, Eina_Strbuf *strbuf
|
|||
}
|
||||
|
||||
static CXCursor
|
||||
_edi_doc_cursor_get(Edi_Editor *editor, CXIndex idx, CXTranslationUnit unit,
|
||||
unsigned int row, unsigned int col)
|
||||
_edi_doc_cursor_get(Edi_Editor *editor, unsigned int row, unsigned int col)
|
||||
{
|
||||
CXFile cxfile;
|
||||
CXSourceLocation location;
|
||||
CXCursor cursor;
|
||||
struct CXUnsavedFile unsaved_file;
|
||||
Elm_Code *code;
|
||||
const char *path, *args;
|
||||
char **clang_argv;
|
||||
unsigned int clang_argc, end_row, end_col;
|
||||
const char *path;
|
||||
|
||||
code = elm_code_widget_code_get(editor->entry);
|
||||
path = elm_code_file_path_get(code->file);
|
||||
|
||||
end_row = elm_code_file_lines_get(code->file);
|
||||
end_col = elm_code_file_line_get(code->file, end_row)->length;
|
||||
|
||||
unsaved_file.Filename = path;
|
||||
unsaved_file.Contents = elm_code_widget_text_between_positions_get(
|
||||
editor->entry, 1, 1, end_row, end_col);
|
||||
unsaved_file.Length = strlen(unsaved_file.Contents);
|
||||
|
||||
//Initialize Clang
|
||||
args = "-I/usr/inclue/ " EFL_CFLAGS " " CLANG_INCLUDES " -Wall -Wextra";
|
||||
clang_argv = eina_str_split_full(args, " ", 0, &clang_argc);
|
||||
|
||||
idx = clang_createIndex(0, 0);
|
||||
|
||||
unit = clang_parseTranslationUnit(idx, path, (const char *const *)clang_argv,
|
||||
(int)clang_argc, &unsaved_file, 1,
|
||||
clang_defaultEditingTranslationUnitOptions());
|
||||
|
||||
cxfile = clang_getFile(unit, path);
|
||||
location = clang_getLocation(unit, cxfile, row, col);
|
||||
cursor = clang_getCursor(unit, location);
|
||||
cxfile = clang_getFile(editor->clang_unit, path);
|
||||
location = clang_getLocation(editor->clang_unit, cxfile, row, col);
|
||||
cursor = clang_getCursor(editor->clang_unit, location);
|
||||
|
||||
return clang_getCursorReferenced(cursor);
|
||||
}
|
||||
|
@ -403,18 +439,14 @@ _edi_language_c_lookup_doc(Edi_Editor *editor, unsigned int row, unsigned int co
|
|||
{
|
||||
Edi_Language_Document *doc = NULL;
|
||||
#if HAVE_LIBCLANG
|
||||
CXIndex idx = NULL;
|
||||
CXTranslationUnit unit = NULL;
|
||||
CXCursor cursor;
|
||||
CXComment comment;
|
||||
|
||||
cursor = _edi_doc_cursor_get(editor, idx, unit, row, col);
|
||||
cursor = _edi_doc_cursor_get(editor, row, col);
|
||||
comment = clang_Cursor_getParsedComment(cursor);
|
||||
|
||||
if (clang_Comment_getKind(comment) == CXComment_Null)
|
||||
{
|
||||
clang_disposeTranslationUnit(unit);
|
||||
clang_disposeIndex(idx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -424,9 +456,6 @@ _edi_language_c_lookup_doc(Edi_Editor *editor, unsigned int row, unsigned int co
|
|||
_edi_doc_dump(doc, comment, doc->detail);
|
||||
_edi_doc_title_get(cursor, doc->title);
|
||||
_edi_doc_trim(doc->detail);
|
||||
|
||||
clang_disposeTranslationUnit(unit);
|
||||
clang_disposeIndex(idx);
|
||||
#endif
|
||||
return doc;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,8 @@ AM_CPPFLAGS = \
|
|||
-DPACKAGE_LIB_DIR=\"$(libdir)\" \
|
||||
-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
|
||||
@EFL_CFLAGS@ \
|
||||
-DEFL_EDI_BUILD
|
||||
-DEFL_EDI_BUILD \
|
||||
-DBEAR_COMMAND=\"$(BEAR_COMMAND)\"
|
||||
|
||||
lib_LTLIBRARIES = libedi.la
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ static void
|
|||
_make_build_make(void)
|
||||
{
|
||||
chdir(edi_project_get());
|
||||
ecore_exe_pipe_run("make", ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
|
||||
ecore_exe_pipe_run(BEAR_COMMAND " make", ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
|
||||
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
|
||||
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ static void
|
|||
_make_build_configure(void)
|
||||
{
|
||||
chdir(edi_project_get());
|
||||
ecore_exe_pipe_run("./configure && make",
|
||||
ecore_exe_pipe_run("./configure && " BEAR_COMMAND " make",
|
||||
ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
|
||||
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
|
||||
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
|
||||
|
@ -70,7 +70,7 @@ static void
|
|||
_make_build_cmake(void)
|
||||
{
|
||||
chdir(edi_project_get());
|
||||
ecore_exe_pipe_run("mkdir -p build && cd build && cmake .. && make && cd ..",
|
||||
ecore_exe_pipe_run("mkdir -p build && cd build && cmake .. && " BEAR_COMMAND " make && cd ..",
|
||||
ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
|
||||
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
|
||||
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
|
||||
|
@ -80,7 +80,7 @@ static void
|
|||
_make_build_autogen(void)
|
||||
{
|
||||
chdir(edi_project_get());
|
||||
ecore_exe_pipe_run("./autogen.sh && make",
|
||||
ecore_exe_pipe_run("./autogen.sh && " BEAR_COMMAND " make",
|
||||
ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
|
||||
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
|
||||
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
|
||||
|
|
Loading…
Reference in New Issue