Browse Source

Formatted code with custom clang-format

merge-requests/37/head
eidheim 8 years ago
parent
commit
791b76b04c
  1. 9
      .clang-format
  2. 30
      README.md
  3. 18
      src/clangmm.h
  4. 24
      src/code_complete_results.cc
  5. 7
      src/code_complete_results.h
  6. 5
      src/compilation_database.h
  7. 2
      src/compile_command.cc
  8. 8
      src/compile_command.h
  9. 4
      src/compile_commands.cc
  10. 4
      src/compile_commands.h
  11. 78
      src/completion_string.cc
  12. 8
      src/completion_string.h
  13. 141
      src/cursor.cc
  14. 14
      src/cursor.h
  15. 22
      src/diagnostic.cc
  16. 15
      src/diagnostic.h
  17. 4
      src/index.h
  18. 9
      src/source_location.cc
  19. 23
      src/source_location.h
  20. 8
      src/source_range.h
  21. 20
      src/token.cc
  22. 21
      src/token.h
  23. 70
      src/tokens.cc
  24. 18
      src/tokens.h
  25. 46
      src/translation_unit.cc
  26. 27
      src/translation_unit.h
  27. 87
      src/utility.cc
  28. 4
      src/utility.h
  29. 36
      tests/code_complete_results_test.cc
  30. 32
      tests/completion_string_test.cc
  31. 16
      tests/cursor_test.cc
  32. 22
      tests/diagnostics_test.cc
  33. 10
      tests/source_location_test.cc
  34. 8
      tests/token_test.cc
  35. 8
      tests/translation_unit_test.cc

9
.clang-format

@ -0,0 +1,9 @@
IndentWidth: 2
AccessModifierOffset: -2
UseTab: Never
ColumnLimit: 0
MaxEmptyLinesToKeep: 2
SpaceBeforeParens: Never
BreakBeforeBraces: Custom
BraceWrapping: {BeforeElse: true, BeforeCatch: true}
NamespaceIndentation: All

30
README.md

@ -13,7 +13,7 @@ Developed for [juCi++](https://gitlab.com/cppit/jucipp), a lightweight, platform
## Installation ##
See [installation guide](https://gitlab.com/cppit/libclangmm/blob/master/docs/install.md)
# Tests #
## Tests ##
To run the unit tests:
```sh
mkdir build && cd build
@ -21,3 +21,31 @@ cmake -DBUILD_TESTING=1 ..
make
make test
```
## Coding style
Due to poor lambda support in clang-format, a custom clang-format is used with the following patch applied:
```diff
diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp
index bb8efd61a3..e80a487055 100644
--- a/lib/Format/ContinuationIndenter.cpp
+++ b/lib/Format/ContinuationIndenter.cpp
@@ -276,6 +276,8 @@ LineState ContinuationIndenter::getInitialState(unsigned FirstIndent,
}
bool ContinuationIndenter::canBreak(const LineState &State) {
+ if(Style.ColumnLimit==0)
+ return true;
const FormatToken &Current = *State.NextToken;
const FormatToken &Previous = *Current.Previous;
assert(&Previous == Current.Previous);
@@ -325,6 +327,8 @@ bool ContinuationIndenter::canBreak(const LineState &State) {
}
bool ContinuationIndenter::mustBreak(const LineState &State) {
+ if(Style.ColumnLimit==0)
+ return false;
const FormatToken &Current = *State.NextToken;
const FormatToken &Previous = *Current.Previous;
if (Current.MustBreakBefore || Current.is(TT_InlineASMColon))
```

18
src/clangmm.h

@ -1,17 +1,17 @@
#ifndef CLANGMM_H_
#define CLANGMM_H_
#include "translation_unit.h"
#include "source_location.h"
#include "source_range.h"
#include "token.h"
#include "tokens.h"
#include "code_complete_results.h"
#include "compilation_database.h"
#include "compile_commands.h"
#include "compile_command.h"
#include "code_complete_results.h"
#include "compile_commands.h"
#include "completion_string.h"
#include "index.h"
#include "cursor.h"
#include "diagnostic.h"
#include "index.h"
#include "source_location.h"
#include "source_range.h"
#include "token.h"
#include "tokens.h"
#include "translation_unit.h"
#include "utility.h"
#endif // CLANGMM_H_
#endif // CLANGMM_H_

24
src/code_complete_results.cc

@ -3,21 +3,21 @@
#include "utility.h"
clangmm::CodeCompleteResults::CodeCompleteResults(CXTranslationUnit &cx_tu,
const std::string &buffer,
unsigned line_num, unsigned column) {
const std::string &buffer,
unsigned line_num, unsigned column) {
CXUnsavedFile files[1];
auto file_path=to_string(clang_getTranslationUnitSpelling(cx_tu));
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);
file_path.c_str(),
line_num,
column,
files,
1,
clang_defaultCodeCompleteOptions() | CXCodeComplete_IncludeBriefComments);
if(cx_results)
clang_sortCodeCompletionResults(cx_results->Results, cx_results->NumResults);
}
@ -27,11 +27,11 @@ clangmm::CodeCompleteResults::CodeCompleteResults(CodeCompleteResults &&rhs) : c
}
clangmm::CodeCompleteResults &clangmm::CodeCompleteResults::operator=(CodeCompleteResults &&rhs) {
if(this!=&rhs) {
if(this != &rhs) {
if(cx_results)
clang_disposeCodeCompleteResults(cx_results);
cx_results=rhs.cx_results;
rhs.cx_results=nullptr;
cx_results = rhs.cx_results;
rhs.cx_results = nullptr;
}
return *this;
}

7
src/code_complete_results.h

@ -1,9 +1,9 @@
#ifndef CODECOMPLETERESULTS_H_
#define CODECOMPLETERESULTS_H_
#include "completion_string.h"
#include <clang-c/Index.h>
#include <map>
#include <string>
#include "completion_string.h"
namespace clangmm {
class CodeCompleteResults {
@ -11,6 +11,7 @@ namespace clangmm {
CodeCompleteResults(CXTranslationUnit &cx_tu, const std::string &buffer,
unsigned line_num, unsigned column);
public:
CodeCompleteResults(CodeCompleteResults &) = delete;
CodeCompleteResults(CodeCompleteResults &&rhs);
@ -23,5 +24,5 @@ namespace clangmm {
CXCodeCompleteResults *cx_results;
};
} // namespace clangmm
#endif // CODECOMPLETERESULTS_H_
} // namespace clangmm
#endif // CODECOMPLETERESULTS_H_

5
src/compilation_database.h

@ -7,6 +7,7 @@
namespace clangmm {
class CompilationDatabase {
CXCompilationDatabase_Error cx_db_error;
public:
explicit CompilationDatabase(const std::string &project_path);
~CompilationDatabase();
@ -15,6 +16,6 @@ namespace clangmm {
CXCompilationDatabase cx_db;
};
}
} // namespace clangmm
#endif // COMPILATIONDATABASE_H_
#endif // COMPILATIONDATABASE_H_

2
src/compile_command.cc

@ -5,7 +5,7 @@
std::vector<std::string> clangmm::CompileCommand::get_arguments() {
unsigned size = clang_CompileCommand_getNumArgs(cx_command);
std::vector<std::string> arguments;
for (unsigned i = 0; i < size; i++)
for(unsigned i = 0; i < size; i++)
arguments.emplace_back(to_string(clang_CompileCommand_getArg(cx_command, i)));
return arguments;
}

8
src/compile_command.h

@ -1,16 +1,16 @@
#ifndef COMPILECOMMAND_H_
#define COMPILECOMMAND_H_
#include <clang-c/CXCompilationDatabase.h>
#include <vector>
#include <string>
#include <vector>
namespace clangmm {
class CompileCommand {
public:
CompileCommand(const CXCompileCommand& cx_command) : cx_command(cx_command) {};
CompileCommand(const CXCompileCommand &cx_command) : cx_command(cx_command){};
std::vector<std::string> get_arguments();
CXCompileCommand cx_command;
};
}
#endif // COMPILECOMMAND_H_
} // namespace clangmm
#endif // COMPILECOMMAND_H_

4
src/compile_commands.cc

@ -3,7 +3,7 @@
clangmm::CompileCommands::CompileCommands(const std::string &filename, CompilationDatabase &db) {
if(!filename.empty())
cx_commands = clang_CompilationDatabase_getCompileCommands(db.cx_db, filename.c_str());
if(filename.empty() || clang_CompileCommands_getSize(cx_commands)==0)
if(filename.empty() || clang_CompileCommands_getSize(cx_commands) == 0)
cx_commands = clang_CompilationDatabase_getAllCompileCommands(db.cx_db);
}
@ -15,7 +15,7 @@ std::vector<clangmm::CompileCommand> clangmm::CompileCommands::get_commands() {
unsigned size = clang_CompileCommands_getSize(cx_commands);
std::vector<CompileCommand> commands;
commands.reserve(size);
for (unsigned i = 0; i < size; i++)
for(unsigned i = 0; i < size; i++)
commands.emplace_back(clang_CompileCommands_getCommand(cx_commands, i));
return commands;
}

4
src/compile_commands.h

@ -15,5 +15,5 @@ namespace clangmm {
CXCompileCommands cx_commands;
};
}
#endif // COMPILECOMMANDS_H_
} // namespace clangmm
#endif // COMPILECOMMANDS_H_

