Browse Source

Improved libclang tooltips and navigation, most significantly support for operators.

merge-requests/365/head
eidheim 9 years ago
parent
commit
c0ca42ccf8
  1. 2
      libclangmm
  2. 14
      src/ctags.cc
  3. 2
      src/juci.cc
  4. 2
      src/meson.cc
  5. 208
      src/source_clang.cc

2
libclangmm

@ -1 +1 @@
Subproject commit e0e2293fa0162b2380d991647c002b54628a269a Subproject commit 1ef04246b8f77f823fc2ddb19b4562c7b6d8261b

14
src/ctags.cc

@ -58,6 +58,13 @@ Ctags::Location Ctags::get_location(const std::string &line, bool markup) {
std::smatch sm; std::smatch sm;
if(std::regex_match(line_fixed, sm, regex)) { if(std::regex_match(line_fixed, sm, regex)) {
location.symbol=sm[1].str(); location.symbol=sm[1].str();
//fix location.symbol for operators
if(9<location.symbol.size() && location.symbol[8]==' ' && location.symbol.compare(0, 8, "operator")==0) {
auto &chr=location.symbol[9];
if(!((chr>='a' && chr<='z') || (chr>='A' && chr<='Z') || (chr>='0' && chr<='9') || chr=='_'))
location.symbol.erase(8, 1);
}
location.file_path=sm[2].str(); location.file_path=sm[2].str();
location.source=sm[4].str(); location.source=sm[4].str();
try { try {
@ -76,11 +83,12 @@ Ctags::Location Ctags::get_location(const std::string &line, bool markup) {
if(markup) { if(markup) {
location.source=Glib::Markup::escape_text(location.source); location.source=Glib::Markup::escape_text(location.source);
auto symbol=Glib::Markup::escape_text(location.symbol);
pos=-1; pos=-1;
while((pos=location.source.find(location.symbol, pos+1))!=std::string::npos) { while((pos=location.source.find(symbol, pos+1))!=std::string::npos) {
location.source.insert(pos+location.symbol.size(), "</b>"); location.source.insert(pos+symbol.size(), "</b>");
location.source.insert(pos, "<b>"); location.source.insert(pos, "<b>");
pos+=7+location.symbol.size(); pos+=7+symbol.size();
} }
} }
} }

2
src/juci.cc

@ -75,7 +75,7 @@ void Application::on_activate() {
else { else {
std::string files_in_directory; std::string files_in_directory;
for(auto it=files.begin();it!=files.end();) { for(auto it=files.begin();it!=files.end();) {
if(it->first.generic_string().substr(0, directory.generic_string().size()+1)==directory.generic_string()+'/') { if(it->first.generic_string().compare(0, directory.generic_string().size()+1, directory.generic_string()+'/')==0) {
files_in_directory+=" "+it->first.string(); files_in_directory+=" "+it->first.string();
it=files.erase(it); it=files.erase(it);
} }

2
src/meson.cc

@ -98,7 +98,7 @@ boost::filesystem::path Meson::get_executable(const boost::filesystem::path &bui
if(!values.empty()) { if(!values.empty()) {
size_t pos; size_t pos;
if((pos=values[0].find("@"))!=std::string::npos) { if((pos=values[0].find("@"))!=std::string::npos) {
if(pos+1<values[0].size() && values[0].substr(pos+1, 3)=="exe") { if(pos+1<values[0].size() && values[0].compare(pos+1, 3, "exe")==0) {
auto executable=build_path/values[0].substr(0, pos); auto executable=build_path/values[0].substr(0, pos);
if(command_file==file_path) if(command_file==file_path)
return executable; return executable;

208
src/source_clang.cc

@ -483,97 +483,80 @@ void Source::ClangViewParse::show_type_tooltips(const Gdk::Rectangle &rectangle)
get_iter_location(iter, iter_rectangle); get_iter_location(iter, iter_rectangle);
if(iter.ends_line() && location_x>iter_rectangle.get_x()) if(iter.ends_line() && location_x>iter_rectangle.get_x())
return; return;
if(iter_rectangle.get_x()>location_x) {
if(!iter.starts_line()) {
if(!iter.backward_char())
return;
}
}
bool found_token=false;
if(!((*iter>='a' && *iter<='z') || (*iter>='A' && *iter<='Z') || (*iter>='0' && *iter<='9') || *iter=='_')) {
if(!iter.backward_char())
return;
}
while((*iter>='a' && *iter<='z') || (*iter>='A' && *iter<='Z') || (*iter>='0' && *iter<='9') || *iter=='_') {
if(!found_token)
found_token=true;
if(!iter.backward_char())
return;
}
if(found_token && iter.forward_char()) {
auto tokens=clang_tu->get_tokens(iter.get_line()+1, iter.get_line_index()+1,
iter.get_line()+1, iter.get_line_index()+1);
type_tooltips.clear(); auto line=static_cast<unsigned>(iter.get_line());
for(auto &token: *tokens) { auto index=static_cast<unsigned>(iter.get_line_index());
auto cursor=token.get_cursor(); type_tooltips.clear();
if(token.get_kind()==clang::Token::Kind::Identifier && cursor.has_type_description()) { for(size_t c=clang_tokens->size()-1;c!=static_cast<size_t>(-1);--c) {
if(token.get_cursor().get_kind()==clang::Cursor::Kind::CallExpr) //These cursors are buggy auto &token=(*clang_tokens)[c];
continue; if(token.is_identifier()) {
auto start=get_buffer()->get_iter_at_line_index(token.offsets.first.line-1, token.offsets.first.index-1); if(line==token.offsets.first.line-1 && index>=token.offsets.first.index-1 && index <=token.offsets.second.index-1) {
auto end=get_buffer()->get_iter_at_line_index(token.offsets.second.line-1, token.offsets.second.index-1); auto cursor=token.get_cursor();
auto create_tooltip_buffer=[this, &token]() { auto referenced=cursor.get_referenced();
auto tooltip_buffer=Gtk::TextBuffer::create(get_buffer()->get_tag_table()); if(referenced) {
tooltip_buffer->insert_with_tag(tooltip_buffer->get_insert()->get_iter(), "Type: "+token.get_cursor().get_type_description(), "def:note"); auto start=get_buffer()->get_iter_at_line_index(token.offsets.first.line-1, token.offsets.first.index-1);
auto brief_comment=token.get_cursor().get_brief_comments(); auto end=get_buffer()->get_iter_at_line_index(token.offsets.second.line-1, token.offsets.second.index-1);
if(brief_comment!="") auto create_tooltip_buffer=[this, &token]() {
tooltip_buffer->insert_with_tag(tooltip_buffer->get_insert()->get_iter(), "\n\n"+brief_comment, "def:note"); auto tooltip_buffer=Gtk::TextBuffer::create(get_buffer()->get_tag_table());
tooltip_buffer->insert_with_tag(tooltip_buffer->get_insert()->get_iter(), "Type: "+token.get_cursor().get_type_description(), "def:note");
auto brief_comment=token.get_cursor().get_brief_comments();
if(brief_comment!="")
tooltip_buffer->insert_with_tag(tooltip_buffer->get_insert()->get_iter(), "\n\n"+brief_comment, "def:note");
#ifdef JUCI_ENABLE_DEBUG #ifdef JUCI_ENABLE_DEBUG
if(Debug::LLDB::get().is_stopped()) { if(Debug::LLDB::get().is_stopped()) {
auto location=token.get_cursor().get_referenced().get_source_location(); auto location=token.get_cursor().get_referenced().get_source_location();
Glib::ustring value_type="Value"; Glib::ustring value_type="Value";
auto start=get_buffer()->get_iter_at_line_index(token.offsets.first.line-1, token.offsets.first.index-1); auto start=get_buffer()->get_iter_at_line_index(token.offsets.first.line-1, token.offsets.first.index-1);
auto end=get_buffer()->get_iter_at_line_index(token.offsets.second.line-1, token.offsets.second.index-1); auto end=get_buffer()->get_iter_at_line_index(token.offsets.second.line-1, token.offsets.second.index-1);
auto iter=start; auto iter=start;
while((*iter>='a' && *iter<='z') || (*iter>='A' && *iter<='Z') || (*iter>='0' && *iter<='9') || *iter=='_' || *iter=='.') { while((*iter>='a' && *iter<='z') || (*iter>='A' && *iter<='Z') || (*iter>='0' && *iter<='9') || *iter=='_' || *iter=='.') {
start=iter; start=iter;
if(!iter.backward_char()) if(!iter.backward_char())
break;
if(*iter=='>') {
if(!(iter.backward_char() && *iter=='-' && iter.backward_char()))
break; break;
if(*iter=='>') {
if(!(iter.backward_char() && *iter=='-' && iter.backward_char()))
break;
}
else if(*iter==':') {
if(!(iter.backward_char() && *iter==':' && iter.backward_char()))
break;
}
} }
else if(*iter==':') { auto spelling=get_buffer()->get_text(start, end).raw();
if(!(iter.backward_char() && *iter==':' && iter.backward_char()))
break; Glib::ustring debug_value=Debug::LLDB::get().get_value(spelling, location.get_path(), location.get_offset().line, location.get_offset().index);
if(debug_value.empty()) {
value_type="Return value";
auto cursor=token.get_cursor();
auto offsets=cursor.get_source_range().get_offsets();
debug_value=Debug::LLDB::get().get_return_value(cursor.get_source_location().get_path(), offsets.first.line, offsets.first.index);
} }
} if(!debug_value.empty()) {
auto spelling=get_buffer()->get_text(start, end).raw(); size_t pos=debug_value.find(" = ");
if(pos!=Glib::ustring::npos) {
Glib::ustring debug_value=Debug::LLDB::get().get_value(spelling, location.get_path(), location.get_offset().line, location.get_offset().index); Glib::ustring::iterator iter;
if(debug_value.empty()) { while(!debug_value.validate(iter)) {
value_type="Return value"; auto next_char_iter=iter;
auto cursor=token.get_cursor(); next_char_iter++;
auto offsets=cursor.get_source_range().get_offsets(); debug_value.replace(iter, next_char_iter, "?");
debug_value=Debug::LLDB::get().get_return_value(cursor.get_source_location().get_path(), offsets.first.line, offsets.first.index); }
} tooltip_buffer->insert_with_tag(tooltip_buffer->get_insert()->get_iter(), "\n\n"+value_type+": "+debug_value.substr(pos+3, debug_value.size()-(pos+3)-1), "def:note");
if(!debug_value.empty()) {
size_t pos=debug_value.find(" = ");
if(pos!=Glib::ustring::npos) {
Glib::ustring::iterator iter;
while(!debug_value.validate(iter)) {
auto next_char_iter=iter;
next_char_iter++;
debug_value.replace(iter, next_char_iter, "?");
} }
tooltip_buffer->insert_with_tag(tooltip_buffer->get_insert()->get_iter(), "\n\n"+value_type+": "+debug_value.substr(pos+3, debug_value.size()-(pos+3)-1), "def:note");
} }
} }
}
#endif #endif
return tooltip_buffer; return tooltip_buffer;
}; };
type_tooltips.emplace_back(create_tooltip_buffer, *this, get_buffer()->create_mark(start), get_buffer()->create_mark(end)); type_tooltips.emplace_back(create_tooltip_buffer, *this, get_buffer()->create_mark(start), get_buffer()->create_mark(end));
type_tooltips.show();
return;
}
} }
} }
type_tooltips.show();
} }
} }
} }
@ -952,14 +935,14 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
//If rename class, also rename constructors and destructor //If rename class, also rename constructors and destructor
std::set<Identifier> identifiers; std::set<Identifier> identifiers;
identifiers.emplace(identifier); identifiers.emplace(identifier);
if(identifier.cursor.get_kind()==clang::Cursor::Kind::ClassDecl) { auto identifier_cursor_kind=identifier.cursor.get_kind();
if(identifier_cursor_kind==clang::Cursor::Kind::ClassDecl || identifier_cursor_kind==clang::Cursor::Kind::ClassTemplate) {
for(auto &token: *clang_view->clang_tokens) { for(auto &token: *clang_view->clang_tokens) {
auto cursor=token.get_cursor(); auto cursor=token.get_cursor();
auto cursor_kind=cursor.get_kind(); auto cursor_kind=cursor.get_kind();
auto parent_cursor=cursor.get_semantic_parent(); auto parent_cursor=cursor.get_semantic_parent();
if(token.get_kind()==clang::Token::Kind::Identifier && if((cursor_kind==clang::Cursor::Kind::Constructor || cursor_kind==clang::Cursor::Kind::Destructor) &&
(cursor_kind==clang::Cursor::Kind::Constructor || cursor_kind==clang::Cursor::Kind::Destructor) && token.is_identifier() && parent_cursor.get_usr()==identifier.cursor.get_usr()) {
parent_cursor.get_usr()==identifier.cursor.get_usr() && cursor.has_type_description()) {
identifiers.emplace(cursor.get_kind(), token.get_spelling(), cursor.get_usr()); identifiers.emplace(cursor.get_kind(), token.get_spelling(), cursor.get_usr());
} }
} }
@ -1038,10 +1021,11 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
if(auto clang_view=dynamic_cast<Source::ClangView*>(view)) { if(auto clang_view=dynamic_cast<Source::ClangView*>(view)) {
for(auto &token: *clang_view->clang_tokens) { for(auto &token: *clang_view->clang_tokens) {
auto cursor=token.get_cursor(); auto cursor=token.get_cursor();
auto kind=cursor.get_kind(); auto cursor_kind=cursor.get_kind();
if((kind==clang::Cursor::Kind::FunctionDecl || kind==clang::Cursor::Kind::CXXMethod || if((cursor_kind==clang::Cursor::Kind::FunctionDecl || cursor_kind==clang::Cursor::Kind::CXXMethod ||
kind==clang::Cursor::Kind::Constructor || kind==clang::Cursor::Kind::Destructor) && cursor_kind==clang::Cursor::Kind::Constructor || cursor_kind==clang::Cursor::Kind::Destructor ||
token.get_kind()==clang::Token::Kind::Identifier && cursor.has_type_description()) { cursor_kind==clang::Cursor::Kind::ConversionFunction) &&
token.is_identifier()) {
auto referenced=cursor.get_referenced(); auto referenced=cursor.get_referenced();
if(referenced && identifier.kind==referenced.get_kind() && if(referenced && identifier.kind==referenced.get_kind() &&
identifier.spelling==token.get_spelling() && identifier.usr==referenced.get_usr()) { identifier.spelling==token.get_spelling() && identifier.usr==referenced.get_usr()) {
@ -1163,12 +1147,13 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
auto line=static_cast<unsigned>(iter.get_line()); auto line=static_cast<unsigned>(iter.get_line());
auto index=static_cast<unsigned>(iter.get_line_index()); auto index=static_cast<unsigned>(iter.get_line_index());
for(auto &token: *clang_tokens) { for(auto &token: *clang_tokens) {
auto cursor=token.get_cursor(); if(token.is_identifier()) {
if(token.get_kind()==clang::Token::Kind::Identifier && cursor.has_type_description()) {
if(line==token.offsets.first.line-1 && index>=token.offsets.first.index-1 && index <=token.offsets.second.index-1) { if(line==token.offsets.first.line-1 && index>=token.offsets.first.index-1 && index <=token.offsets.second.index-1) {
auto cursor=token.get_cursor();
auto kind=cursor.get_kind(); auto kind=cursor.get_kind();
if(kind==clang::Cursor::Kind::FunctionDecl || kind==clang::Cursor::Kind::CXXMethod || if(kind==clang::Cursor::Kind::FunctionDecl || kind==clang::Cursor::Kind::CXXMethod ||
kind==clang::Cursor::Kind::Constructor || kind==clang::Cursor::Kind::Destructor) { kind==clang::Cursor::Kind::Constructor || kind==clang::Cursor::Kind::Destructor ||
kind==clang::Cursor::Kind::ConversionFunction) {
auto referenced=cursor.get_referenced(); auto referenced=cursor.get_referenced();
if(referenced && referenced==cursor) { if(referenced && referenced==cursor) {
std::string result; std::string result;
@ -1225,13 +1210,19 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
Info::get().print("Buffer is parsing"); Info::get().print("Buffer is parsing");
return methods; return methods;
} }
clang::Offset last_offset(-1, -1);
for(auto &token: *clang_tokens) { for(auto &token: *clang_tokens) {
auto cursor=token.get_cursor(); if(token.is_identifier()) {
if(token.get_kind()==clang::Token::Kind::Identifier && cursor.has_type_description()) { auto cursor=token.get_cursor();
auto kind=cursor.get_kind(); auto kind=cursor.get_kind();
if(kind==clang::Cursor::Kind::FunctionDecl || kind==clang::Cursor::Kind::CXXMethod || if(kind==clang::Cursor::Kind::FunctionDecl || kind==clang::Cursor::Kind::CXXMethod ||
kind==clang::Cursor::Kind::Constructor || kind==clang::Cursor::Kind::Destructor) { kind==clang::Cursor::Kind::Constructor || kind==clang::Cursor::Kind::Destructor ||
kind==clang::Cursor::Kind::ConversionFunction) {
auto offset=cursor.get_source_location().get_offset(); auto offset=cursor.get_source_location().get_offset();
if(offset==last_offset)
continue;
last_offset=offset;
std::string method; std::string method;
if(kind==clang::Cursor::Kind::FunctionDecl || kind==clang::Cursor::Kind::CXXMethod) { if(kind==clang::Cursor::Kind::FunctionDecl || kind==clang::Cursor::Kind::CXXMethod) {
method+=cursor.get_type().get_result().get_spelling(); method+=cursor.get_type().get_result().get_spelling();
@ -1255,28 +1246,10 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
size_t token_end_pos=row.find('('); size_t token_end_pos=row.find('(');
if(token_end_pos==0 || token_end_pos==std::string::npos) if(token_end_pos==0 || token_end_pos==std::string::npos)
continue; continue;
if(token_end_pos>8 && row.substr(token_end_pos-4, 4)=="&gt;") {
token_end_pos-=8;
size_t angle_bracket_count=1;
do {
if(row.substr(token_end_pos-4, 4)=="&gt;") {
angle_bracket_count++;
token_end_pos-=4;
}
else if(row.substr(token_end_pos-4, 4)=="&lt;") {
angle_bracket_count--;
token_end_pos-=4;
}
else
token_end_pos--;
} while(angle_bracket_count>0 && token_end_pos>4);
}
auto pos=token_end_pos; auto pos=token_end_pos;
do { do {
pos--; pos--;
} while(((row[pos]>='a' && row[pos]<='z') || } while(row[pos]!=':' && row[pos]!=' ' && pos!=std::string::npos);
(row[pos]>='A' && row[pos]<='Z') ||
(row[pos]>='0' && row[pos]<='9') || row[pos]=='_' || row[pos]=='~') && pos>0);
row.insert(token_end_pos, "</b>"); row.insert(token_end_pos, "</b>");
row.insert(pos+1, "<b>"); row.insert(pos+1, "<b>");
methods.emplace_back(Offset(offset.line-1, offset.index-1), row); methods.emplace_back(Offset(offset.line-1, offset.index-1), row);
@ -1309,10 +1282,9 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
auto line=static_cast<unsigned>(iter.get_line()); auto line=static_cast<unsigned>(iter.get_line());
auto index=static_cast<unsigned>(iter.get_line_index()); auto index=static_cast<unsigned>(iter.get_line_index());
for(auto &token: *clang_tokens) { for(auto &token: *clang_tokens) {
auto cursor=token.get_cursor(); if(token.is_identifier()) {
if(token.get_kind()==clang::Token::Kind::Identifier && cursor.has_type_description()) {
if(line==token.offsets.first.line-1 && index>=token.offsets.first.index-1 && index <=token.offsets.second.index-1) { if(line==token.offsets.first.line-1 && index>=token.offsets.first.index-1 && index <=token.offsets.second.index-1) {
auto referenced=cursor.get_referenced(); auto referenced=token.get_cursor().get_referenced();
if(referenced) { if(referenced) {
auto usr=referenced.get_usr(); auto usr=referenced.get_usr();
@ -1430,13 +1402,11 @@ Source::ClangViewRefactor::Identifier Source::ClangViewRefactor::get_identifier(
auto iter=get_buffer()->get_insert()->get_iter(); auto iter=get_buffer()->get_insert()->get_iter();
auto line=static_cast<unsigned>(iter.get_line()); auto line=static_cast<unsigned>(iter.get_line());
auto index=static_cast<unsigned>(iter.get_line_index()); auto index=static_cast<unsigned>(iter.get_line_index());
for(auto &token: *clang_tokens) { for(size_t c=clang_tokens->size()-1;c!=static_cast<size_t>(-1);--c) {
auto cursor=token.get_cursor(); auto &token=(*clang_tokens)[c];
if(token.get_kind()==clang::Token::Kind::Identifier && cursor.has_type_description()) { if(token.is_identifier()) {
if(line==token.offsets.first.line-1 && index>=token.offsets.first.index-1 && index <=token.offsets.second.index-1) { if(line==token.offsets.first.line-1 && index>=token.offsets.first.index-1 && index <=token.offsets.second.index-1) {
if(token.get_cursor().get_kind()==clang::Cursor::Kind::CallExpr) //These cursors are buggy auto referenced=token.get_cursor().get_referenced();
continue;
auto referenced=cursor.get_referenced();
if(referenced) if(referenced)
return Identifier(referenced.get_kind(), token.get_spelling(), referenced.get_usr(), referenced); return Identifier(referenced.get_kind(), token.get_spelling(), referenced.get_usr(), referenced);
} }

Loading…
Cancel
Save