From 4b24a69e47f313ae8a134a5b99ed7bd83a33a4fe Mon Sep 17 00:00:00 2001 From: eidheim Date: Fri, 18 Aug 2017 19:43:57 +0200 Subject: [PATCH] Optimization of Tokens::Tokens, and some minor cleanup --- src/SourceLocation.h | 5 ++-- src/SourceRange.cc | 14 +++++++-- src/SourceRange.h | 4 ++- src/Tokens.cc | 71 ++++++++++++++++++++++++++++---------------- 4 files changed, 62 insertions(+), 32 deletions(-) diff --git a/src/SourceLocation.h b/src/SourceLocation.h index 98b554d..10c9c21 100644 --- a/src/SourceLocation.h +++ b/src/SourceLocation.h @@ -6,8 +6,9 @@ namespace clangmm { class Offset { public: - bool operator==(const clangmm::Offset &o) const {return line==o.line && index==o.index;} - bool operator!=(const clangmm::Offset &o) const {return !(*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 clangmm::SourceRange::get_offsets() { - SourceLocation start(clang_getRangeStart(cx_range)), end(clang_getRangeEnd(cx_range)); - return {start.get_offset(), end.get_offset()}; +clangmm::SourceLocation clangmm::SourceRange::get_start() const { + return SourceLocation(clang_getRangeStart(cx_range)); +} + +clangmm::SourceLocation clangmm::SourceRange::get_end() const { + return SourceLocation(clang_getRangeEnd(cx_range)); +} + + +std::pair clangmm::SourceRange::get_offsets() const { + return {get_start().get_offset(), get_end().get_offset()}; } \ No newline at end of file diff --git a/src/SourceRange.h b/src/SourceRange.h index 9953c5d..cb8e90d 100644 --- a/src/SourceRange.h +++ b/src/SourceRange.h @@ -10,7 +10,9 @@ namespace clangmm { public: SourceRange(const CXSourceRange& cx_range) : cx_range(cx_range) {} SourceRange(SourceLocation &start, SourceLocation &end); - std::pair get_offsets(); + SourceLocation get_start() const; + SourceLocation get_end() const; + std::pair get_offsets() const; CXSourceRange cx_range; }; } // namespace clangmm diff --git a/src/Tokens.cc b/src/Tokens.cc index 1431e3f..b76ffa4 100644 --- a/src/Tokens.cc +++ b/src/Tokens.cc @@ -2,51 +2,70 @@ #include "Utility.h" #include #include +#include clangmm::Tokens::Tokens(CXTranslationUnit &cx_tu, const SourceRange &range): cx_tu(cx_tu) { unsigned num_tokens; clang_tokenize(cx_tu, range.cx_range, &cx_tokens, &num_tokens); cx_cursors=std::unique_ptr(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(); + std::map 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; } // Corrects: when getting tokens from a header, FieldDecl tokens are getting ClassDecl or StructDecl cursors - else if(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()) { - class VisitorData { - public: - std::string path; - bool found_path; - std::pair offsets; - CXCursor found_cursor; - }; - VisitorData data{token.get_source_location().get_path(), false, token_offsets, clang_getNullCursor()}; - 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(data_); + 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); + } + + emplace_back(Token(cx_tu, cx_tokens[i], cx_cursors[i])); + } + if(!tu_cursors && !invalid_tokens.empty()) { + class VisitorData { + public: + Tokens *tokens; + const std::string &path; + std::map &invalid_tokens; + std::vector cursors; + }; + 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(data_); + Cursor cursor(cx_cursor); + if(cursor.get_source_location().get_path()==data->path) + data->cursors.emplace_back(cursor); + return CXChildVisit_Continue; + }, &data); + + for(auto &cursor: data.cursors) { + clang_visitChildren(cursor.cx_cursor, [](CXCursor cx_cursor, CXCursor cx_parent, CXClientData data_) { + auto data=static_cast(data_); + if(clang_getCursorKind(cx_cursor)==CXCursor_FieldDecl) { Cursor cursor(cx_cursor); - if(data->found_path || cursor.get_source_location().get_path()==data->path) { - data->found_path=true; - if(cursor.get_source_range().get_offsets().second==data->offsets.second && cursor.get_source_location().get_offset()==data->offsets.first) { - data->found_cursor=cx_cursor; - return CXChildVisit_Break; + auto clang_offset=cursor.get_source_location().get_offset(); + for(auto it=data->invalid_tokens.begin();it!=data->invalid_tokens.end();++it) { + if(it->second==clang_offset) { + (*data->tokens)[it->first].cx_cursor=cursor.cx_cursor; + data->invalid_tokens.erase(it); + if(data->invalid_tokens.empty()) + return CXChildVisit_Break; + break; } - return CXChildVisit_Recurse; } - return CXChildVisit_Continue; - }, &data); - - if(!clang_Cursor_isNull(data.found_cursor)) - cx_cursors[i]=data.found_cursor; - } + } + return CXChildVisit_Recurse; + }, &data); } - emplace_back(Token(cx_tu, cx_tokens[i], cx_cursors[i])); } }