78
src/completion_string.cc

@ -39,35 +39,35 @@ clangmm::Cursor clangmm::CompletionString::get_cursor(CXTranslationUnit &tu) con
public:
static void remove_template_argument_and_namespace(std::string &chunk) {
size_t pos1, pos2;
if((pos1=chunk.find('<'))!=std::string::npos && (pos2=chunk.rfind('>'))!=std::string::npos)
chunk=chunk.substr(0, pos1)+chunk.substr(pos2+1);
if((pos2=chunk.rfind("::"))!=std::string::npos) {
pos1=pos2-1;
while(pos1!=std::string::npos && ((chunk[pos1]>='a' && chunk[pos1]<='z') || (chunk[pos1]>='A' && chunk[pos1]<='Z') ||
(chunk[pos1]>='0' && chunk[pos1]<='9') || chunk[pos1]==':' || chunk[pos1]=='_'))
if((pos1 = chunk.find('<')) != std::string::npos && (pos2 = chunk.rfind('>')) != std::string::npos)
chunk = chunk.substr(0, pos1) + chunk.substr(pos2 + 1);
if((pos2 = chunk.rfind("::")) != std::string::npos) {
pos1 = pos2 - 1;
while(pos1 != std::string::npos && ((chunk[pos1] >= 'a' && chunk[pos1] <= 'z') || (chunk[pos1] >= 'A' && chunk[pos1] <= 'Z') ||
(chunk[pos1] >= '0' && chunk[pos1] <= '9') || chunk[pos1] == ':' || chunk[pos1] == '_'))
--pos1;
chunk=chunk.substr(0, pos1+1)+chunk.substr(pos2+2);
chunk = chunk.substr(0, pos1 + 1) + chunk.substr(pos2 + 2);
}
}
};
std::vector<std::string> chunks;
for(unsigned i=0;i<clang_getNumCompletionChunks(cx_completion_string);++i) {
for(unsigned i = 0; i < clang_getNumCompletionChunks(cx_completion_string); ++i) {
auto kind = clang_getCompletionChunkKind(cx_completion_string, i);
if(kind != CXCompletionChunk_Optional && kind != CXCompletionChunk_Informative) {
auto chunk=clangmm::to_string(clang_getCompletionChunkText(cx_completion_string, i));
auto chunk = clangmm::to_string(clang_getCompletionChunkText(cx_completion_string, i));
ChunkString::remove_template_argument_and_namespace(chunk);
chunks.emplace_back(chunk);
}
}
auto parent=clangmm::to_string(clang_getCompletionParent(cx_completion_string, nullptr));
auto parent = clangmm::to_string(clang_getCompletionParent(cx_completion_string, nullptr));
std::vector<std::string> parent_parts;
if(!parent.empty()) {
size_t pos=0;
size_t last_pos=0;
while((pos=parent.find("::", pos))!=std::string::npos) {
parent_parts.emplace_back(parent.substr(last_pos, pos-last_pos));
pos+=2;
last_pos=pos;
size_t pos = 0;
size_t last_pos = 0;
while((pos = parent.find("::", pos)) != std::string::npos) {
parent_parts.emplace_back(parent.substr(last_pos, pos - last_pos));
pos += 2;
last_pos = pos;
}
parent_parts.emplace_back(parent.substr(last_pos));
}
@ -77,51 +77,51 @@ clangmm::Cursor clangmm::CompletionString::get_cursor(CXTranslationUnit &tu) con
clang_visitChildren(clang_getTranslationUnitCursor(tu), [](CXCursor cx_cursor, CXCursor cx_parent, CXClientData cx_data) {
auto data = static_cast<VisitorData *>(cx_data);
bool equal=true;
auto cx_tmp_cursor=cx_parent;
if(clang_getCursorKind(cx_tmp_cursor)!=CXCursorKind::CXCursor_TranslationUnit) {
int c=0;
auto it=data->parent_parts.rbegin();
for(;it!=data->parent_parts.rend();++it) {
auto name=clangmm::to_string(clang_getCursorDisplayName(cx_tmp_cursor));
bool equal = true;
auto cx_tmp_cursor = cx_parent;
if(clang_getCursorKind(cx_tmp_cursor) != CXCursorKind::CXCursor_TranslationUnit) {
int c = 0;
auto it = data->parent_parts.rbegin();
for(; it != data->parent_parts.rend(); ++it) {
auto name = clangmm::to_string(clang_getCursorDisplayName(cx_tmp_cursor));
size_t pos;
if((pos=name.find('<'))!=std::string::npos)
name=name.substr(0, pos);
if(name!=*it) {
equal=false;
if((pos = name.find('<')) != std::string::npos)
name = name.substr(0, pos);
if(name != *it) {
equal = false;
break;
}
cx_tmp_cursor=clang_getCursorSemanticParent(cx_tmp_cursor);
if(clang_getCursorKind(cx_tmp_cursor)==CXCursorKind::CXCursor_TranslationUnit) {
cx_tmp_cursor = clang_getCursorSemanticParent(cx_tmp_cursor);
if(clang_getCursorKind(cx_tmp_cursor) == CXCursorKind::CXCursor_TranslationUnit) {
++it;
break;
}
++c;
}
if(it!=data->parent_parts.rend())
equal=false;
if(it != data->parent_parts.rend())
equal = false;
}
else if(!data->parent_parts.empty())
return CXChildVisit_Recurse;
if(equal) {
auto completion_string = clang_getCursorCompletionString(cx_cursor);
auto num_completion_chunks=clang_getNumCompletionChunks(completion_string);
if(num_completion_chunks>=data->completion_chunks.size()) {
bool equal=true;
for(unsigned i=0;i<data->completion_chunks.size() && i<num_completion_chunks;++i) {
auto num_completion_chunks = clang_getNumCompletionChunks(completion_string);
if(num_completion_chunks >= data->completion_chunks.size()) {
bool equal = true;
for(unsigned i = 0; i < data->completion_chunks.size() && i < num_completion_chunks; ++i) {
auto kind = clang_getCompletionChunkKind(completion_string, i);
if(kind != CXCompletionChunk_Optional && kind != CXCompletionChunk_Informative) {
auto chunk=clangmm::to_string(clang_getCompletionChunkText(completion_string, i));
auto chunk = clangmm::to_string(clang_getCompletionChunkText(completion_string, i));
ChunkString::remove_template_argument_and_namespace(chunk);
if(data->completion_chunks[i]!=chunk) {
equal=false;
if(data->completion_chunks[i] != chunk) {
equal = false;
break;
}
}
}
if(equal) {
data->found_cursor=cx_cursor;
data->found_cursor = cx_cursor;
return CXChildVisit_Break;
}
}

8
src/completion_string.h

@ -1,13 +1,13 @@
#ifndef COMPLETIONSTRING_H_
#define COMPLETIONSTRING_H_
#include "cursor.h"
#include <clang-c/Index.h>
#include <string>
#include <vector>
#include "cursor.h"
namespace clangmm {
enum CompletionChunkKind {
CompletionChunk_Optional, CompletionChunk_TypedText,
CompletionChunk_Optional, CompletionChunk_TypedText,
CompletionChunk_Text, CompletionChunk_Placeholder,
CompletionChunk_Informative, CompletionChunk_CurrentParameter,
CompletionChunk_LeftParen, CompletionChunk_RightParen,
@ -40,5 +40,5 @@ namespace clangmm {
CXCompletionString cx_completion_string;
};
} // namespace clangmm
#endif // COMPLETIONSTRING_H_
} // namespace clangmm
#endif // COMPLETIONSTRING_H_

141
src/cursor.cc

@ -14,7 +14,7 @@ clangmm::Cursor clangmm::Cursor::Type::get_cursor() const {
return Cursor(clang_getTypeDeclaration(cx_type));
}
bool clangmm::Cursor::Type::operator==(const Cursor::Type& rhs) const {
bool clangmm::Cursor::Type::operator==(const Cursor::Type &rhs) const {
return clang_equalTypes(cx_type, rhs.cx_type);
}
@ -27,24 +27,24 @@ std::string clangmm::Cursor::get_kind_spelling() const {
}
bool clangmm::Cursor::is_similar_kind(Kind kind, Kind other_kind) {
auto is_function_or_method=[](Kind kind) {
if(kind==Kind::FunctionDecl || kind==Kind::CXXMethod || kind==Kind::FunctionTemplate)
auto is_function_or_method = [](Kind kind) {
if(kind == Kind::FunctionDecl || kind == Kind::CXXMethod || kind == Kind::FunctionTemplate)
return true;
return false;
};
auto is_class_or_struct=[](Kind kind) {
if(kind==Kind::ClassDecl || kind==Kind::StructDecl || kind==Kind::ClassTemplate ||
kind==Cursor::Kind::Constructor || kind==Cursor::Kind::Destructor || kind==Cursor::Kind::FunctionTemplate)
auto is_class_or_struct = [](Kind kind) {
if(kind == Kind::ClassDecl || kind == Kind::StructDecl || kind == Kind::ClassTemplate ||
kind == Cursor::Kind::Constructor || kind == Cursor::Kind::Destructor || kind == Cursor::Kind::FunctionTemplate)
return true;
return false;
};
if(kind==Kind::FunctionTemplate)
if(kind == Kind::FunctionTemplate)
return is_function_or_method(other_kind) || is_class_or_struct(other_kind);
if(is_function_or_method(kind))
return is_function_or_method(other_kind);
if(is_class_or_struct(kind))
return is_class_or_struct(other_kind);
return kind==other_kind;
return kind == other_kind;
}
clangmm::Cursor::Type clangmm::Cursor::get_type() const {
@ -68,15 +68,15 @@ std::string clangmm::Cursor::get_display_name() const {
}
std::string clangmm::Cursor::get_token_spelling() const {
auto spelling=get_spelling();
for(size_t i=0;i<spelling.size();++i) {
if(spelling[i]=='<' || spelling[i]=='(') {
if(i>0 && spelling[0]=='~')
return spelling.substr(1, i-1);
auto spelling = get_spelling();
for(size_t i = 0; i < spelling.size(); ++i) {
if(spelling[i] == '<' || spelling[i] == '(') {
if(i > 0 && spelling[0] == '~')
return spelling.substr(1, i - 1);
return spelling.substr(0, i);
}
}
if(!spelling.empty() && spelling[0]=='~')
if(!spelling.empty() && spelling[0] == '~')
return spelling.substr(1);
return spelling;
}
@ -89,37 +89,37 @@ std::string clangmm::Cursor::get_usr_extended() const {
if(!is_valid_kind())
return std::string();
auto cursor=*this;
auto kind=cursor.get_kind();
auto cursor = *this;
auto kind = cursor.get_kind();
// If constructor, destructor or function template, and the token spelling is equal, set cursor to parent
if(kind==Cursor::Kind::Constructor || kind==Cursor::Kind::Destructor ||
kind==Cursor::Kind::FunctionTemplate) {
auto parent=cursor.get_semantic_parent();
auto parent_kind=parent.get_kind();
if((parent_kind==Cursor::Kind::ClassDecl || parent_kind==Cursor::Kind::StructDecl || parent_kind==Cursor::Kind::ClassTemplate) &&
cursor.get_token_spelling()==parent.get_token_spelling())
cursor=parent;
if(kind == Cursor::Kind::Constructor || kind == Cursor::Kind::Destructor ||
kind == Cursor::Kind::FunctionTemplate) {
auto parent = cursor.get_semantic_parent();
auto parent_kind = parent.get_kind();
if((parent_kind == Cursor::Kind::ClassDecl || parent_kind == Cursor::Kind::StructDecl || parent_kind == Cursor::Kind::ClassTemplate) &&
cursor.get_token_spelling() == parent.get_token_spelling())
cursor = parent;
}
std::string usr=cursor.get_token_spelling();
auto parent=cursor.get_semantic_parent();
while((kind=parent.get_kind())!=Kind::TranslationUnit && parent.is_valid_kind()) {
if(kind==Kind::CXXMethod || kind==Kind::FunctionDecl || kind==Kind::FunctionTemplate ||
kind==Kind::Constructor || kind==Kind::Destructor) {
auto canonical=cursor.get_canonical();
auto location=canonical.get_source_location();
auto offset=location.get_offset();
return std::to_string(offset.line)+':'+std::to_string(offset.index)+':'+location.get_path();
std::string usr = cursor.get_token_spelling();
auto parent = cursor.get_semantic_parent();
while((kind = parent.get_kind()) != Kind::TranslationUnit && parent.is_valid_kind()) {
if(kind == Kind::CXXMethod || kind == Kind::FunctionDecl || kind == Kind::FunctionTemplate ||
kind == Kind::Constructor || kind == Kind::Destructor) {
auto canonical = cursor.get_canonical();
auto location = canonical.get_source_location();
auto offset = location.get_offset();
return std::to_string(offset.line) + ':' + std::to_string(offset.index) + ':' + location.get_path();
}
usr+=':'+parent.get_token_spelling();
parent=parent.get_semantic_parent();
usr += ':' + parent.get_token_spelling();
parent = parent.get_semantic_parent();
}
return usr;
}
std::unordered_set<std::string> clangmm::Cursor::get_all_usr_extended() const {
std::unordered_set<std::string> usrs;
if(get_kind()==Kind::CXXMethod) {
if(get_kind() == Kind::CXXMethod) {
class Recursive {
public:
static void overridden(std::unordered_set<std::string> &usrs, const Cursor &cursor) {
@ -127,7 +127,7 @@ std::unordered_set<std::string> clangmm::Cursor::get_all_usr_extended() const {
CXCursor *cursors;
unsigned size;
clang_getOverriddenCursors(cursor.cx_cursor, &cursors, &size);
for(unsigned c=0;c<size;++c)
for(unsigned c = 0; c < size; ++c)
overridden(usrs, cursors[c]);
clang_disposeOverriddenCursors(cursors);
}
@ -159,39 +159,36 @@ clangmm::Cursor clangmm::Cursor::get_semantic_parent() const {
std::vector<clangmm::Cursor> clangmm::Cursor::get_children() const {
std::vector<Cursor> result;
clang_visitChildren(cx_cursor,
[](CXCursor cur, CXCursor /*parent*/, CXClientData data) {
static_cast<std::vector<Cursor>*>(data)->emplace_back(cur);
return CXChildVisit_Continue;
},
&result
);
clang_visitChildren(cx_cursor, [](CXCursor cur, CXCursor /*parent*/, CXClientData data) {
static_cast<std::vector<Cursor> *>(data)->emplace_back(cur);
return CXChildVisit_Continue;
}, &result);
return result;
}
std::vector<clangmm::Cursor> clangmm::Cursor::get_arguments() const {
std::vector<Cursor> cursors;
auto size=clang_Cursor_getNumArguments(cx_cursor);
for(int c=0;c<size;++c)
auto size = clang_Cursor_getNumArguments(cx_cursor);
for(int c = 0; c < size; ++c)
cursors.emplace_back(clang_Cursor_getArgument(cx_cursor, c));
return cursors;
}
std::vector<clangmm::Cursor> clangmm::Cursor::get_all_overridden_cursors() const {
std::vector<Cursor> result;
if(get_kind()!=Kind::CXXMethod)
if(get_kind() != Kind::CXXMethod)
return result;
class Recursive {
public:
static void overridden(std::vector<Cursor> &result, const Cursor &cursor, int depth) {
if(depth>0)
if(depth > 0)
result.emplace_back(cursor);
CXCursor *cursors;
unsigned size;
clang_getOverriddenCursors(cursor.cx_cursor, &cursors, &size);
for(unsigned c=0;c<size;++c)
overridden(result, cursors[c], depth+1);
for(unsigned c = 0; c < size; ++c)
overridden(result, cursors[c], depth + 1);
clang_disposeOverriddenCursors(cursors);
}
};
@ -203,7 +200,7 @@ clangmm::Cursor::operator bool() const {
return !clang_Cursor_isNull(cx_cursor);
}
bool clangmm::Cursor::operator==(const Cursor& rhs) const {
bool clangmm::Cursor::operator==(const Cursor &rhs) const {
return clang_equalCursors(cx_cursor, rhs.cx_cursor);
}
@ -212,37 +209,37 @@ unsigned clangmm::Cursor::hash() const {
}
bool clangmm::Cursor::is_valid_kind() const {
auto referenced=clang_getCursorReferenced(cx_cursor);
auto referenced = clang_getCursorReferenced(cx_cursor);
if(clang_Cursor_isNull(referenced))
return false;
auto kind=get_kind();
return kind>Kind::UnexposedDecl && (kind<Kind::FirstInvalid || kind>Kind::LastInvalid);
auto kind = get_kind();
return kind > Kind::UnexposedDecl && (kind < Kind::FirstInvalid || kind > Kind::LastInvalid);
}
std::string clangmm::Cursor::get_type_description() const {
std::string spelling;
auto referenced=clang_getCursorReferenced(cx_cursor);
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+" &";
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+" &";
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;
}
@ -257,9 +254,9 @@ std::string clangmm::Cursor::get_type_description() const {
std::string clangmm::Cursor::get_brief_comments() const {
std::string comment_string;
auto referenced=get_referenced();
auto referenced = get_referenced();
if(referenced) {
comment_string=to_string(clang_Cursor_getBriefCommentText(referenced.cx_cursor));
comment_string = to_string(clang_Cursor_getBriefCommentText(referenced.cx_cursor));
}
return comment_string;
}

14
src/cursor.h

@ -1,11 +1,11 @@
#ifndef CURSOR_H_
#define CURSOR_H_
#include <clang-c/Index.h>
#include "source_location.h"
#include "source_range.h"
#include <clang-c/Index.h>
#include <string>
#include <vector>
#include <unordered_set>
#include <vector>
namespace clangmm {
class Cursor {
@ -183,12 +183,12 @@ namespace clangmm {
std::string get_spelling() const;
Type get_result() const;
Cursor get_cursor() const;
bool operator==(const Cursor::Type& rhs) const;
bool operator==(const Cursor::Type &rhs) const;
CXType cx_type;
};
Cursor() { cx_cursor=clang_getNullCursor(); }
Cursor() { cx_cursor = clang_getNullCursor(); }
Cursor(const CXCursor &cx_cursor) : cx_cursor(cx_cursor) {}
Kind get_kind() const;
std::string get_kind_spelling() const;
@ -212,7 +212,7 @@ namespace clangmm {
std::vector<Cursor> get_arguments() const;
std::vector<Cursor> get_all_overridden_cursors() const;
operator bool() const;
bool operator==(const Cursor& rhs) const;
bool operator==(const Cursor &rhs) const;
unsigned hash() const;
bool is_valid_kind() const;
@ -226,5 +226,5 @@ namespace clangmm {
CXCursor cx_cursor;
};
} // namespace clangmm
#endif // CURSOR_H_
} // namespace clangmm
#endif // CURSOR_H_

22
src/diagnostic.cc

@ -3,22 +3,22 @@
#include "tokens.h"
#include "utility.h"
clangmm::Diagnostic::Diagnostic(CXTranslationUnit& cx_tu, CXDiagnostic& cx_diagnostic) {
severity=static_cast<Severity>(clang_getDiagnosticSeverity(cx_diagnostic));
spelling=to_string(clang_getDiagnosticSpelling(cx_diagnostic));
clangmm::Diagnostic::Diagnostic(CXTranslationUnit &cx_tu, CXDiagnostic &cx_diagnostic) {
severity = static_cast<Severity>(clang_getDiagnosticSeverity(cx_diagnostic));
spelling = to_string(clang_getDiagnosticSpelling(cx_diagnostic));
SourceLocation location(clang_getDiagnosticLocation(cx_diagnostic));
path=location.get_path();
auto offset=location.get_offset();
auto corrected_location=SourceLocation(cx_tu, path.c_str(), offset.line, offset.index); // to avoid getting macro tokens
path = location.get_path();
auto offset = location.get_offset();
auto corrected_location = SourceLocation(cx_tu, path.c_str(), offset.line, offset.index); // to avoid getting macro tokens
Tokens tokens(cx_tu, SourceRange(corrected_location, corrected_location), false);
if(tokens.size()==1)
offsets={offset, tokens.begin()->get_source_range().get_offsets().second};
if(tokens.size() == 1)
offsets = {offset, tokens.begin()->get_source_range().get_offsets().second};
unsigned num_fix_its=clang_getDiagnosticNumFixIts(cx_diagnostic);
for(unsigned c=0;c<num_fix_its;c++) {
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));
auto source = to_string(clang_getDiagnosticFixIt(cx_diagnostic, c, &fix_it_range));
fix_its.emplace_back(source, SourceRange(fix_it_range).get_offsets());
}
}

15
src/diagnostic.h

@ -1,14 +1,15 @@
#ifndef DIAGNOSTIC_H_
#define DIAGNOSTIC_H_
#include "source_range.h"
#include <clang-c/Index.h>
#include <string>
#include <vector>
#include <clang-c/Index.h>
#include "source_range.h"
namespace clangmm {
class Diagnostic {
friend class TranslationUnit;
Diagnostic(CXTranslationUnit& cx_tu, CXDiagnostic& cx_diagnostic);
Diagnostic(CXTranslationUnit &cx_tu, CXDiagnostic &cx_diagnostic);
public:
enum class Severity {
Ignored = 0,
@ -20,8 +21,8 @@ namespace clangmm {
class FixIt {
public:
FixIt(const std::string &source, const std::pair<clangmm::Offset, clangmm::Offset> &offsets):
source(source), offsets(offsets) {}
FixIt(const std::string &source, const std::pair<clangmm::Offset, clangmm::Offset> &offsets)
: source(source), offsets(offsets) {}
std::string source;
std::pair<clangmm::Offset, clangmm::Offset> offsets;
};
@ -32,6 +33,6 @@ namespace clangmm {
std::pair<clangmm::Offset, clangmm::Offset> offsets;
std::vector<FixIt> fix_its;
};
}
} // namespace clangmm
#endif // DIAGNOSTIC_H_
#endif // DIAGNOSTIC_H_

4
src/index.h

@ -9,5 +9,5 @@ namespace clangmm {
~Index();
CXIndex cx_index;
};
} // namespace clangmm
#endif // INDEX_H_
} // namespace clangmm
#endif // INDEX_H_

9
src/source_location.cc

@ -25,15 +25,14 @@ clangmm::Offset clangmm::SourceLocation::get_offset() const {
return {line, index};
}
void clangmm::SourceLocation::get_data(std::string* path, unsigned *line, unsigned *column, unsigned *offset) const {
if(path==nullptr)
void clangmm::SourceLocation::get_data(std::string *path, unsigned *line, unsigned *column, unsigned *offset) const {
if(path == nullptr)
clang_getExpansionLocation(cx_location, NULL, line, column, offset);
else {
CXFile file;
clang_getExpansionLocation(cx_location, &file, line, column, offset);
if (file!=NULL) {
*path=to_string(clang_getFileName(file));
if(file != NULL) {
*path = to_string(clang_getFileName(file));
}
}
}

23
src/source_location.h

@ -1,18 +1,18 @@
#ifndef SOURCELOCATION_H_
#define SOURCELOCATION_H_
#include <clang-c/Index.h>
#include <string>
#include <ostream>
#include <string>
namespace clangmm {
class Offset {
public:
bool operator==(const Offset &o) const {return line==o.line && index==o.index;}
bool operator!=(const Offset &o) const {return !(*this==o);}
bool operator<(const Offset &o) const {return line<o.line || (line==o.line && index<o.index);}
bool operator>(const Offset &o) const {return o < *this;}
bool operator<=(const Offset &o) const {return (*this == o) || (*this < o);}
bool operator>=(const Offset &o) const {return (*this == o) || (*this > o);}
bool operator==(const Offset &o) const { return line == o.line && index == o.index; }
bool operator!=(const Offset &o) const { return !(*this == o); }
bool operator<(const Offset &o) const { return line < o.line || (line == o.line && index < o.index); }
bool operator>(const Offset &o) const { return o < *this; }
bool operator<=(const Offset &o) const { return (*this == o) || (*this < o); }
bool operator>=(const Offset &o) const { return (*this == o) || (*this > o); }
unsigned line;
unsigned index; //byte index in line (not char number)
};
@ -22,15 +22,16 @@ namespace clangmm {
friend class Diagnostic;
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) {}
SourceLocation(const CXSourceLocation &cx_location) : cx_location(cx_location) {}
public:
std::string get_path() const;
clangmm::Offset get_offset() const;
friend std::ostream &operator<<(std::ostream &os, const SourceLocation &location) {
auto offset=location.get_offset();
auto offset = location.get_offset();
os << location.get_path() << ':' << offset.line << ':' << offset.index;
return os;
}
@ -41,5 +42,5 @@ namespace clangmm {
void get_data(std::string *path, unsigned *line, unsigned *column, unsigned *offset) const;
};
} // namespace clangmm
#endif // SOURCELOCATION_H_
} // namespace clangmm
#endif // SOURCELOCATION_H_

8
src/source_range.h

@ -1,14 +1,14 @@
#ifndef SOURCERANGE_H_
#define SOURCERANGE_H_
#include <clang-c/Index.h>
#include "source_location.h"
#include <clang-c/Index.h>
#include <string>
#include <utility>
namespace clangmm {
class SourceRange {
public:
SourceRange(const CXSourceRange& cx_range) : cx_range(cx_range) {}
SourceRange(const CXSourceRange &cx_range) : cx_range(cx_range) {}
SourceRange(const SourceLocation &start, const SourceLocation &end);
SourceLocation get_start() const;
SourceLocation get_end() const;
@ -21,5 +21,5 @@ namespace clangmm {
CXSourceRange cx_range;
};
} // namespace clangmm
#endif // SOURCERANGE_H_
} // namespace clangmm
#endif // SOURCERANGE_H_

20
src/token.cc

@ -25,20 +25,20 @@ clangmm::Token::Kind clangmm::Token::get_kind() const {
}
bool clangmm::Token::is_identifier() const {
auto token_kind=get_kind();
auto cursor=get_cursor();
if(token_kind==clangmm::Token::Kind::Identifier && cursor.is_valid_kind())
auto token_kind = get_kind();
auto cursor = get_cursor();
if(token_kind == clangmm::Token::Kind::Identifier && cursor.is_valid_kind())
return true;
else if(token_kind==clangmm::Token::Kind::Keyword && cursor.is_valid_kind()) {
auto spelling=get_spelling();
if(spelling=="operator" || (spelling=="bool" && get_cursor().get_spelling()=="operator bool"))
else if(token_kind == clangmm::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==clangmm::Token::Kind::Punctuation && cursor.is_valid_kind()) {
auto referenced=cursor.get_referenced();
else if(token_kind == clangmm::Token::Kind::Punctuation && cursor.is_valid_kind()) {
auto referenced = cursor.get_referenced();
if(referenced) {
auto referenced_kind=referenced.get_kind();
if(referenced_kind==Cursor::Kind::FunctionDecl || referenced_kind==Cursor::Kind::CXXMethod || referenced_kind==Cursor::Kind::Constructor)
auto referenced_kind = referenced.get_kind();
if(referenced_kind == Cursor::Kind::FunctionDecl || referenced_kind == Cursor::Kind::CXXMethod || referenced_kind == Cursor::Kind::Constructor)
return true;
}
}

21
src/token.h

@ -1,14 +1,15 @@
#ifndef TOKEN_H_
#define TOKEN_H_
#include <clang-c/Index.h>
#include "cursor.h"
#include "source_location.h"
#include "source_range.h"
#include "cursor.h"
#include <clang-c/Index.h>
#include <string>
namespace clangmm {
class Token {
friend class Tokens;
public:
enum Kind {
Punctuation,
@ -17,15 +18,17 @@ namespace clangmm {
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) {}
Token(CXTranslationUnit &cx_tu, CXToken &cx_token, CXCursor &cx_cursor)
: cx_tu(cx_tu), cx_token(cx_token), cx_cursor(cx_cursor) {}
public:
Kind get_kind() const;
std::string get_spelling() const;
SourceLocation get_source_location() const;
SourceRange get_source_range() const;
clangmm::Cursor get_cursor() const {return clangmm::Cursor(cx_cursor);}
clangmm::Cursor get_cursor() const { return clangmm::Cursor(cx_cursor); }
bool is_identifier() const;
@ -35,8 +38,8 @@ namespace clangmm {
}
CXTranslationUnit &cx_tu;
CXToken& cx_token;
CXCursor& cx_cursor;
CXToken &cx_token;
CXCursor &cx_cursor;
};
} // namespace clangmm
#endif // TOKEN_H_
} // namespace clangmm
#endif // TOKEN_H_

70
src/tokens.cc

@ -1,39 +1,39 @@
#include "tokens.h"
#include "utility.h"
#include <unordered_set>
#include <cstring>
#include <map>
#include <unordered_set>
clangmm::Tokens::Tokens(CXTranslationUnit &cx_tu, const SourceRange &range, bool annotate_tokens): cx_tu(cx_tu) {
clangmm::Tokens::Tokens(CXTranslationUnit &cx_tu, const SourceRange &range, bool annotate_tokens) : cx_tu(cx_tu) {
unsigned num_tokens;
clang_tokenize(cx_tu, range.cx_range, &cx_tokens, &num_tokens);
if(!annotate_tokens) {
cx_cursors=std::unique_ptr<CXCursor[]>(new CXCursor[num_tokens]);
for (unsigned i = 0; i < num_tokens; i++) {
cx_cursors[i]=clang_getNullCursor();
cx_cursors = std::unique_ptr<CXCursor[]>(new CXCursor[num_tokens]);
for(unsigned i = 0; i < num_tokens; i++) {
cx_cursors[i] = clang_getNullCursor();
emplace_back(Token(cx_tu, cx_tokens[i], cx_cursors[i]));
}
return;
}
cx_cursors=std::unique_ptr<CXCursor[]>(new CXCursor[num_tokens]); // To avoid allocation with initialization
cx_cursors = std::unique_ptr<CXCursor[]>(new CXCursor[num_tokens]); // To avoid allocation with initialization
clang_annotateTokens(cx_tu, cx_tokens, num_tokens, cx_cursors.get());
bool tu_cursors=SourceRange(clang_getCursorExtent(clang_getTranslationUnitCursor(cx_tu))).get_start().get_path()==range.get_start().get_path();
bool tu_cursors = SourceRange(clang_getCursorExtent(clang_getTranslationUnitCursor(cx_tu))).get_start().get_path() == range.get_start().get_path();
std::map<size_t, Offset> invalid_tokens;
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;
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;
}
// Corrects: when getting tokens from a header, FieldDecl tokens are getting ClassDecl or StructDecl cursors
else if(!tu_cursors && (cx_cursors[i].kind==CXCursor_ClassDecl || cx_cursors[i].kind==CXCursor_StructDecl)) {
else if(!tu_cursors && (cx_cursors[i].kind == CXCursor_ClassDecl || cx_cursors[i].kind == CXCursor_StructDecl)) {
Token token(cx_tu, cx_tokens[i], cx_cursors[i]);
auto cursor=token.get_cursor();
auto token_offsets=token.get_source_range().get_offsets();
if(token_offsets.second!=cursor.get_source_range().get_offsets().second && token_offsets.first!=cursor.get_source_location().get_offset() && token.is_identifier())
auto cursor = token.get_cursor();
auto token_offsets = token.get_source_range().get_offsets();
if(token_offsets.second != cursor.get_source_range().get_offsets().second && token_offsets.first != cursor.get_source_location().get_offset() && token.is_identifier())
invalid_tokens.emplace(i, token_offsets.first);
}
@ -50,23 +50,23 @@ clangmm::Tokens::Tokens(CXTranslationUnit &cx_tu, const SourceRange &range, bool
VisitorData data{this, range.get_start().get_path(), invalid_tokens, {}};
auto translation_unit_cursor = clang_getTranslationUnitCursor(cx_tu);
clang_visitChildren(translation_unit_cursor, [](CXCursor cx_cursor, CXCursor cx_parent, CXClientData data_) {
auto data=static_cast<VisitorData*>(data_);
auto data = static_cast<VisitorData *>(data_);
Cursor cursor(cx_cursor);
if(cursor.get_source_location().get_path()==data->path)
if(cursor.get_source_location().get_path() == data->path)
data->cursors.emplace_back(cursor);
return CXChildVisit_Continue;
}, &data);
for(auto &cursor: data.cursors) {
for(auto &cursor : data.cursors) {
clang_visitChildren(cursor.cx_cursor, [](CXCursor cx_cursor, CXCursor cx_parent, CXClientData data_) {
auto data=static_cast<VisitorData*>(data_);
if(clang_getCursorKind(cx_cursor)==CXCursor_FieldDecl) {
auto data = static_cast<VisitorData *>(data_);
if(clang_getCursorKind(cx_cursor) == CXCursor_FieldDecl) {
Cursor cursor(cx_cursor);
auto clang_offset=cursor.get_source_location().get_offset();
for(auto it=data->invalid_tokens.begin();it!=data->invalid_tokens.end();) {
if(it->second==clang_offset) {
(*data->tokens)[it->first].cx_cursor=cursor.cx_cursor;
it=data->invalid_tokens.erase(it);
auto clang_offset = cursor.get_source_location().get_offset();
for(auto it = data->invalid_tokens.begin(); it != data->invalid_tokens.end();) {
if(it->second == clang_offset) {
(*data->tokens)[it->first].cx_cursor = cursor.cx_cursor;
it = data->invalid_tokens.erase(it);
if(data->invalid_tokens.empty())
return CXChildVisit_Break;
break;
@ -88,21 +88,21 @@ clangmm::Tokens::~Tokens() {
}
//This works across TranslationUnits. Similar tokens defined as tokens with equal canonical cursors.
std::vector<std::pair<clangmm::Offset, clangmm::Offset> > clangmm::Tokens::get_similar_token_offsets(Cursor::Kind kind, const std::string &spelling,
const std::unordered_set<std::string> &usrs) {
std::vector<std::pair<Offset, Offset> > offsets;
for(auto &token: *this) {
std::vector<std::pair<clangmm::Offset, clangmm::Offset>> clangmm::Tokens::get_similar_token_offsets(Cursor::Kind kind, const std::string &spelling,
const std::unordered_set<std::string> &usrs) {
std::vector<std::pair<Offset, Offset>> offsets;
for(auto &token : *this) {
if(token.is_identifier()) {
auto referenced=token.get_cursor().get_referenced();
auto referenced = token.get_cursor().get_referenced();
if(referenced && Cursor::is_similar_kind(referenced.get_kind(), kind)) {
bool equal_spelling=false;
auto cx_string=clang_getTokenSpelling(cx_tu, token.cx_token);
bool equal_spelling = false;
auto cx_string = clang_getTokenSpelling(cx_tu, token.cx_token);
if(cx_string.data)
equal_spelling=std::strcmp(static_cast<const char*>(cx_string.data), spelling.c_str())==0;
equal_spelling = std::strcmp(static_cast<const char *>(cx_string.data), spelling.c_str()) == 0;
clang_disposeString(cx_string);
if(equal_spelling) {
auto referenced_usrs=referenced.get_all_usr_extended();
for(auto &usr: referenced_usrs) {
auto referenced_usrs = referenced.get_all_usr_extended();
for(auto &usr : referenced_usrs) {
if(usrs.count(usr)) {
offsets.emplace_back(token.get_source_range().get_offsets());
break;

18
src/tokens.h

@ -1,25 +1,27 @@
#ifndef TOKENS_H_
#define TOKENS_H_
#include <clang-c/Index.h>
#include "source_range.h"
#include "token.h"
#include <clang-c/Index.h>
#include <memory>
#include <unordered_set>
#include <vector>
#include <memory>
namespace clangmm {
class Tokens : public std::vector<clangmm::Token> {
friend class TranslationUnit;
friend class Diagnostic;
Tokens(CXTranslationUnit &cx_tu, const SourceRange &range, bool annotate_tokens=true);
Tokens(CXTranslationUnit &cx_tu, const SourceRange &range, bool annotate_tokens = true);
public:
~Tokens();
std::vector<std::pair<clangmm::Offset, clangmm::Offset> > get_similar_token_offsets(Cursor::Kind kind, const std::string &spelling,
const std::unordered_set<std::string> &usrs);
std::vector<std::pair<clangmm::Offset, clangmm::Offset>> get_similar_token_offsets(Cursor::Kind kind, const std::string &spelling,
const std::unordered_set<std::string> &usrs);
private:
CXToken *cx_tokens;
std::unique_ptr<CXCursor[]> cx_cursors;
CXTranslationUnit& cx_tu;
CXTranslationUnit &cx_tu;
};
} // namespace clangmm
#endif // TOKENS_H_
} // namespace clangmm
#endif // TOKENS_H_

46
src/translation_unit.cc

@ -5,21 +5,21 @@
#include <fstream>
#include <sstream>
#include <iostream> //TODO: remove
#include <iostream> //TODO: remove
using namespace std; //TODO: remove
clangmm::TranslationUnit::TranslationUnit(Index &index, const std::string &file_path,
const std::vector<std::string> &command_line_args,
const std::string &buffer, int flags) {
std::vector<const char*> args;
for(auto &a: command_line_args) {
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();
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);
@ -28,8 +28,8 @@ clangmm::TranslationUnit::TranslationUnit(Index &index, const std::string &file_
clangmm::TranslationUnit::TranslationUnit(Index &index, const std::string &file_path,
const std::vector<std::string> &command_line_args,
int flags) {
std::vector<const char*> args;
for(auto &a: command_line_args) {
std::vector<const char *> args;
for(auto &a : command_line_args) {
args.push_back(a.c_str());
}
@ -43,17 +43,17 @@ clangmm::TranslationUnit::~TranslationUnit() {
void clangmm::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, int flags) {
const std::map<std::string, std::string> &buffers, int flags) {
std::vector<CXUnsavedFile> files;
for (auto &buffer : buffers) {
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) {
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(),
@ -63,19 +63,19 @@ void clangmm::TranslationUnit::parse(Index &index, const std::string &file_path,
int clangmm::TranslationUnit::reparse(const std::string &buffer, int flags) {
CXUnsavedFile files[1];
auto file_path=to_string(clang_getTranslationUnitSpelling(cx_tu));
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();
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);
}
int clangmm::TranslationUnit::DefaultFlags() {
int 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;
int 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;
}
@ -88,8 +88,8 @@ clangmm::CodeCompleteResults clangmm::TranslationUnit::get_code_completions(cons
std::vector<clangmm::Diagnostic> clangmm::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);
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);
}
@ -109,7 +109,7 @@ std::unique_ptr<clangmm::Tokens> clangmm::TranslationUnit::get_tokens(const std:
}
std::unique_ptr<clangmm::Tokens> clangmm::TranslationUnit::get_tokens(unsigned start_offset, unsigned end_offset) {
auto path=clangmm::to_string(clang_getTranslationUnitSpelling(cx_tu));
auto path = clangmm::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);
@ -118,7 +118,7 @@ std::unique_ptr<clangmm::Tokens> clangmm::TranslationUnit::get_tokens(unsigned s
std::unique_ptr<clangmm::Tokens> clangmm::TranslationUnit::get_tokens(unsigned start_line, unsigned start_column,
unsigned end_line, unsigned end_column) {
auto path=to_string(clang_getTranslationUnitSpelling(cx_tu));
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);

27
src/translation_unit.h

@ -1,15 +1,15 @@
#ifndef TRANSLATIONUNIT_H_
#define TRANSLATIONUNIT_H_
#include "code_complete_results.h"
#include "cursor.h"
#include "diagnostic.h"
#include "index.h"
#include "tokens.h"
#include <clang-c/Index.h>
#include <string>
#include <vector>
#include <map>
#include <memory>
#include "index.h"
#include "diagnostic.h"
#include "tokens.h"
#include "code_complete_results.h"
#include "cursor.h"
#include <string>
#include <vector>
namespace clangmm {
class TranslationUnit {
@ -17,13 +17,13 @@ namespace clangmm {
TranslationUnit(Index &index, const std::string &file_path,
const std::vector<std::string> &command_line_args,
const std::string &buffer,
int flags=DefaultFlags());
int flags = DefaultFlags());
TranslationUnit(Index &index, const std::string &file_path,
const std::vector<std::string> &command_line_args,
int flags=DefaultFlags());
int flags = DefaultFlags());
~TranslationUnit();
int reparse(const std::string &buffer, int flags=DefaultFlags());
int reparse(const std::string &buffer, int flags = DefaultFlags());
static int DefaultFlags();
@ -31,7 +31,7 @@ namespace clangmm {
const std::string &file_path,
const std::vector<std::string> &command_line_args,
const std::map<std::string, std::string> &buffers,
int flags=DefaultFlags());
int flags = DefaultFlags());
CodeCompleteResults get_code_completions(const std::string &buffer,
unsigned line_number, unsigned column);
@ -50,6 +50,5 @@ namespace clangmm {
CXTranslationUnit cx_tu;
};
} // namespace clangmm
#endif // TRANSLATIONUNIT_H_
} // namespace clangmm
#endif // TRANSLATIONUNIT_H_

87
src/utility.cc

@ -3,22 +3,22 @@
std::string clangmm::to_string(CXString cx_string) {
std::string string;
if(cx_string.data!=NULL) {
string=clang_getCString(cx_string);
if(cx_string.data != NULL) {
string = clang_getCString(cx_string);
clang_disposeString(cx_string);
}
return string;
}
clangmm::String::String(const CXString &cx_string) : cx_string(cx_string) {
if(cx_string.data!=NULL)
c_str=clang_getCString(cx_string);
if(cx_string.data != NULL)
c_str = clang_getCString(cx_string);
else
c_str="";
c_str = "";
}
clangmm::String::~String() {
if(cx_string.data!=NULL)
if(cx_string.data != NULL)
clang_disposeString(cx_string);
}
@ -28,76 +28,77 @@ void clangmm::remove_include_guard(std::string &buffer) {
static std::regex define_regex("^[ \t]*#[ \t]*define[ \t]+([A-Za-z0-9_]+).*$");
static std::regex endif_regex("^[ \t]*#[ \t]*endif.*$");
std::vector<std::pair<size_t, size_t>> ranges;
bool found_ifndef=false, found_define=false;
bool line_comment=false, multiline_comment=false;
size_t start_of_line=0;
bool found_ifndef = false, found_define = false;
bool line_comment = false, multiline_comment = false;
size_t start_of_line = 0;
std::string line;
std::string preprocessor_identifier;
for(size_t c=0;c<buffer.size();++c) {
if(!line_comment && !multiline_comment && buffer[c]=='/' && c+1<buffer.size() && (buffer[c+1]=='/' || buffer[c+1]=='*')) {
if(buffer[c+1]=='/')
line_comment=true;
for(size_t c = 0; c < buffer.size(); ++c) {
if(!line_comment && !multiline_comment && buffer[c] == '/' && c + 1 < buffer.size() && (buffer[c + 1] == '/' || buffer[c + 1] == '*')) {
if(buffer[c + 1] == '/')
line_comment = true;
else
multiline_comment=true;
multiline_comment = true;
++c;
}
else if(multiline_comment && buffer[c]=='*' && c+1<buffer.size() && buffer[c+1]=='/') {
multiline_comment=false;
else if(multiline_comment && buffer[c] == '*' && c + 1 < buffer.size() && buffer[c + 1] == '/') {
multiline_comment = false;
++c;
}
else if(buffer[c]=='\n') {
bool empty_line=true;
for(auto &chr: line) {
if(chr!=' ' && chr!='\t') {
empty_line=false;
else if(buffer[c] == '\n') {
bool empty_line = true;
for(auto &chr : line) {
if(chr != ' ' && chr != '\t') {
empty_line = false;
break;
}
}
std::smatch sm;
if(empty_line) {}
if(empty_line) {
}
else if(!found_ifndef && (std::regex_match(line, sm, ifndef_regex1) || std::regex_match(line, sm, ifndef_regex2))) {
found_ifndef=true;
found_ifndef = true;
ranges.emplace_back(start_of_line, c);
preprocessor_identifier=sm[1].str();
preprocessor_identifier = sm[1].str();
}
else if(found_ifndef && std::regex_match(line, sm, define_regex)) {
found_define=true;
found_define = true;
ranges.emplace_back(start_of_line, c);
if(preprocessor_identifier!=sm[1].str())
if(preprocessor_identifier != sm[1].str())
return;
break;
}
else
return;
line_comment=false;
line_comment = false;
line.clear();
if(c+1<buffer.size())
start_of_line=c+1;
if(c + 1 < buffer.size())
start_of_line = c + 1;
else
return;
}
else if(!line_comment && !multiline_comment && buffer[c]!='\r')
line+=buffer[c];
else if(!line_comment && !multiline_comment && buffer[c] != '\r')
line += buffer[c];
}
if(found_ifndef && found_define) {
size_t last_char_pos=std::string::npos;
for(size_t c=buffer.size()-1;c!=std::string::npos;--c) {
if(last_char_pos==std::string::npos) {
if(buffer[c]!=' ' && buffer[c]!='\t' && buffer[c]!='\r' && buffer[c]!='\n')
last_char_pos=c;
size_t last_char_pos = std::string::npos;
for(size_t c = buffer.size() - 1; c != std::string::npos; --c) {
if(last_char_pos == std::string::npos) {
if(buffer[c] != ' ' && buffer[c] != '\t' && buffer[c] != '\r' && buffer[c] != '\n')
last_char_pos = c;
}
else {
if(buffer[c]=='\n' && c+1<buffer.size()) {
auto line=buffer.substr(c+1, last_char_pos-c);
if(buffer[c] == '\n' && c + 1 < buffer.size()) {
auto line = buffer.substr(c + 1, last_char_pos - c);
std::smatch sm;
if(std::regex_match(line, sm, endif_regex)) {
ranges.emplace_back(c+1, last_char_pos+1);
for(auto &range: ranges) {
for(size_t c=range.first;c<range.second;++c) {
if(buffer[c]!='\r')
buffer[c]=' ';
ranges.emplace_back(c + 1, last_char_pos + 1);
for(auto &range : ranges) {
for(size_t c = range.first; c < range.second; ++c) {
if(buffer[c] != '\r')
buffer[c] = ' ';
}
}
return;

4
src/utility.h

@ -15,6 +15,6 @@ namespace clangmm {
};
void remove_include_guard(std::string &buffer);
}
} // namespace clangmm
#endif // UTILITY_H_
#endif // UTILITY_H_

36
tests/code_complete_results_test.cc

@ -1,39 +1,39 @@
#include "clangmm.h"
#include <string>
#include <cassert>
#include <regex>
#include <string>
int main() {
std::string tests_path=LIBCLANGMM_TESTS_PATH;
std::string path(tests_path+"/case/main.cpp");
std::string tests_path = LIBCLANGMM_TESTS_PATH;
std::string path(tests_path + "/case/main.cpp");
std::vector<std::string> arguments;
auto clang_version_string=clangmm::to_string(clang_getClangVersion());
auto clang_version_string = clangmm::to_string(clang_getClangVersion());
const static std::regex clang_version_regex("^[A-Za-z ]+([0-9.]+).*$");
std::smatch sm;
if(std::regex_match(clang_version_string, sm, clang_version_regex)) {
auto clang_version=sm[1].str();
arguments.emplace_back("-I/usr/lib/clang/"+clang_version+"/include");
arguments.emplace_back("-I/usr/lib64/clang/"+clang_version+"/include"); // For Fedora
auto clang_version = sm[1].str();
arguments.emplace_back("-I/usr/lib/clang/" + clang_version + "/include");
arguments.emplace_back("-I/usr/lib64/clang/" + clang_version + "/include"); // For Fedora
}
clangmm::Index index(0, 0);
clangmm::TranslationUnit tu(index, path, arguments);
std::string buffer="#include <string>\n"
"int main(int argc, char *argv[]) {\n"
"std::string str;\n"
"str.\n"
"return 0\n"
"}";
std::string buffer = "#include <string>\n"
"int main(int argc, char *argv[]) {\n"
"std::string str;\n"
"str.\n"
"return 0\n"
"}";
tu.reparse(buffer);
auto results=tu.get_code_completions(buffer, 4, 5);
auto results = tu.get_code_completions(buffer, 4, 5);
bool substr_found=false;
for(unsigned c=0;c<results.size();c++) {
if(results.get(c).get_chunks()[1].text=="substr") {
substr_found=true;
bool substr_found = false;
for(unsigned c = 0; c < results.size(); c++) {
if(results.get(c).get_chunks()[1].text == "substr") {
substr_found = true;
break;
}
}

32
tests/completion_string_test.cc

@ -1,7 +1,7 @@
#include "clangmm.h"
#include <string>
#include <cassert>
#include <regex>
#include <string>
int main() {
{
@ -12,35 +12,35 @@ int main() {
}
{
std::string tests_path=LIBCLANGMM_TESTS_PATH;
std::string path(tests_path+"/case/main.cpp");
std::string tests_path = LIBCLANGMM_TESTS_PATH;
std::string path(tests_path + "/case/main.cpp");
std::vector<std::string> arguments;
auto clang_version_string=clangmm::to_string(clang_getClangVersion());
auto clang_version_string = clangmm::to_string(clang_getClangVersion());
const static std::regex clang_version_regex("^[A-Za-z ]+([0-9.]+).*$");
std::smatch sm;
if(std::regex_match(clang_version_string, sm, clang_version_regex)) {
auto clang_version=sm[1].str();
arguments.emplace_back("-I/usr/lib/clang/"+clang_version+"/include");
arguments.emplace_back("-I/usr/lib64/clang/"+clang_version+"/include"); // For Fedora
auto clang_version = sm[1].str();
arguments.emplace_back("-I/usr/lib/clang/" + clang_version + "/include");
arguments.emplace_back("-I/usr/lib64/clang/" + clang_version + "/include"); // For Fedora
}
clangmm::Index index(0, 0);
clangmm::TranslationUnit tu(index, path, arguments);
std::string buffer="#include <string>\n"
"int main(int argc, char *argv[]) {\n"
"std::string str;\n"
"str.\n"
"return 0\n"
"}";
std::string buffer = "#include <string>\n"
"int main(int argc, char *argv[]) {\n"
"std::string str;\n"
"str.\n"
"return 0\n"
"}";
tu.reparse(buffer);
auto results=tu.get_code_completions(buffer, 4, 5);
auto results = tu.get_code_completions(buffer, 4, 5);
auto str = results.get(0);
assert(str.get_num_chunks()>0);
assert(str.get_chunks().size()>0);
assert(str.get_num_chunks() > 0);
assert(str.get_chunks().size() > 0);
}
}

16
tests/cursor_test.cc

@ -1,27 +1,27 @@
#include "clangmm.h"
#include <string>
#include <cassert>
#include <regex>
#include <string>
int main() {
std::string tests_path=LIBCLANGMM_TESTS_PATH;
std::string path(tests_path+"/case/main.cpp");
std::string tests_path = LIBCLANGMM_TESTS_PATH;
std::string path(tests_path + "/case/main.cpp");
clangmm::Index index(0, 0);
std::vector<std::string> arguments;
auto clang_version_string=clangmm::to_string(clang_getClangVersion());
auto clang_version_string = clangmm::to_string(clang_getClangVersion());
const static std::regex clang_version_regex("^[A-Za-z ]+([0-9.]+).*$");
std::smatch sm;
if(std::regex_match(clang_version_string, sm, clang_version_regex)) {
auto clang_version=sm[1].str();
arguments.emplace_back("-I/usr/lib/clang/"+clang_version+"/include");
arguments.emplace_back("-I/usr/lib64/clang/"+clang_version+"/include"); // For Fedora
auto clang_version = sm[1].str();
arguments.emplace_back("-I/usr/lib/clang/" + clang_version + "/include");
arguments.emplace_back("-I/usr/lib64/clang/" + clang_version + "/include"); // For Fedora
}
clangmm::TranslationUnit tu(index, path, arguments);
auto cursor=tu.get_cursor(path, 103);
auto cursor = tu.get_cursor(path, 103);
assert(cursor.get_kind() == clangmm::Cursor::Kind::ReturnStmt);
}

22
tests/diagnostics_test.cc

@ -1,31 +1,31 @@
#include "clangmm.h"
#include <iostream>
#include <fstream>
#include <cassert>
#include <fstream>
#include <iostream>
#include <regex>
using namespace std;
int main() {
std::string tests_path=LIBCLANGMM_TESTS_PATH;
std::string path(tests_path+"/case/main_error.cpp");
std::string tests_path = LIBCLANGMM_TESTS_PATH;
std::string path(tests_path + "/case/main_error.cpp");
clangmm::Index index(0, 0);
std::vector<std::string> arguments;
auto clang_version_string=clangmm::to_string(clang_getClangVersion());
auto clang_version_string = clangmm::to_string(clang_getClangVersion());
const static std::regex clang_version_regex("^[A-Za-z ]+([0-9.]+).*$");
std::smatch sm;
if(std::regex_match(clang_version_string, sm, clang_version_regex)) {
auto clang_version=sm[1].str();
arguments.emplace_back("-I/usr/lib/clang/"+clang_version+"/include");
arguments.emplace_back("-I/usr/lib64/clang/"+clang_version+"/include"); // For Fedora
auto clang_version = sm[1].str();
arguments.emplace_back("-I/usr/lib/clang/" + clang_version + "/include");
arguments.emplace_back("-I/usr/lib64/clang/" + clang_version + "/include"); // For Fedora
}
clangmm::TranslationUnit tu(index, path, arguments);
auto diagnostics=tu.get_diagnostics();
assert(diagnostics.size()>0);
auto diagnostics = tu.get_diagnostics();
assert(diagnostics.size() > 0);
assert(!diagnostics[0].spelling.empty());
assert(diagnostics[0].severity==clangmm::Diagnostic::Severity::Error);
assert(diagnostics[0].severity == clangmm::Diagnostic::Severity::Error);
}

10
tests/source_location_test.cc

@ -1,17 +1,17 @@
#include "clangmm.h"
#include <string>
#include <cassert>
#include <string>
int main() {
std::string tests_path=LIBCLANGMM_TESTS_PATH;
std::string path(tests_path+"/case/main.cpp");
std::string tests_path = LIBCLANGMM_TESTS_PATH;
std::string path(tests_path + "/case/main.cpp");
clangmm::Index index(0, 0);
clangmm::TranslationUnit tu(index, path, {});
auto tokens=tu.get_tokens(0, 113);
auto tokens = tu.get_tokens(0, 113);
auto offsets=(*tokens)[28].get_source_range().get_offsets();
auto offsets = (*tokens)[28].get_source_range().get_offsets();
assert(offsets.first.line == 6 && offsets.first.index == 3);
assert(offsets.second.line == 6 && offsets.second.index == 9);

8
tests/token_test.cc

@ -1,16 +1,16 @@
#include "clangmm.h"
#include <string>
#include <cassert>
#include <string>
int main() {
std::string tests_path=LIBCLANGMM_TESTS_PATH;
std::string path(tests_path+"/case/main.cpp");
std::string tests_path = LIBCLANGMM_TESTS_PATH;
std::string path(tests_path + "/case/main.cpp");
clangmm::Index index(0, 0);
clangmm::TranslationUnit tu(index, path, {});
auto tokens=tu.get_tokens(0, 113);
auto tokens = tu.get_tokens(0, 113);
assert(tokens->size() == 32);
assert((*tokens)[1].get_kind() == clangmm::Token::Kind::Identifier);

8
tests/translation_unit_test.cc

@ -1,11 +1,11 @@
#include "clangmm.h"
#include <string>
#include <map>
#include <cassert>
#include <map>
#include <string>
int main() {
std::string tests_path=LIBCLANGMM_TESTS_PATH;
std::string path(tests_path+"/case/main.cpp");
std::string tests_path = LIBCLANGMM_TESTS_PATH;
std::string path(tests_path + "/case/main.cpp");
clangmm::Index index(0, 0);

Loading…
Cancel
Save