Browse Source

Implemented menu item Source.Comments.Add Documentation

merge-requests/365/head
eidheim 9 years ago
parent
commit
cea6db59bf
  1. 2
      src/menu.cc
  2. 115
      src/source.cc
  3. 4
      src/source.h
  4. 44
      src/source_clang.cc
  5. 43
      src/window.cc

2
src/menu.cc

@ -275,7 +275,7 @@ const Glib::ustring menu_xml= R"RAW(<interface>
<attribute name='action'>app.source_comments_toggle</attribute> <attribute name='action'>app.source_comments_toggle</attribute>
</item> </item>
<item> <item>
<attribute name='label' translatable='yes'>_Add _Documentation (not yet implemented)</attribute> <attribute name='label' translatable='yes'>_Add _Documentation</attribute>
<attribute name='action'>app.source_comments_add_documentation</attribute> <attribute name='action'>app.source_comments_add_documentation</attribute>
</item> </item>
</submenu> </submenu>

115
src/source.cc

@ -1244,6 +1244,25 @@ std::string Source::View::get_token(Gtk::TextIter iter) {
return get_buffer()->get_text(start, end); return get_buffer()->get_text(start, end);
} }
void Source::View::cleanup_whitespace_characters_on_return(const Gtk::TextIter &iter) {
auto start_blank_iter=iter;
auto end_blank_iter=iter;
while((*end_blank_iter==' ' || *end_blank_iter=='\t') &&
!end_blank_iter.ends_line() && end_blank_iter.forward_char()) {}
if(!start_blank_iter.starts_line()) {
start_blank_iter.backward_char();
while((*start_blank_iter==' ' || *start_blank_iter=='\t') &&
!start_blank_iter.starts_line() && start_blank_iter.backward_char()) {}
if(*start_blank_iter!=' ' && *start_blank_iter!='\t')
start_blank_iter.forward_char();
}
if(start_blank_iter.starts_line())
get_buffer()->erase(iter, end_blank_iter);
else
get_buffer()->erase(start_blank_iter, end_blank_iter);
}
bool Source::View::on_key_press_event(GdkEventKey* key) { bool Source::View::on_key_press_event(GdkEventKey* key) {
if(SelectionDialog::get() && SelectionDialog::get()->is_visible()) { if(SelectionDialog::get() && SelectionDialog::get()->is_visible()) {
if(SelectionDialog::get()->on_key_press(key)) if(SelectionDialog::get()->on_key_press(key))
@ -1328,24 +1347,6 @@ bool Source::View::on_key_press_event(GdkEventKey* key) {
return true; return true;
} }
if(get_buffer()->get_has_selection()) {
auto return_value=on_key_press_event_basic(key);
get_buffer()->end_user_action();
if(return_value)
return true;
else
return Gsv::View::on_key_press_event(key);
}
if(!is_code_iter(get_buffer()->get_insert()->get_iter())) {
auto return_value=on_key_press_event_basic(key);
get_buffer()->end_user_action();
if(return_value)
return true;
else
return Gsv::View::on_key_press_event(key);
}
if(is_bracket_language && on_key_press_event_bracket_language(key)) { if(is_bracket_language && on_key_press_event_bracket_language(key)) {
get_buffer()->end_user_action(); get_buffer()->end_user_action();
return true; return true;
@ -1363,23 +1364,10 @@ bool Source::View::on_key_press_event(GdkEventKey* key) {
//Basic indentation //Basic indentation
bool Source::View::on_key_press_event_basic(GdkEventKey* key) { bool Source::View::on_key_press_event_basic(GdkEventKey* key) {
auto iter=get_buffer()->get_insert()->get_iter(); auto iter=get_buffer()->get_insert()->get_iter();
//Indent as in next or previous line //Indent as in next or previous line
if((key->keyval==GDK_KEY_Return || key->keyval==GDK_KEY_KP_Enter) && !get_buffer()->get_has_selection() && !iter.starts_line()) { if((key->keyval==GDK_KEY_Return || key->keyval==GDK_KEY_KP_Enter) && !get_buffer()->get_has_selection() && !iter.starts_line()) {
//First remove spaces or tabs around cursor cleanup_whitespace_characters_on_return(iter);
auto start_blank_iter=iter;
auto end_blank_iter=iter;
while((*end_blank_iter==' ' || *end_blank_iter=='\t') &&
!end_blank_iter.ends_line() && end_blank_iter.forward_char()) {}
start_blank_iter.backward_char();
while((*start_blank_iter==' ' || *start_blank_iter=='\t') &&
!start_blank_iter.starts_line() && start_blank_iter.backward_char()) {}
if(start_blank_iter.starts_line() && (*start_blank_iter==' ' || *start_blank_iter=='\t'))
get_buffer()->erase(iter, end_blank_iter);
else {
start_blank_iter.forward_char();
get_buffer()->erase(start_blank_iter, end_blank_iter);
}
iter=get_buffer()->get_insert()->get_iter(); iter=get_buffer()->get_insert()->get_iter();
auto tabs=get_line_before(get_tabs_end_iter(iter)); auto tabs=get_line_before(get_tabs_end_iter(iter));
@ -1595,22 +1583,39 @@ bool Source::View::on_key_press_event_basic(GdkEventKey* key) {
//Bracket language indentation //Bracket language indentation
bool Source::View::on_key_press_event_bracket_language(GdkEventKey* key) { bool Source::View::on_key_press_event_bracket_language(GdkEventKey* key) {
auto iter=get_buffer()->get_insert()->get_iter(); auto iter=get_buffer()->get_insert()->get_iter();
//Indent depending on if/else/etc and brackets
if(get_buffer()->get_has_selection())
return false;
if(!is_code_iter(iter)) {
// Add * at start of line in comment blocks
if((key->keyval==GDK_KEY_Return || key->keyval==GDK_KEY_KP_Enter) && !iter.starts_line()) { if((key->keyval==GDK_KEY_Return || key->keyval==GDK_KEY_KP_Enter) && !iter.starts_line()) {
//First remove spaces or tabs around cursor cleanup_whitespace_characters_on_return(iter);
auto start_blank_iter=iter;
auto end_blank_iter=iter; iter=get_buffer()->get_insert()->get_iter();
while((*end_blank_iter==' ' || *end_blank_iter=='\t') && auto start_iter=get_tabs_end_iter(iter.get_line());
!end_blank_iter.ends_line() && end_blank_iter.forward_char()) {} auto end_iter=start_iter;
start_blank_iter.backward_char(); end_iter.forward_chars(2);
while((*start_blank_iter==' ' || *start_blank_iter=='\t' || start_blank_iter.ends_line()) && auto start_of_sentence=get_buffer()->get_text(start_iter, end_iter);
!start_blank_iter.starts_line() && start_blank_iter.backward_char()) {} if(!start_of_sentence.empty()) {
if(!start_blank_iter.starts_line()) { if(start_of_sentence=="/*" || start_of_sentence[0]=='*') {
start_blank_iter.forward_char(); auto tabs=get_line_before(start_iter);
get_buffer()->erase(start_blank_iter, end_blank_iter); auto insert_str="\n"+tabs;
if(start_of_sentence[0]=='/')
insert_str+=' ';
insert_str+="* ";
get_buffer()->insert_at_cursor(insert_str);
return true;
}
}
}
return false;
} }
else
get_buffer()->erase(iter, end_blank_iter); //Indent depending on if/else/etc and brackets
if((key->keyval==GDK_KEY_Return || key->keyval==GDK_KEY_KP_Enter) && !iter.starts_line()) {
cleanup_whitespace_characters_on_return(iter);
iter=get_buffer()->get_insert()->get_iter(); iter=get_buffer()->get_insert()->get_iter();
auto previous_iter=iter; auto previous_iter=iter;
@ -1627,6 +1632,22 @@ bool Source::View::on_key_press_event_bracket_language(GdkEventKey* key) {
else else
start_iter=get_tabs_end_iter(get_buffer()->get_iter_at_line(find_start_of_sentence(start_iter).get_line())); start_iter=get_tabs_end_iter(get_buffer()->get_iter_at_line(find_start_of_sentence(start_iter).get_line()));
auto tabs=get_line_before(start_iter); auto tabs=get_line_before(start_iter);
/*
* Change tabs after ending comment block with an extra space (as in this case)
*/
if(tabs.size()%tab_size==1) {
iter=get_buffer()->get_insert()->get_iter();
auto tabs_end_iter=get_tabs_end_iter(iter);
if(!tabs_end_iter.ends_line() && !is_code_iter(tabs_end_iter)) {
auto end_of_line_iter=tabs_end_iter;
end_of_line_iter.forward_to_line_end();
auto line=get_buffer()->get_text(tabs_end_iter, end_of_line_iter);
if(!line.empty() && line.compare(0, 2, "*/")==0)
tabs.pop_back();
}
}
if(*previous_iter=='{') { if(*previous_iter=='{') {
Gtk::TextIter found_iter; Gtk::TextIter found_iter;
bool found_right_bracket=find_close_curly_bracket_forward(iter, found_iter); bool found_right_bracket=find_close_curly_bracket_forward(iter, found_iter);

4
src/source.h

@ -77,7 +77,7 @@ namespace Source {
std::function<void()> goto_next_diagnostic; std::function<void()> goto_next_diagnostic;
std::function<std::vector<FixIt>()> get_fix_its; std::function<std::vector<FixIt>()> get_fix_its;
std::function<void()> toggle_comments; std::function<void()> toggle_comments;
std::function<void()> add_documentation; std::function<std::tuple<Source::Offset, std::string, size_t>()> get_documentation_template;
std::function<void(int)> toggle_breakpoint; std::function<void(int)> toggle_breakpoint;
Gtk::TextIter get_iter_for_dialog(); Gtk::TextIter get_iter_for_dialog();
@ -136,6 +136,8 @@ namespace Source {
std::string get_token(Gtk::TextIter iter); std::string get_token(Gtk::TextIter iter);
void cleanup_whitespace_characters_on_return(const Gtk::TextIter &iter);
const static std::regex bracket_regex; const static std::regex bracket_regex;
const static std::regex no_bracket_statement_regex; const static std::regex no_bracket_statement_regex;
const static std::regex no_bracket_no_para_statement_regex; const static std::regex no_bracket_no_para_statement_regex;

44
src/source_clang.cc

@ -1403,6 +1403,50 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
Info::get().print("No fix-its found in current buffer"); Info::get().print("No fix-its found in current buffer");
return fix_its; return fix_its;
}; };
get_documentation_template=[this]() {
if(!parsed) {
Info::get().print("Buffer is parsing");
return std::tuple<Source::Offset, std::string, size_t>(Source::Offset(), "", 0);
}
auto identifier=get_identifier();
if(identifier) {
auto cursor=identifier.cursor.get_canonical();
if(!clang_Range_isNull(clang_Cursor_getCommentRange(cursor.cx_cursor))) {
Info::get().print("Symbol is already documented");
return std::tuple<Source::Offset, std::string, size_t>(Source::Offset(), "", 0);
}
auto clang_offsets=cursor.get_source_range().get_offsets();
auto source_offset=Offset(clang_offsets.first.line-1, 0, cursor.get_source_location().get_path());
std::string tabs;
for(size_t c=0;c<clang_offsets.first.index-1;++c)
tabs+=' ';
auto first_line=tabs+"/**\n";
auto second_line=tabs+" * \n";
auto iter_offset=first_line.size()+second_line.size()-1;
std::string param_lines;
for(int c=0;c<clang_Cursor_getNumArguments(cursor.cx_cursor);++c)
param_lines+=tabs+" * @param "+clang::Cursor(clang_Cursor_getArgument(cursor.cx_cursor, c)).get_spelling()+'\n';
std::string return_line;
auto return_spelling=cursor.get_type().get_result().get_spelling();
if(!return_spelling.empty() && return_spelling!="void")
return_line+=tabs+" * @return\n";
auto documentation=first_line+second_line;
if(!param_lines.empty() || !return_line.empty())
documentation+=tabs+" *\n";
documentation+=param_lines+return_line+tabs+" */\n";
return std::tuple<Source::Offset, std::string, size_t>(source_offset, documentation, iter_offset);
}
else {
Info::get().print("No symbol found at current cursor location");
return std::tuple<Source::Offset, std::string, size_t>(Source::Offset(), "", 0);
}
};
} }
Source::ClangViewRefactor::Identifier Source::ClangViewRefactor::get_identifier() { Source::ClangViewRefactor::Identifier Source::ClangViewRefactor::get_identifier() {

43
src/window.cc

@ -651,8 +651,23 @@ void Window::set_menu_actions() {
}); });
menu.add_action("source_comments_add_documentation", [this]() { menu.add_action("source_comments_add_documentation", [this]() {
if(auto view=Notebook::get().get_current_view()) { if(auto view=Notebook::get().get_current_view()) {
if(view->add_documentation) { if(view->get_documentation_template) {
view->add_documentation(); auto documentation_template=view->get_documentation_template();
auto offset=std::get<0>(documentation_template);
if(offset) {
boost::system::error_code ec;
auto canonical_path=boost::filesystem::canonical(offset.file_path, ec);
if(ec)
return;
Notebook::get().open(canonical_path);
auto view=Notebook::get().get_current_view();
auto iter=view->get_buffer()->get_iter_at_line_index(offset.line, offset.index);
view->get_buffer()->insert(iter, std::get<1>(documentation_template));
iter=view->get_buffer()->get_iter_at_line_index(offset.line, offset.index);
iter.forward_chars(std::get<2>(documentation_template));
view->get_buffer()->place_cursor(iter);
view->scroll_to_cursor_delayed(view, true, false);
}
} }
} }
}); });
@ -1174,18 +1189,18 @@ void Window::activate_menu_items() {
menu.actions["source_goto_line"]->set_enabled(view); menu.actions["source_goto_line"]->set_enabled(view);
menu.actions["source_center_cursor"]->set_enabled(view); menu.actions["source_center_cursor"]->set_enabled(view);
menu.actions["source_indentation_auto_indent_buffer"]->set_enabled(view && static_cast<bool>(view->format_style)); menu.actions["source_indentation_auto_indent_buffer"]->set_enabled(view && view->format_style);
menu.actions["source_comments_toggle"]->set_enabled(view && static_cast<bool>(view->toggle_comments)); menu.actions["source_comments_toggle"]->set_enabled(view && view->toggle_comments);
menu.actions["source_comments_add_documentation"]->set_enabled(view && static_cast<bool>(view->add_documentation)); menu.actions["source_comments_add_documentation"]->set_enabled(view && view->get_documentation_template);
menu.actions["source_find_documentation"]->set_enabled(view && static_cast<bool>(view->get_token_data)); menu.actions["source_find_documentation"]->set_enabled(view && view->get_token_data);
menu.actions["source_goto_declaration"]->set_enabled(view && static_cast<bool>(view->get_declaration_location)); menu.actions["source_goto_declaration"]->set_enabled(view && view->get_declaration_location);
menu.actions["source_goto_implementation"]->set_enabled(view && static_cast<bool>(view->get_implementation_locations)); menu.actions["source_goto_implementation"]->set_enabled(view && view->get_implementation_locations);
menu.actions["source_goto_usage"]->set_enabled(view && static_cast<bool>(view->get_usages)); menu.actions["source_goto_usage"]->set_enabled(view && view->get_usages);
menu.actions["source_goto_method"]->set_enabled(view && static_cast<bool>(view->get_methods)); menu.actions["source_goto_method"]->set_enabled(view && view->get_methods);
menu.actions["source_rename"]->set_enabled(view && static_cast<bool>(view->rename_similar_tokens)); menu.actions["source_rename"]->set_enabled(view && view->rename_similar_tokens);
menu.actions["source_implement_method"]->set_enabled(view && static_cast<bool>(view->get_method)); menu.actions["source_implement_method"]->set_enabled(view && view->get_method);
menu.actions["source_goto_next_diagnostic"]->set_enabled(view && static_cast<bool>(view->goto_next_diagnostic)); menu.actions["source_goto_next_diagnostic"]->set_enabled(view && view->goto_next_diagnostic);
menu.actions["source_apply_fix_its"]->set_enabled(view && static_cast<bool>(view->get_fix_its)); menu.actions["source_apply_fix_its"]->set_enabled(view && view->get_fix_its);
#ifdef JUCI_ENABLE_DEBUG #ifdef JUCI_ENABLE_DEBUG
Project::debug_activate_menu_items(); Project::debug_activate_menu_items();
#endif #endif

Loading…
Cancel
Save