mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-25 00:55:08 +00:00
wip
This commit is contained in:
commit
5dbde940b6
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
.vs
|
||||
Debug
|
||||
x64
|
||||
*.swp
|
||||
*.sln
|
||||
*.vcxproj
|
||||
*.vcxproj.filters
|
54
libclangmm/CMakeLists.txt
Normal file
54
libclangmm/CMakeLists.txt
Normal file
@ -0,0 +1,54 @@
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O3 -Wall -Wextra -Wno-unused-parameter -Wno-reorder")
|
||||
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_HOME_DIRECTORY}/cmake/Modules/")
|
||||
|
||||
message("Searcing for libclang")
|
||||
#LIBCLANG_FOUND System has libclang.
|
||||
#LIBCLANG_INCLUDE_DIRS The libclang include directories.
|
||||
#LIBCLANG_LIBRARIES The libraries needed to use libclang.
|
||||
#LIBCLANG_LIBRARY_DIR The path to the directory containing libclang.
|
||||
#LIBCLANG_KNOWN_LLVM_VERSIONS Known LLVM release numbers.
|
||||
find_package(LibClang REQUIRED)
|
||||
|
||||
set(header_files
|
||||
clangmm.h
|
||||
CodeCompleteResults.h
|
||||
CompilationDatabase.h
|
||||
CompileCommand.h
|
||||
CompileCommands.h
|
||||
CompletionString.h
|
||||
Cursor.h
|
||||
Index.h
|
||||
SourceLocation.h
|
||||
SourceRange.h
|
||||
Token.h
|
||||
Tokens.h
|
||||
TranslationUnit.h
|
||||
Diagnostic.h
|
||||
Utility.h
|
||||
)
|
||||
set(cc_files
|
||||
CodeCompleteResults.cc
|
||||
CompilationDatabase.cc
|
||||
CompileCommand.cc
|
||||
CompileCommands.cc
|
||||
CompletionString.cc
|
||||
Cursor.cc
|
||||
Index.cc
|
||||
SourceLocation.cc
|
||||
SourceRange.cc
|
||||
Token.cc
|
||||
Tokens.cc
|
||||
TranslationUnit.cc
|
||||
Diagnostic.cc
|
||||
Utility.cc
|
||||
)
|
||||
|
||||
add_library(${project_name} SHARED ${header_files} ${cc_files})
|
||||
|
||||
include_directories(${LIBCLANG_INCLUDE_DIRS})
|
||||
target_link_libraries(${project_name} ${LIBCLANG_LIBRARIES})
|
||||
|
||||
install(TARGETS ${project_name} RUNTIME DESTINATION bin LIBRARY DESTINATION lib)
|
||||
install(FILES ${header_files} DESTINATION include/libclangmm)
|
45
libclangmm/CodeCompleteResults.cc
Normal file
45
libclangmm/CodeCompleteResults.cc
Normal file
@ -0,0 +1,45 @@
|
||||
#include "CodeCompleteResults.h"
|
||||
#include "CompletionString.h"
|
||||
#include <exception>
|
||||
#include "Utility.h"
|
||||
|
||||
clang::CodeCompleteResults::CodeCompleteResults(CXTranslationUnit &cx_tu,
|
||||
const std::string &buffer,
|
||||
unsigned line_num, unsigned column) {
|
||||
CXUnsavedFile files[1];
|
||||
auto file_path=to_string(clang_getTranslationUnitSpelling(cx_tu));
|
||||
files[0].Filename = file_path.c_str();
|
||||
files[0].Contents = buffer.c_str();
|
||||
files[0].Length = buffer.size();
|
||||
|
||||
cx_results = clang_codeCompleteAt(cx_tu,
|
||||
file_path.c_str(),
|
||||
line_num,
|
||||
column,
|
||||
files,
|
||||
1,
|
||||
clang_defaultCodeCompleteOptions()|CXCodeComplete_IncludeBriefComments);
|
||||
if(cx_results!=nullptr)
|
||||
clang_sortCodeCompletionResults(cx_results->Results, cx_results->NumResults);
|
||||
}
|
||||
|
||||
clang::CodeCompleteResults::~CodeCompleteResults() {
|
||||
clang_disposeCodeCompleteResults(cx_results);
|
||||
}
|
||||
|
||||
unsigned clang::CodeCompleteResults::size() const {
|
||||
if(cx_results==nullptr)
|
||||
return 0;
|
||||
return cx_results->NumResults;
|
||||
}
|
||||
|
||||
clang::CompletionString clang::CodeCompleteResults::get(unsigned i) const {
|
||||
if (i >= size()) {
|
||||
throw std::invalid_argument("clang::CodeCompleteResults::get(unsigned i): i>=size()");
|
||||
}
|
||||
return CompletionString(cx_results->Results[i].CompletionString);
|
||||
}
|
||||
|
||||
std::string clang::CodeCompleteResults::get_usr() const {
|
||||
return to_string(clang_codeCompleteGetContainerUSR(cx_results));
|
||||
}
|
23
libclangmm/CodeCompleteResults.h
Normal file
23
libclangmm/CodeCompleteResults.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef CODECOMPLETERESULTS_H_
|
||||
#define CODECOMPLETERESULTS_H_
|
||||
#include <clang-c/Index.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "CompletionString.h"
|
||||
|
||||
namespace clang {
|
||||
class CodeCompleteResults {
|
||||
friend class TranslationUnit;
|
||||
|
||||
CodeCompleteResults(CXTranslationUnit &cx_tu, const std::string &buffer,
|
||||
unsigned line_num, unsigned column);
|
||||
public:
|
||||
~CodeCompleteResults();
|
||||
CompletionString get(unsigned index) const;
|
||||
unsigned size() const;
|
||||
std::string get_usr() const;
|
||||
|
||||
CXCodeCompleteResults *cx_results;
|
||||
};
|
||||
} // namespace clang
|
||||
#endif // CODECOMPLETERESULTS_H_
|
14
libclangmm/CompilationDatabase.cc
Normal file
14
libclangmm/CompilationDatabase.cc
Normal file
@ -0,0 +1,14 @@
|
||||
#include "CompilationDatabase.h"
|
||||
#include <exception>
|
||||
|
||||
clang::CompilationDatabase::CompilationDatabase(const std::string &project_path) {
|
||||
CXCompilationDatabase_Error error;
|
||||
cx_db = clang_CompilationDatabase_fromDirectory(project_path.c_str(), &error);
|
||||
if(error) {
|
||||
//TODO: compile_commands.json is missing, create it?
|
||||
}
|
||||
}
|
||||
|
||||
clang::CompilationDatabase::~CompilationDatabase() {
|
||||
clang_CompilationDatabase_dispose(cx_db);
|
||||
}
|
18
libclangmm/CompilationDatabase.h
Normal file
18
libclangmm/CompilationDatabase.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef COMPILATIONDATABASE_H_
|
||||
#define COMPILATIONDATABASE_H_
|
||||
|
||||
#include <clang-c/CXCompilationDatabase.h>
|
||||
#include <clang-c/Index.h>
|
||||
#include <string>
|
||||
|
||||
namespace clang {
|
||||
class CompilationDatabase {
|
||||
public:
|
||||
explicit CompilationDatabase(const std::string &project_path);
|
||||
~CompilationDatabase();
|
||||
|
||||
CXCompilationDatabase cx_db;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // COMPILATIONDATABASE_H_
|
21
libclangmm/CompileCommand.cc
Normal file
21
libclangmm/CompileCommand.cc
Normal file
@ -0,0 +1,21 @@
|
||||
#include "CompileCommand.h"
|
||||
#include "CompileCommands.h"
|
||||
#include "Utility.h"
|
||||
|
||||
std::string clang::CompileCommand::get_command() {
|
||||
std::string res;
|
||||
unsigned N = clang_CompileCommand_getNumArgs(cx_command);
|
||||
for (unsigned i = 0; i < N; i++) {
|
||||
res += to_string(clang_CompileCommand_getArg(cx_command, i));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<std::string> clang::CompileCommand::get_command_as_args() {
|
||||
unsigned N = clang_CompileCommand_getNumArgs(cx_command);
|
||||
std::vector<std::string> res(N);
|
||||
for (unsigned i = 0; i < N; i++) {
|
||||
res[i] = to_string(clang_CompileCommand_getArg(cx_command, i));
|
||||
}
|
||||
return res;
|
||||
}
|
17
libclangmm/CompileCommand.h
Normal file
17
libclangmm/CompileCommand.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef COMPILECOMMAND_H_
|
||||
#define COMPILECOMMAND_H_
|
||||
#include <clang-c/CXCompilationDatabase.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace clang {
|
||||
class CompileCommand {
|
||||
public:
|
||||
CompileCommand(const CXCompileCommand& cx_command) : cx_command(cx_command) {};
|
||||
std::string get_command();
|
||||
std::vector<std::string> get_command_as_args();
|
||||
|
||||
CXCompileCommand cx_command;
|
||||
};
|
||||
}
|
||||
#endif // COMPILECOMMAND_H_
|
21
libclangmm/CompileCommands.cc
Normal file
21
libclangmm/CompileCommands.cc
Normal file
@ -0,0 +1,21 @@
|
||||
#include "CompileCommands.h"
|
||||
|
||||
clang::CompileCommands::CompileCommands(const std::string &filename, CompilationDatabase &db) {
|
||||
cx_commands =
|
||||
clang_CompilationDatabase_getCompileCommands(db.cx_db, filename.c_str());
|
||||
if(clang_CompileCommands_getSize(cx_commands)==0)
|
||||
cx_commands = clang_CompilationDatabase_getAllCompileCommands(db.cx_db);
|
||||
}
|
||||
|
||||
clang::CompileCommands::~CompileCommands() {
|
||||
clang_CompileCommands_dispose(cx_commands);
|
||||
}
|
||||
|
||||
std::vector<clang::CompileCommand> clang::CompileCommands::get_commands() {
|
||||
unsigned N = clang_CompileCommands_getSize(cx_commands);
|
||||
std::vector<CompileCommand> res;
|
||||
for (unsigned i = 0; i < N; i++) {
|
||||
res.emplace_back(clang_CompileCommands_getCommand(cx_commands, i));
|
||||
}
|
||||
return res;
|
||||
}
|
19
libclangmm/CompileCommands.h
Normal file
19
libclangmm/CompileCommands.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef COMPILECOMMANDS_H_
|
||||
#define COMPILECOMMANDS_H_
|
||||
#include "CompilationDatabase.h"
|
||||
#include "CompileCommand.h"
|
||||
#include <clang-c/CXCompilationDatabase.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
class CompileCommands {
|
||||
public:
|
||||
CompileCommands(const std::string &filename, CompilationDatabase &db);
|
||||
std::vector<CompileCommand> get_commands();
|
||||
~CompileCommands();
|
||||
|
||||
CXCompileCommands cx_commands;
|
||||
};
|
||||
}
|
||||
#endif // COMPILECOMMANDS_H_
|
28
libclangmm/CompletionString.cc
Normal file
28
libclangmm/CompletionString.cc
Normal file
@ -0,0 +1,28 @@
|
||||
#include "CompletionString.h"
|
||||
#include "Utility.h"
|
||||
|
||||
clang::CompletionString::
|
||||
CompletionString(const CXCompletionString &cx_completion_sting) : cx_completion_sting(cx_completion_sting) {}
|
||||
|
||||
bool clang::CompletionString::available() {
|
||||
return clang_getCompletionAvailability(cx_completion_sting) == CXAvailability_Available;
|
||||
}
|
||||
|
||||
unsigned clang::CompletionString::get_num_chunks() {
|
||||
return clang_getNumCompletionChunks(cx_completion_sting);
|
||||
}
|
||||
|
||||
std::vector<clang::CompletionChunk> clang::CompletionString::get_chunks() {
|
||||
std::vector<CompletionChunk> res;
|
||||
for (unsigned i = 0; i < get_num_chunks(); i++) {
|
||||
res.emplace_back(to_string(clang_getCompletionChunkText(cx_completion_sting, i)), static_cast<CompletionChunkKind> (clang_getCompletionChunkKind(cx_completion_sting, i)));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string clang::CompletionString::get_brief_comments() {
|
||||
return to_string(clang_getCompletionBriefComment(cx_completion_sting));
|
||||
}
|
||||
|
||||
clang::CompletionChunk::CompletionChunk(std::string chunk, CompletionChunkKind kind) :
|
||||
chunk(chunk), kind(kind) { }
|
40
libclangmm/CompletionString.h
Normal file
40
libclangmm/CompletionString.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef COMPLETIONSTRING_H_
|
||||
#define COMPLETIONSTRING_H_
|
||||
#include <clang-c/Index.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
enum CompletionChunkKind {
|
||||
CompletionChunk_Optional, CompletionChunk_TypedText,
|
||||
CompletionChunk_Text, CompletionChunk_Placeholder,
|
||||
CompletionChunk_Informative, CompletionChunk_CurrentParameter,
|
||||
CompletionChunk_LeftParen, CompletionChunk_RightParen,
|
||||
CompletionChunk_LeftBracket, CompletionChunk_RightBracket,
|
||||
CompletionChunk_LeftBrace, CompletionChunk_RightBrace,
|
||||
CompletionChunk_LeftAngle, CompletionChunk_RightAngle,
|
||||
CompletionChunk_Comma, CompletionChunk_ResultType,
|
||||
CompletionChunk_Colon, CompletionChunk_SemiColon,
|
||||
CompletionChunk_Equal, CompletionChunk_HorizontalSpace,
|
||||
CompletionChunk_VerticalSpace
|
||||
};
|
||||
|
||||
class CompletionChunk {
|
||||
public:
|
||||
CompletionChunk(std::string chunk, CompletionChunkKind kind);
|
||||
std::string chunk;
|
||||
CompletionChunkKind kind;
|
||||
};
|
||||
|
||||
class CompletionString {
|
||||
public:
|
||||
explicit CompletionString(const CXCompletionString &cx_completion_sting);
|
||||
bool available();
|
||||
std::vector<CompletionChunk> get_chunks();
|
||||
std::string get_brief_comments();
|
||||
unsigned get_num_chunks();
|
||||
|
||||
CXCompletionString cx_completion_sting;
|
||||
};
|
||||
} // namespace clang
|
||||
#endif // COMPLETIONSTRING_H_
|
138
libclangmm/Cursor.cc
Normal file
138
libclangmm/Cursor.cc
Normal file
@ -0,0 +1,138 @@
|
||||
#include "Cursor.h"
|
||||
#include "Utility.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace clang {
|
||||
|
||||
std::string Cursor::Type::get_spelling() const {
|
||||
return to_string(clang_getTypeSpelling(cx_type));
|
||||
}
|
||||
|
||||
Cursor::Type Cursor::Type::get_result() const {
|
||||
return Type(clang_getResultType(cx_type));
|
||||
}
|
||||
|
||||
Cursor::Cursor() = default;
|
||||
|
||||
Cursor::Cursor(const CXCursor& other) : cx_cursor(cx_cursor) {}
|
||||
|
||||
bool Cursor::Type::operator==(const Cursor::Type& rhs) const {
|
||||
return clang_equalTypes(cx_type, rhs.cx_type);
|
||||
}
|
||||
|
||||
CXCursorKind Cursor::get_kind() const {
|
||||
return clang_getCursorKind(cx_cursor);
|
||||
}
|
||||
|
||||
Cursor::Type Cursor::get_type() const {
|
||||
return Type(clang_getCursorType(cx_cursor));
|
||||
}
|
||||
|
||||
SourceLocation Cursor::get_source_location() const {
|
||||
return SourceLocation(clang_getCursorLocation(cx_cursor));
|
||||
}
|
||||
|
||||
SourceRange Cursor::get_source_range() const {
|
||||
return SourceRange(clang_getCursorExtent(cx_cursor));
|
||||
}
|
||||
|
||||
std::string Cursor::get_spelling() const {
|
||||
return to_string(clang_getCursorSpelling(cx_cursor));
|
||||
}
|
||||
|
||||
std::string Cursor::get_display_name() const {
|
||||
return to_string(clang_getCursorDisplayName(cx_cursor));
|
||||
}
|
||||
|
||||
std::string Cursor::get_usr() const {
|
||||
return to_string(clang_getCursorUSR(cx_cursor));
|
||||
}
|
||||
|
||||
Cursor Cursor::get_referenced() const {
|
||||
return Cursor(clang_getCursorReferenced(cx_cursor));
|
||||
}
|
||||
|
||||
Cursor Cursor::get_canonical() const {
|
||||
return Cursor(clang_getCanonicalCursor(cx_cursor));
|
||||
}
|
||||
|
||||
Cursor Cursor::get_definition() const {
|
||||
return Cursor(clang_getCursorDefinition(cx_cursor));
|
||||
}
|
||||
|
||||
Cursor Cursor::get_semantic_parent() const {
|
||||
return Cursor(clang_getCursorSemanticParent(cx_cursor));
|
||||
}
|
||||
|
||||
std::vector<Cursor> Cursor::get_arguments() const {
|
||||
auto size = clang_Cursor_getNumArguments(cx_cursor);
|
||||
std::vector<Cursor> cursors(size);
|
||||
for (int c = 0; c < size; ++c)
|
||||
cursors.emplace_back(clang_Cursor_getArgument(cx_cursor, c));
|
||||
return cursors;
|
||||
}
|
||||
|
||||
Cursor::operator bool() const {
|
||||
return !clang_Cursor_isNull(cx_cursor);
|
||||
}
|
||||
|
||||
bool Cursor::operator==(const Cursor& rhs) const {
|
||||
return clang_equalCursors(cx_cursor, rhs.cx_cursor);
|
||||
}
|
||||
|
||||
bool Cursor::is_valid_kind() const {
|
||||
CXCursor referenced = clang_getCursorReferenced(cx_cursor);
|
||||
if (clang_Cursor_isNull(referenced))
|
||||
return false;
|
||||
|
||||
CXCursorKind kind = get_kind();
|
||||
return kind > CXCursor_UnexposedDecl &&
|
||||
(kind < CXCursor_FirstInvalid || kind > CXCursor_LastInvalid);
|
||||
}
|
||||
|
||||
std::string Cursor::get_type_description() const {
|
||||
std::string spelling;
|
||||
|
||||
auto referenced = clang_getCursorReferenced(cx_cursor);
|
||||
if (!clang_Cursor_isNull(referenced)) {
|
||||
auto type = clang_getCursorType(referenced);
|
||||
spelling = to_string(clang_getTypeSpelling(type));
|
||||
|
||||
#if CINDEX_VERSION_MAJOR==0 && CINDEX_VERSION_MINOR<32
|
||||
const std::string auto_str = "auto";
|
||||
if (spelling.size() >= 4 && std::equal(auto_str.begin(), auto_str.end(), spelling.begin())) {
|
||||
auto canonical_type = clang_getCanonicalType(clang_getCursorType(cx_cursor));
|
||||
auto canonical_spelling = to_string(clang_getTypeSpelling(canonical_type));
|
||||
if (spelling.size() > 5 && spelling[4] == ' ' && spelling[5] == '&' && spelling != canonical_spelling)
|
||||
return canonical_spelling + " &";
|
||||
else
|
||||
return canonical_spelling;
|
||||
}
|
||||
|
||||
const std::string const_auto_str = "const auto";
|
||||
if (spelling.size() >= 10 && std::equal(const_auto_str.begin(), const_auto_str.end(), spelling.begin())) {
|
||||
auto canonical_type = clang_getCanonicalType(clang_getCursorType(cx_cursor));
|
||||
auto canonical_spelling = to_string(clang_getTypeSpelling(canonical_type));
|
||||
if (spelling.size() > 11 && spelling[10] == ' ' && spelling[11] == '&' && spelling != canonical_spelling)
|
||||
return canonical_spelling + " &";
|
||||
else
|
||||
return canonical_spelling;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (spelling.empty())
|
||||
return get_spelling();
|
||||
|
||||
return spelling;
|
||||
}
|
||||
|
||||
std::string Cursor::get_brief_comments() const {
|
||||
Cursor referenced = get_referenced();
|
||||
if (referenced)
|
||||
return to_string(clang_Cursor_getBriefCommentText(referenced.cx_cursor));
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace clang
|
51
libclangmm/Cursor.h
Normal file
51
libclangmm/Cursor.h
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef CURSOR_H_
|
||||
#define CURSOR_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <clang-c/Index.h>
|
||||
|
||||
#include "SourceLocation.h"
|
||||
#include "SourceRange.h"
|
||||
|
||||
|
||||
namespace clang {
|
||||
class Cursor {
|
||||
public:
|
||||
|
||||
class Type {
|
||||
public:
|
||||
Type(const CXType &cx_type) : cx_type(cx_type) {}
|
||||
std::string get_spelling() const;
|
||||
Type get_result() const;
|
||||
bool operator==(const Cursor::Type& rhs) const;
|
||||
|
||||
CXType cx_type;
|
||||
};
|
||||
|
||||
Cursor();
|
||||
explicit Cursor(const CXCursor& cx_cursor);
|
||||
|
||||
CXCursorKind get_kind() const;
|
||||
Type get_type() const;
|
||||
SourceLocation get_source_location() const;
|
||||
SourceRange get_source_range() const;
|
||||
std::string get_spelling() const;
|
||||
std::string get_display_name() const;
|
||||
std::string get_usr() const;
|
||||
Cursor get_referenced() const;
|
||||
Cursor get_canonical() const;
|
||||
Cursor get_definition() const;
|
||||
Cursor get_semantic_parent() const;
|
||||
std::vector<Cursor> get_arguments() const;
|
||||
operator bool() const;
|
||||
bool operator==(const Cursor& rhs) const;
|
||||
|
||||
bool is_valid_kind() const;
|
||||
std::string get_type_description() const;
|
||||
std::string get_brief_comments() const;
|
||||
|
||||
CXCursor cx_cursor = clang_getNullCursor();
|
||||
};
|
||||
} // namespace clang
|
||||
#endif // CURSOR_H_
|
41
libclangmm/Diagnostic.cc
Normal file
41
libclangmm/Diagnostic.cc
Normal file
@ -0,0 +1,41 @@
|
||||
#include "Diagnostic.h"
|
||||
#include "SourceLocation.h"
|
||||
#include "Tokens.h"
|
||||
#include "Utility.h"
|
||||
|
||||
clang::Diagnostic::Diagnostic(CXTranslationUnit& cx_tu, CXDiagnostic& cx_diagnostic) {
|
||||
severity=clang_getDiagnosticSeverity(cx_diagnostic);
|
||||
severity_spelling=get_severity_spelling(severity);
|
||||
spelling=to_string(clang_getDiagnosticSpelling(cx_diagnostic));
|
||||
|
||||
SourceLocation start_location(clang_getDiagnosticLocation(cx_diagnostic));
|
||||
path=start_location.get_path();
|
||||
auto start_offset=start_location.get_offset();
|
||||
Tokens tokens(cx_tu, SourceRange(start_location, start_location));
|
||||
if(tokens.size()==1)
|
||||
offsets={start_offset, tokens.begin()->offsets.second};
|
||||
|
||||
unsigned num_fix_its=clang_getDiagnosticNumFixIts(cx_diagnostic);
|
||||
for(unsigned c=0;c<num_fix_its;c++) {
|
||||
CXSourceRange fix_it_range;
|
||||
auto source=to_string(clang_getDiagnosticFixIt(cx_diagnostic, c, &fix_it_range));
|
||||
fix_its.emplace_back(source, SourceRange(fix_it_range).get_offsets());
|
||||
}
|
||||
}
|
||||
|
||||
const std::string clang::Diagnostic::get_severity_spelling(unsigned severity) {
|
||||
switch(severity) {
|
||||
case CXDiagnostic_Ignored:
|
||||
return "Ignored";
|
||||
case CXDiagnostic_Note:
|
||||
return "Note";
|
||||
case CXDiagnostic_Warning:
|
||||
return "Warning";
|
||||
case CXDiagnostic_Error:
|
||||
return "Error";
|
||||
case CXDiagnostic_Fatal:
|
||||
return "Fatal";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
32
libclangmm/Diagnostic.h
Normal file
32
libclangmm/Diagnostic.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef DIAGNOSTIC_H_
|
||||
#define DIAGNOSTIC_H_
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <clang-c/Index.h>
|
||||
#include "SourceRange.h"
|
||||
|
||||
namespace clang {
|
||||
class Diagnostic {
|
||||
friend class TranslationUnit;
|
||||
Diagnostic(CXTranslationUnit& cx_tu, CXDiagnostic& cx_diagnostic);
|
||||
public:
|
||||
class FixIt {
|
||||
public:
|
||||
FixIt(const std::string &source, const std::pair<clang::Offset, clang::Offset> &offsets):
|
||||
source(source), offsets(offsets) {}
|
||||
std::string source;
|
||||
std::pair<clang::Offset, clang::Offset> offsets;
|
||||
};
|
||||
|
||||
static const std::string get_severity_spelling(unsigned severity);
|
||||
|
||||
unsigned severity;
|
||||
std::string severity_spelling;
|
||||
std::string spelling;
|
||||
std::string path;
|
||||
std::pair<clang::Offset, clang::Offset> offsets;
|
||||
std::vector<FixIt> fix_its;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // DIAGNOSTIC_H_
|
9
libclangmm/Index.cc
Normal file
9
libclangmm/Index.cc
Normal file
@ -0,0 +1,9 @@
|
||||
#include "Index.h"
|
||||
|
||||
clang::Index::Index(int excludeDeclarationsFromPCH, int displayDiagnostics) {
|
||||
cx_index = clang_createIndex(excludeDeclarationsFromPCH, displayDiagnostics);
|
||||
}
|
||||
|
||||
clang::Index::~Index() {
|
||||
clang_disposeIndex(cx_index);
|
||||
}
|
13
libclangmm/Index.h
Normal file
13
libclangmm/Index.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef INDEX_H_
|
||||
#define INDEX_H_
|
||||
#include <clang-c/Index.h>
|
||||
|
||||
namespace clang {
|
||||
class Index {
|
||||
public:
|
||||
Index(int excludeDeclarationsFromPCH, int displayDiagnostics);
|
||||
~Index();
|
||||
CXIndex cx_index;
|
||||
};
|
||||
} // namespace clang
|
||||
#endif // INDEX_H_
|
39
libclangmm/SourceLocation.cc
Normal file
39
libclangmm/SourceLocation.cc
Normal file
@ -0,0 +1,39 @@
|
||||
#include "SourceLocation.h"
|
||||
#include "Utility.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
SourceLocation::SourceLocation(CXTranslationUnit &tu, const std::string &filepath, unsigned offset) {
|
||||
CXFile file = clang_getFile(tu, filepath.c_str());
|
||||
cx_location = clang_getLocationForOffset(tu, file, offset);
|
||||
}
|
||||
|
||||
SourceLocation::SourceLocation(CXTranslationUnit &tu, const std::string &filepath, unsigned line, unsigned column) {
|
||||
CXFile file = clang_getFile(tu, filepath.c_str());
|
||||
cx_location = clang_getLocation(tu, file, line, column);
|
||||
}
|
||||
|
||||
std::string SourceLocation::get_path() {
|
||||
std::string path;
|
||||
get_data(&path, nullptr, nullptr, nullptr);
|
||||
return path;
|
||||
}
|
||||
Offset SourceLocation::get_offset() {
|
||||
unsigned line, index;
|
||||
get_data(nullptr, &line, &index, nullptr);
|
||||
return{ line, index };
|
||||
}
|
||||
|
||||
void SourceLocation::get_data(std::string* path, unsigned *line, unsigned *column, unsigned *offset) {
|
||||
if (path == nullptr)
|
||||
clang_getExpansionLocation(cx_location, nullptr, line, column, offset);
|
||||
else {
|
||||
CXFile file;
|
||||
clang_getExpansionLocation(cx_location, &file, line, column, offset);
|
||||
if (file != nullptr) {
|
||||
*path = to_string(clang_getFileName(file));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
38
libclangmm/SourceLocation.h
Normal file
38
libclangmm/SourceLocation.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef SOURCELOCATION_H_
|
||||
#define SOURCELOCATION_H_
|
||||
|
||||
#include <clang-c/Index.h>
|
||||
#include <string>
|
||||
|
||||
namespace clang {
|
||||
|
||||
class Offset {
|
||||
public:
|
||||
Offset() {}
|
||||
Offset(unsigned line, unsigned index) : line(line), index(index) {}
|
||||
bool operator==(const clang::Offset &o) { return (line == o.line && index == o.index); }
|
||||
bool operator!=(const clang::Offset &o) { return !(*this == o); }
|
||||
unsigned line;
|
||||
unsigned index; //byte index in line (not char number)
|
||||
};
|
||||
|
||||
class SourceLocation {
|
||||
friend class TranslationUnit;
|
||||
SourceLocation(CXTranslationUnit &tu, const std::string &filepath, unsigned offset);
|
||||
SourceLocation(CXTranslationUnit &tu, const std::string &filepath, unsigned line, unsigned column);
|
||||
public:
|
||||
SourceLocation(const CXSourceLocation& cx_location) : cx_location(cx_location) {}
|
||||
|
||||
public:
|
||||
std::string get_path();
|
||||
clang::Offset get_offset();
|
||||
|
||||
CXSourceLocation cx_location;
|
||||
|
||||
private:
|
||||
void get_data(std::string *path, unsigned *line, unsigned *column, unsigned *offset);
|
||||
};
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif // SOURCELOCATION_H_
|
10
libclangmm/SourceRange.cc
Normal file
10
libclangmm/SourceRange.cc
Normal file
@ -0,0 +1,10 @@
|
||||
#include "SourceRange.h"
|
||||
|
||||
clang::SourceRange::SourceRange(clang::SourceLocation &start, clang::SourceLocation &end) {
|
||||
cx_range = clang_getRange(start.cx_location, end.cx_location);
|
||||
}
|
||||
|
||||
std::pair<clang::Offset, clang::Offset> clang::SourceRange::get_offsets() {
|
||||
SourceLocation start(clang_getRangeStart(cx_range)), end(clang_getRangeEnd(cx_range));
|
||||
return {start.get_offset(), end.get_offset()};
|
||||
}
|
17
libclangmm/SourceRange.h
Normal file
17
libclangmm/SourceRange.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef SOURCERANGE_H_
|
||||
#define SOURCERANGE_H_
|
||||
#include <clang-c/Index.h>
|
||||
#include "SourceLocation.h"
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace clang {
|
||||
class SourceRange {
|
||||
public:
|
||||
SourceRange(const CXSourceRange& cx_range) : cx_range(cx_range) {}
|
||||
SourceRange(SourceLocation &start, SourceLocation &end);
|
||||
std::pair<clang::Offset, clang::Offset> get_offsets();
|
||||
CXSourceRange cx_range;
|
||||
};
|
||||
} // namespace clang
|
||||
#endif // SOURCERANGE_H_
|
46
libclangmm/Token.cc
Normal file
46
libclangmm/Token.cc
Normal file
@ -0,0 +1,46 @@
|
||||
#include "Token.h"
|
||||
#include "Utility.h"
|
||||
|
||||
// // // // //
|
||||
// Token //
|
||||
// // // // //
|
||||
|
||||
// returns gets an source location for this token objekt
|
||||
// based on the translationunit given
|
||||
clang::SourceLocation clang::Token::get_source_location() const {
|
||||
return SourceLocation(clang_getTokenLocation(cx_tu, cx_token));
|
||||
}
|
||||
|
||||
// returns a sourcerange that covers this token
|
||||
clang::SourceRange clang::Token::get_source_range() const {
|
||||
return SourceRange(clang_getTokenExtent(cx_tu, cx_token));
|
||||
}
|
||||
// returns a string description of this tokens kind
|
||||
std::string clang::Token::get_spelling() const {
|
||||
return to_string(clang_getTokenSpelling(cx_tu, cx_token));
|
||||
}
|
||||
|
||||
clang::Token::Kind clang::Token::get_kind() const {
|
||||
return static_cast<Kind>(clang_getTokenKind(cx_token));
|
||||
}
|
||||
|
||||
bool clang::Token::is_identifier() const {
|
||||
auto token_kind=get_kind();
|
||||
auto cursor=get_cursor();
|
||||
if(token_kind==clang::Token::Kind::Identifier && cursor.is_valid_kind())
|
||||
return true;
|
||||
else if(token_kind==clang::Token::Kind::Keyword && cursor.is_valid_kind()) {
|
||||
auto spelling=get_spelling();
|
||||
if(spelling=="operator" || (spelling=="bool" && get_cursor().get_spelling()=="operator bool"))
|
||||
return true;
|
||||
}
|
||||
else if(token_kind==clang::Token::Kind::Punctuation && cursor.is_valid_kind()) {
|
||||
auto referenced=get_cursor().get_referenced();
|
||||
if(referenced) {
|
||||
auto referenced_kind=referenced.get_kind();
|
||||
if(referenced_kind== CXCursor_FunctionDecl || referenced_kind==CXCursor_CXXMethod || referenced_kind==CXCursor_Constructor)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
38
libclangmm/Token.h
Normal file
38
libclangmm/Token.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef TOKEN_H_
|
||||
#define TOKEN_H_
|
||||
#include <clang-c/Index.h>
|
||||
#include "SourceLocation.h"
|
||||
#include "SourceRange.h"
|
||||
#include "Cursor.h"
|
||||
#include <string>
|
||||
|
||||
namespace clang {
|
||||
class Token {
|
||||
friend class Tokens;
|
||||
public:
|
||||
enum Kind {
|
||||
Punctuation,
|
||||
Keyword,
|
||||
Identifier,
|
||||
Literal,
|
||||
Comment
|
||||
};
|
||||
private:
|
||||
Token(CXTranslationUnit &cx_tu, CXToken &cx_token, CXCursor &cx_cursor):
|
||||
cx_tu(cx_tu), cx_token(cx_token), cx_cursor(cx_cursor), offsets(get_source_range().get_offsets()) {};
|
||||
public:
|
||||
Kind get_kind() const;
|
||||
std::string get_spelling() const;
|
||||
SourceLocation get_source_location() const;
|
||||
SourceRange get_source_range() const;
|
||||
clang::Cursor get_cursor() const {return clang::Cursor(cx_cursor);}
|
||||
|
||||
bool is_identifier() const;
|
||||
|
||||
CXTranslationUnit &cx_tu;
|
||||
CXToken& cx_token;
|
||||
CXCursor& cx_cursor;
|
||||
std::pair<clang::Offset, clang::Offset> offsets;
|
||||
};
|
||||
} // namespace clang
|
||||
#endif // TOKEN_H_
|
36
libclangmm/Tokens.cc
Normal file
36
libclangmm/Tokens.cc
Normal file
@ -0,0 +1,36 @@
|
||||
#include "Tokens.h"
|
||||
#include "Utility.h"
|
||||
|
||||
clang::Tokens::Tokens(CXTranslationUnit &cx_tu, const SourceRange &range): cx_tu(cx_tu) {
|
||||
clang_tokenize(cx_tu, range.cx_range, &cx_tokens, &num_tokens);
|
||||
cx_cursors.resize(num_tokens);
|
||||
clang_annotateTokens(cx_tu, cx_tokens, num_tokens, cx_cursors.data());
|
||||
for (unsigned i = 0; i < num_tokens; i++) {
|
||||
if(cx_cursors[i].kind==CXCursor_DeclRefExpr) { //Temporary fix to a libclang bug
|
||||
auto real_cursor=clang_getCursor(cx_tu, clang_getTokenLocation(cx_tu, cx_tokens[i]));
|
||||
cx_cursors[i]=real_cursor;
|
||||
}
|
||||
emplace_back(Token(cx_tu, cx_tokens[i], cx_cursors[i]));
|
||||
}
|
||||
}
|
||||
|
||||
clang::Tokens::~Tokens() {
|
||||
clang_disposeTokens(cx_tu, cx_tokens, size());
|
||||
}
|
||||
|
||||
//This works across TranslationUnits! However, to get rename refactoring to work,
|
||||
//one have to open all the files that might include a similar token
|
||||
//Similar tokens defined as tokens with equal referenced cursors.
|
||||
std::vector<std::pair<clang::Offset, clang::Offset> > clang::Tokens::get_similar_token_offsets(CXCursorKind kind,
|
||||
const std::string &spelling,
|
||||
const std::string &usr) {
|
||||
std::vector<std::pair<Offset, Offset> > offsets;
|
||||
for(auto &token: *this) {
|
||||
if(token.is_identifier()) {
|
||||
auto referenced=token.get_cursor().get_referenced();
|
||||
if(referenced && kind==referenced.get_kind() && spelling==token.get_spelling() && usr==referenced.get_usr())
|
||||
offsets.emplace_back(token.offsets);
|
||||
}
|
||||
}
|
||||
return offsets;
|
||||
}
|
26
libclangmm/Tokens.h
Normal file
26
libclangmm/Tokens.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef TOKENS_H_
|
||||
#define TOKENS_H_
|
||||
#include <clang-c/Index.h>
|
||||
#include "SourceRange.h"
|
||||
#include "Token.h"
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
class Tokens : public std::vector<clang::Token> {
|
||||
friend class TranslationUnit;
|
||||
friend class Diagnostic;
|
||||
Tokens(CXTranslationUnit &cx_tu, const SourceRange &range);
|
||||
public:
|
||||
~Tokens();
|
||||
std::vector<std::pair<clang::Offset, clang::Offset> > get_similar_token_offsets(CXCursorKind kind,
|
||||
const std::string &spelling,
|
||||
const std::string &usr);
|
||||
private:
|
||||
CXToken *cx_tokens;
|
||||
unsigned num_tokens;
|
||||
std::vector<CXCursor> cx_cursors;
|
||||
CXTranslationUnit& cx_tu;
|
||||
};
|
||||
} // namespace clang
|
||||
#endif // TOKENS_H_
|
128
libclangmm/TranslationUnit.cc
Normal file
128
libclangmm/TranslationUnit.cc
Normal file
@ -0,0 +1,128 @@
|
||||
#include "TranslationUnit.h"
|
||||
#include "SourceLocation.h"
|
||||
#include "Tokens.h"
|
||||
#include "Utility.h"
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include <iostream> //TODO: remove
|
||||
using namespace std; //TODO: remove
|
||||
|
||||
clang::TranslationUnit::TranslationUnit(Index &index, const std::string &file_path,
|
||||
const std::vector<std::string> &command_line_args,
|
||||
const std::string &buffer, unsigned flags) {
|
||||
std::vector<const char*> args;
|
||||
for(auto &a: command_line_args) {
|
||||
args.push_back(a.c_str());
|
||||
}
|
||||
|
||||
CXUnsavedFile files[1];
|
||||
files[0].Filename=file_path.c_str();
|
||||
files[0].Contents=buffer.c_str();
|
||||
files[0].Length=buffer.size();
|
||||
|
||||
cx_tu = clang_parseTranslationUnit(index.cx_index, file_path.c_str(), args.data(),
|
||||
args.size(), files, 1, flags);
|
||||
}
|
||||
|
||||
clang::TranslationUnit::TranslationUnit(Index &index, const std::string &file_path,
|
||||
const std::vector<std::string> &command_line_args,
|
||||
unsigned flags) {
|
||||
std::vector<const char*> args;
|
||||
for(auto &a: command_line_args) {
|
||||
args.push_back(a.c_str());
|
||||
}
|
||||
|
||||
cx_tu = clang_parseTranslationUnit(index.cx_index, file_path.c_str(), args.data(),
|
||||
args.size(), nullptr, 0, flags);
|
||||
}
|
||||
|
||||
clang::TranslationUnit::~TranslationUnit() {
|
||||
clang_disposeTranslationUnit(cx_tu);
|
||||
}
|
||||
|
||||
void clang::TranslationUnit::parse(Index &index, const std::string &file_path,
|
||||
const std::vector<std::string> &command_line_args,
|
||||
const std::map<std::string, std::string> &buffers, unsigned flags) {
|
||||
std::vector<CXUnsavedFile> files;
|
||||
for (auto &buffer : buffers) {
|
||||
CXUnsavedFile file;
|
||||
file.Filename = buffer.first.c_str();
|
||||
file.Contents = buffer.second.c_str();
|
||||
file.Length = buffer.second.size();
|
||||
files.push_back(file);
|
||||
}
|
||||
std::vector<const char*> args;
|
||||
for(auto &a: command_line_args) {
|
||||
args.push_back(a.c_str());
|
||||
}
|
||||
cx_tu = clang_parseTranslationUnit(index.cx_index, file_path.c_str(), args.data(),
|
||||
args.size(), files.data(), files.size(), flags);
|
||||
}
|
||||
|
||||
int clang::TranslationUnit::ReparseTranslationUnit(const std::string &buffer, unsigned flags) {
|
||||
CXUnsavedFile files[1];
|
||||
|
||||
auto file_path=to_string(clang_getTranslationUnitSpelling(cx_tu));
|
||||
|
||||
files[0].Filename=file_path.c_str();
|
||||
files[0].Contents=buffer.c_str();
|
||||
files[0].Length=buffer.size();
|
||||
|
||||
return clang_reparseTranslationUnit(cx_tu, 1, files, flags);
|
||||
}
|
||||
|
||||
unsigned clang::TranslationUnit::DefaultFlags() {
|
||||
auto flags=
|
||||
CXTranslationUnit_CacheCompletionResults |
|
||||
CXTranslationUnit_PrecompiledPreamble |
|
||||
CXTranslationUnit_Incomplete |
|
||||
CXTranslationUnit_IncludeBriefCommentsInCodeCompletion;
|
||||
#if CINDEX_VERSION_MAJOR>0 || (CINDEX_VERSION_MAJOR==0 && CINDEX_VERSION_MINOR>=35)
|
||||
flags|=CXTranslationUnit_KeepGoing;
|
||||
#endif
|
||||
return flags;
|
||||
}
|
||||
|
||||
clang::CodeCompleteResults clang::TranslationUnit::get_code_completions(const std::string &buffer,
|
||||
unsigned line_number, unsigned column) {
|
||||
CodeCompleteResults results(cx_tu, buffer, line_number, column);
|
||||
return results;
|
||||
}
|
||||
|
||||
std::vector<clang::Diagnostic> clang::TranslationUnit::get_diagnostics() {
|
||||
std::vector<Diagnostic> diagnostics;
|
||||
for(unsigned c=0;c<clang_getNumDiagnostics(cx_tu);c++) {
|
||||
CXDiagnostic clang_diagnostic=clang_getDiagnostic(cx_tu, c);
|
||||
diagnostics.emplace_back(Diagnostic(cx_tu, clang_diagnostic));
|
||||
clang_disposeDiagnostic(clang_diagnostic);
|
||||
}
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
std::unique_ptr<clang::Tokens> clang::TranslationUnit::get_tokens(unsigned start_offset, unsigned end_offset) {
|
||||
auto path=clang::to_string(clang_getTranslationUnitSpelling(cx_tu));
|
||||
SourceLocation start_location(cx_tu, path, start_offset);
|
||||
SourceLocation end_location(cx_tu, path, end_offset);
|
||||
SourceRange range(start_location, end_location);
|
||||
return std::unique_ptr<Tokens>(new Tokens(cx_tu, range));
|
||||
}
|
||||
|
||||
std::unique_ptr<clang::Tokens> clang::TranslationUnit::get_tokens(unsigned start_line, unsigned start_column,
|
||||
unsigned end_line, unsigned end_column) {
|
||||
auto path=to_string(clang_getTranslationUnitSpelling(cx_tu));
|
||||
SourceLocation start_location(cx_tu, path, start_line, start_column);
|
||||
SourceLocation end_location(cx_tu, path, end_line, end_column);
|
||||
SourceRange range(start_location, end_location);
|
||||
return std::unique_ptr<Tokens>(new Tokens(cx_tu, range));
|
||||
}
|
||||
|
||||
clang::Cursor clang::TranslationUnit::get_cursor(std::string path, unsigned offset) {
|
||||
SourceLocation location(cx_tu, path, offset);
|
||||
return Cursor(clang_getCursor(cx_tu, location.cx_location));
|
||||
}
|
||||
|
||||
clang::Cursor clang::TranslationUnit::get_cursor(std::string path, unsigned line, unsigned column) {
|
||||
SourceLocation location(cx_tu, path, line, column);
|
||||
return Cursor(clang_getCursor(cx_tu, location.cx_location));
|
||||
}
|
54
libclangmm/TranslationUnit.h
Normal file
54
libclangmm/TranslationUnit.h
Normal file
@ -0,0 +1,54 @@
|
||||
#ifndef TRANSLATIONUNIT_H_
|
||||
#define TRANSLATIONUNIT_H_
|
||||
#include <clang-c/Index.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include "Index.h"
|
||||
#include "Diagnostic.h"
|
||||
#include "Tokens.h"
|
||||
#include "CodeCompleteResults.h"
|
||||
#include "Cursor.h"
|
||||
|
||||
namespace clang {
|
||||
class TranslationUnit {
|
||||
public:
|
||||
TranslationUnit(Index &index,
|
||||
const std::string &file_path,
|
||||
const std::vector<std::string> &command_line_args,
|
||||
const std::string &buffer,
|
||||
unsigned flags=DefaultFlags());
|
||||
TranslationUnit(Index &index,
|
||||
const std::string &file_path,
|
||||
const std::vector<std::string> &command_line_args,
|
||||
unsigned flags=DefaultFlags());
|
||||
~TranslationUnit();
|
||||
|
||||
int ReparseTranslationUnit(const std::string &buffer, unsigned flags=DefaultFlags());
|
||||
|
||||
static unsigned DefaultFlags();
|
||||
|
||||
void parse(Index &index,
|
||||
const std::string &file_path,
|
||||
const std::vector<std::string> &command_line_args,
|
||||
const std::map<std::string, std::string> &buffers,
|
||||
unsigned flags=DefaultFlags());
|
||||
|
||||
clang::CodeCompleteResults get_code_completions(const std::string &buffer,
|
||||
unsigned line_number, unsigned column);
|
||||
|
||||
std::vector<clang::Diagnostic> get_diagnostics();
|
||||
|
||||
std::unique_ptr<Tokens> get_tokens(unsigned start_offset, unsigned end_offset);
|
||||
std::unique_ptr<Tokens> get_tokens(unsigned start_line, unsigned start_column,
|
||||
unsigned end_line, unsigned end_column);
|
||||
|
||||
clang::Cursor get_cursor(std::string path, unsigned offset);
|
||||
clang::Cursor get_cursor(std::string path, unsigned line, unsigned column);
|
||||
|
||||
CXTranslationUnit cx_tu;
|
||||
};
|
||||
} // namespace clang
|
||||
#endif // TRANSLATIONUNIT_H_
|
||||
|
181
libclangmm/Utility.cc
Normal file
181
libclangmm/Utility.cc
Normal file
@ -0,0 +1,181 @@
|
||||
#include "Utility.h"
|
||||
|
||||
std::string clang::to_string(CXString cx_string) {
|
||||
std::string string;
|
||||
if(cx_string.data!=nullptr) {
|
||||
string=clang_getCString(cx_string);
|
||||
clang_disposeString(cx_string);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
std::string clang::to_string(CXCursorKind kind) {
|
||||
switch (kind) {
|
||||
case CXCursor_UnexposedDecl: return "UnexposedDecl";
|
||||
case CXCursor_StructDecl: return "StructDecl";
|
||||
case CXCursor_UnionDecl: return "UnionDecl";
|
||||
case CXCursor_ClassDecl: return "ClassDecl";
|
||||
case CXCursor_EnumDecl: return "EnumDecl";
|
||||
case CXCursor_FieldDecl: return "FieldDecl";
|
||||
case CXCursor_EnumConstantDecl: return "EnumConstantDecl";
|
||||
case CXCursor_FunctionDecl: return "FunctionDecl";
|
||||
case CXCursor_VarDecl: return "VarDecl";
|
||||
case CXCursor_ParmDecl: return "ParmDecl";
|
||||
case CXCursor_ObjCInterfaceDecl: return "ObjCInterfaceDecl";
|
||||
case CXCursor_ObjCCategoryDecl: return "ObjCCategoryDecl";
|
||||
case CXCursor_ObjCProtocolDecl: return "ObjCProtocolDecl";
|
||||
case CXCursor_ObjCPropertyDecl: return "ObjCPropertyDecl";
|
||||
case CXCursor_ObjCIvarDecl: return "ObjCIvarDecl";
|
||||
case CXCursor_ObjCInstanceMethodDecl: return "ObjCInstanceMethodDecl";
|
||||
case CXCursor_ObjCClassMethodDecl: return "ObjCClassMethodDecl";
|
||||
case CXCursor_ObjCImplementationDecl: return "ObjCImplementationDecl";
|
||||
case CXCursor_ObjCCategoryImplDecl: return "ObjCCategoryImplDecl";
|
||||
case CXCursor_TypedefDecl: return "TypedefDecl";
|
||||
case CXCursor_CXXMethod: return "CXXMethod";
|
||||
case CXCursor_Namespace: return "Namespace";
|
||||
case CXCursor_LinkageSpec: return "LinkageSpec";
|
||||
case CXCursor_Constructor: return "Constructor";
|
||||
case CXCursor_Destructor: return "Destructor";
|
||||
case CXCursor_ConversionFunction: return "ConversionFunction";
|
||||
case CXCursor_TemplateTypeParameter: return "TemplateTypeParameter";
|
||||
case CXCursor_NonTypeTemplateParameter: return "NonTypeTemplateParameter";
|
||||
case CXCursor_TemplateTemplateParameter: return "TemplateTemplateParameter";
|
||||
case CXCursor_FunctionTemplate: return "FunctionTemplate";
|
||||
case CXCursor_ClassTemplate: return "ClassTemplate";
|
||||
case CXCursor_ClassTemplatePartialSpecialization: return "ClassTemplatePartialSpecialization";
|
||||
case CXCursor_NamespaceAlias: return "NamespaceAlias";
|
||||
case CXCursor_UsingDirective: return "UsingDirective";
|
||||
case CXCursor_UsingDeclaration: return "UsingDeclaration";
|
||||
case CXCursor_TypeAliasDecl: return "TypeAliasDecl";
|
||||
case CXCursor_ObjCSynthesizeDecl: return "ObjCSynthesizeDecl";
|
||||
case CXCursor_ObjCDynamicDecl: return "ObjCDynamicDecl";
|
||||
case CXCursor_CXXAccessSpecifier: return "CXXAccessSpecifier";
|
||||
//case CXCursor_FirstDecl: return "FirstDecl";
|
||||
//case CXCursor_LastDecl: return "LastDecl";
|
||||
//case CXCursor_FirstRef: return "FirstRef";
|
||||
case CXCursor_ObjCSuperClassRef: return "ObjCSuperClassRef";
|
||||
case CXCursor_ObjCProtocolRef: return "ObjCProtocolRef";
|
||||
case CXCursor_ObjCClassRef: return "ObjCClassRef";
|
||||
case CXCursor_TypeRef: return "TypeRef";
|
||||
case CXCursor_CXXBaseSpecifier: return "CXXBaseSpecifier";
|
||||
case CXCursor_TemplateRef: return "TemplateRef";
|
||||
case CXCursor_NamespaceRef: return "NamespaceRef";
|
||||
case CXCursor_MemberRef: return "MemberRef";
|
||||
case CXCursor_LabelRef: return "LabelRef";
|
||||
case CXCursor_OverloadedDeclRef: return "OverloadedDeclRef";
|
||||
case CXCursor_VariableRef: return "VariableRef";
|
||||
//case CXCursor_LastRef: return "LastRef";
|
||||
//case CXCursor_FirstInvalid: return "FirstInvalid";
|
||||
case CXCursor_InvalidFile: return "InvalidFile";
|
||||
case CXCursor_NoDeclFound: return "NoDeclFound";
|
||||
case CXCursor_NotImplemented: return "NotImplemented";
|
||||
case CXCursor_InvalidCode: return "InvalidCode";
|
||||
//case CXCursor_LastInvalid: return "LastInvalid";
|
||||
//case CXCursor_FirstExpr: return "FirstExpr";
|
||||
case CXCursor_UnexposedExpr: return "UnexposedExpr";
|
||||
case CXCursor_DeclRefExpr: return "DeclRefExpr";
|
||||
case CXCursor_MemberRefExpr: return "MemberRefExpr";
|
||||
case CXCursor_CallExpr: return "CallExpr";
|
||||
case CXCursor_ObjCMessageExpr: return "ObjCMessageExpr";
|
||||
case CXCursor_BlockExpr: return "BlockExpr";
|
||||
case CXCursor_IntegerLiteral: return "IntegerLiteral";
|
||||
case CXCursor_FloatingLiteral: return "FloatingLiteral";
|
||||
case CXCursor_ImaginaryLiteral: return "ImaginaryLiteral";
|
||||
case CXCursor_StringLiteral: return "StringLiteral";
|
||||
case CXCursor_CharacterLiteral: return "CharacterLiteral";
|
||||
case CXCursor_ParenExpr: return "ParenExpr";
|
||||
case CXCursor_UnaryOperator: return "UnaryOperator";
|
||||
case CXCursor_ArraySubscriptExpr: return "ArraySubscriptExpr";
|
||||
case CXCursor_BinaryOperator: return "BinaryOperator";
|
||||
case CXCursor_CompoundAssignOperator: return "CompoundAssignOperator";
|
||||
case CXCursor_ConditionalOperator: return "ConditionalOperator";
|
||||
case CXCursor_CStyleCastExpr: return "CStyleCastExpr";
|
||||
case CXCursor_CompoundLiteralExpr: return "CompoundLiteralExpr";
|
||||
case CXCursor_InitListExpr: return "InitListExpr";
|
||||
case CXCursor_AddrLabelExpr: return "AddrLabelExpr";
|
||||
case CXCursor_StmtExpr: return "StmtExpr";
|
||||
case CXCursor_GenericSelectionExpr: return "GenericSelectionExpr";
|
||||
case CXCursor_GNUNullExpr: return "GNUNullExpr";
|
||||
case CXCursor_CXXStaticCastExpr: return "CXXStaticCastExpr";
|
||||
case CXCursor_CXXDynamicCastExpr: return "CXXDynamicCastExpr";
|
||||
case CXCursor_CXXReinterpretCastExpr: return "CXXReinterpretCastExpr";
|
||||
case CXCursor_CXXConstCastExpr: return "CXXConstCastExpr";
|
||||
case CXCursor_CXXFunctionalCastExpr: return "CXXFunctionalCastExpr";
|
||||
case CXCursor_CXXTypeidExpr: return "CXXTypeidExpr";
|
||||
case CXCursor_CXXBoolLiteralExpr: return "CXXBoolLiteralExpr";
|
||||
case CXCursor_CXXNullPtrLiteralExpr: return "CXXNullPtrLiteralExpr";
|
||||
case CXCursor_CXXThisExpr: return "CXXThisExpr";
|
||||
case CXCursor_CXXThrowExpr: return "CXXThrowExpr";
|
||||
case CXCursor_CXXNewExpr: return "CXXNewExpr";
|
||||
case CXCursor_CXXDeleteExpr: return "CXXDeleteExpr";
|
||||
case CXCursor_UnaryExpr: return "UnaryExpr";
|
||||
case CXCursor_ObjCStringLiteral: return "ObjCStringLiteral";
|
||||
case CXCursor_ObjCEncodeExpr: return "ObjCEncodeExpr";
|
||||
case CXCursor_ObjCSelectorExpr: return "ObjCSelectorExpr";
|
||||
case CXCursor_ObjCProtocolExpr: return "ObjCProtocolExpr";
|
||||
case CXCursor_ObjCBridgedCastExpr: return "ObjCBridgedCastExpr";
|
||||
case CXCursor_PackExpansionExpr: return "PackExpansionExpr";
|
||||
case CXCursor_SizeOfPackExpr: return "SizeOfPackExpr";
|
||||
case CXCursor_LambdaExpr: return "LambdaExpr";
|
||||
case CXCursor_ObjCBoolLiteralExpr: return "ObjCBoolLiteralExpr";
|
||||
case CXCursor_ObjCSelfExpr: return "ObjCSelfExpr";
|
||||
//case CXCursor_LastExpr: return "LastExpr";
|
||||
//case CXCursor_FirstStmt: return "FirstStmt";
|
||||
case CXCursor_UnexposedStmt: return "UnexposedStmt";
|
||||
case CXCursor_LabelStmt: return "LabelStmt";
|
||||
case CXCursor_CompoundStmt: return "CompoundStmt";
|
||||
case CXCursor_CaseStmt: return "CaseStmt";
|
||||
case CXCursor_DefaultStmt: return "DefaultStmt";
|
||||
case CXCursor_IfStmt: return "IfStmt";
|
||||
case CXCursor_SwitchStmt: return "SwitchStmt";
|
||||
case CXCursor_WhileStmt: return "WhileStmt";
|
||||
case CXCursor_DoStmt: return "DoStmt";
|
||||
case CXCursor_ForStmt: return "ForStmt";
|
||||
case CXCursor_GotoStmt: return "GotoStmt";
|
||||
case CXCursor_IndirectGotoStmt: return "IndirectGotoStmt";
|
||||
case CXCursor_ContinueStmt: return "ContinueStmt";
|
||||
case CXCursor_BreakStmt: return "BreakStmt";
|
||||
case CXCursor_ReturnStmt: return "ReturnStmt";
|
||||
case CXCursor_GCCAsmStmt: return "GCCAsmStmt";
|
||||
//case CXCursor_AsmStmt: return "AsmStmt";
|
||||
case CXCursor_ObjCAtTryStmt: return "ObjCAtTryStmt";
|
||||
case CXCursor_ObjCAtCatchStmt: return "ObjCAtCatchStmt";
|
||||
case CXCursor_ObjCAtFinallyStmt: return "ObjCAtFinallyStmt";
|
||||
case CXCursor_ObjCAtThrowStmt: return "ObjCAtThrowStmt";
|
||||
case CXCursor_ObjCAtSynchronizedStmt: return "ObjCAtSynchronizedStmt";
|
||||
case CXCursor_ObjCAutoreleasePoolStmt: return "ObjCAutoreleasePoolStmt";
|
||||
case CXCursor_ObjCForCollectionStmt: return "ObjCForCollectionStmt";
|
||||
case CXCursor_CXXCatchStmt: return "CXXCatchStmt";
|
||||
case CXCursor_CXXTryStmt: return "CXXTryStmt";
|
||||
case CXCursor_CXXForRangeStmt: return "CXXForRangeStmt";
|
||||
case CXCursor_SEHTryStmt: return "SEHTryStmt";
|
||||
case CXCursor_SEHExceptStmt: return "SEHExceptStmt";
|
||||
case CXCursor_SEHFinallyStmt: return "SEHFinallyStmt";
|
||||
case CXCursor_MSAsmStmt: return "MSAsmStmt";
|
||||
case CXCursor_NullStmt: return "NullStmt";
|
||||
case CXCursor_DeclStmt: return "DeclStmt";
|
||||
case CXCursor_LastStmt: return "LastStmt";
|
||||
case CXCursor_TranslationUnit: return "TranslationUnit";
|
||||
//case CXCursor_FirstAttr: return "FirstAttr";
|
||||
case CXCursor_UnexposedAttr: return "UnexposedAttr";
|
||||
case CXCursor_IBActionAttr: return "IBActionAttr";
|
||||
case CXCursor_IBOutletAttr: return "IBOutletAttr";
|
||||
case CXCursor_IBOutletCollectionAttr: return "IBOutletCollectionAttr";
|
||||
case CXCursor_CXXFinalAttr: return "CXXFinalAttr";
|
||||
case CXCursor_CXXOverrideAttr: return "CXXOverrideAttr";
|
||||
case CXCursor_AnnotateAttr: return "AnnotateAttr";
|
||||
case CXCursor_AsmLabelAttr: return "AsmLabelAttr";
|
||||
case CXCursor_LastAttr: return "LastAttr";
|
||||
case CXCursor_PreprocessingDirective: return "PreprocessingDirective";
|
||||
case CXCursor_MacroDefinition: return "MacroDefinition";
|
||||
case CXCursor_MacroExpansion: return "MacroExpansion";
|
||||
//case CXCursor_MacroInstantiation: return "MacroInstantiation";
|
||||
case CXCursor_InclusionDirective: return "InclusionDirective";
|
||||
//case CXCursor_FirstPreprocessing: return "FirstPreprocessing";
|
||||
//case CXCursor_LastPreprocessing: return "LastPreprocessing";
|
||||
case CXCursor_ModuleImportDecl: return "ModuleImportDecl";
|
||||
//case CXCursor_FirstExtraDecl: return "FirstExtraDecl";
|
||||
case CXCursor_LastExtraDecl: return "LastExtraDecl";
|
||||
}
|
||||
return "";
|
||||
}
|
11
libclangmm/Utility.h
Normal file
11
libclangmm/Utility.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef UTILITY_H_
|
||||
#define UTILITY_H_
|
||||
#include <clang-c/Index.h>
|
||||
#include <string>
|
||||
|
||||
namespace clang {
|
||||
std::string to_string(CXString cx_string);
|
||||
std::string to_string(CXCursorKind cursor_kind);
|
||||
}
|
||||
|
||||
#endif // UTILITY_H_
|
17
libclangmm/clangmm.h
Normal file
17
libclangmm/clangmm.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef CLANGMM_H_
|
||||
#define CLANGMM_H_
|
||||
#include "TranslationUnit.h"
|
||||
#include "SourceLocation.h"
|
||||
#include "SourceRange.h"
|
||||
#include "Token.h"
|
||||
#include "Tokens.h"
|
||||
#include "CompilationDatabase.h"
|
||||
#include "CompileCommands.h"
|
||||
#include "CompileCommand.h"
|
||||
#include "CodeCompleteResults.h"
|
||||
#include "CompletionString.h"
|
||||
#include "Index.h"
|
||||
#include "Cursor.h"
|
||||
#include "Diagnostic.h"
|
||||
#include "Utility.h"
|
||||
#endif // CLANGMM_H_
|
85
main.cpp
Normal file
85
main.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "libclangmm\clangmm.h"
|
||||
#include "libclangmm\Utility.h"
|
||||
//#include <clang-c\Index.h>
|
||||
|
||||
CXChildVisitResult visitPrint(CXCursor cursor0, CXCursor parent, CXClientData param) {
|
||||
int* level = static_cast<int*>(param);
|
||||
|
||||
clang::Cursor cursor(cursor0);
|
||||
|
||||
for (int i = 0; i < *level; ++i)
|
||||
std::cout << " ";
|
||||
std::cout << cursor.get_spelling() << " " << clang::to_string(cursor.get_kind()) << std::endl;
|
||||
|
||||
*level += 1;
|
||||
clang_visitChildren(cursor0, &visitPrint, level);
|
||||
*level -= 1;
|
||||
|
||||
return CXChildVisitResult::CXChildVisit_Continue;
|
||||
/*
|
||||
echo " ".repeat(param.level), cursor.kind, " ", getSpelling(cursor)
|
||||
|
||||
var visitParam : VisitPrintParam
|
||||
visitParam.level = param.level + 1
|
||||
visitChildren(cursor, visitPrint, addr visitParam)
|
||||
|
||||
return VisitResult.Continu
|
||||
*/
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
/*
|
||||
echo "Parsing ", filename
|
||||
let index : libclang.CXIndex = libclang.createIndex(#[excludeDeclsFromPCH]# 0, #[displayDiagnostics]# 0)
|
||||
|
||||
let translationUnit : libclang.CXTranslationUnit =
|
||||
libclang.parseTranslationUnit(index, filename.cstring, nil, 0, nil, 0, 0)
|
||||
if translationUnit == nil :
|
||||
echo "Error: cannot create translation unit for '", filename, "'"
|
||||
return
|
||||
|
||||
let cursor = libclang.getTranslationUnitCursor(translationUnit)
|
||||
|
||||
var param : VisitFileParam
|
||||
param.db = db
|
||||
|
||||
echo "=== START AST ==="
|
||||
# printChildren(cursor, 0)
|
||||
echo "=== DONE AST ==="
|
||||
|
||||
var file : File
|
||||
file.path = filename
|
||||
file.vars = newList[VarRef]()
|
||||
file.funcs = newList[FuncRef]()
|
||||
file.types = newList[TypeRef]()
|
||||
|
||||
visitChildren(cursor, visitFile, addr param)
|
||||
|
||||
libclang.disposeTranslationUnit(translationUnit)
|
||||
libclang.disposeIndex(index)
|
||||
*/
|
||||
|
||||
std::vector<std::string> args;
|
||||
|
||||
clang::Index index(0 /*excludeDeclarationsFromPCH*/, 0 /*displayDiagnostics*/);
|
||||
clang::TranslationUnit translationUnit(index, "test.cc", args);
|
||||
|
||||
int level = 0;
|
||||
auto cursor = clang_getTranslationUnitCursor(translationUnit.cx_tu);
|
||||
clang_visitChildren(cursor, &visitPrint, &level);
|
||||
/*
|
||||
TranslationUnit(Index &index,
|
||||
const std::string &file_path,
|
||||
const std::vector<std::string> &command_line_args,
|
||||
const std::string &buffer,
|
||||
unsigned flags = DefaultFlags());
|
||||
TranslationUnit(Index &index,
|
||||
const std::string &file_path,
|
||||
const std::vector<std::string> &command_line_args,
|
||||
unsigned flags = DefaultFlags());
|
||||
*/
|
||||
|
||||
std::cin.get();
|
||||
}
|
Loading…
Reference in New Issue
Block a user