[PATCH] 658097 Fix hovering over pointer dereference expression
- From: Dodji Seketeli <dodji seketeli org>
- To: Nemiver Development <nemiver-list gnome org>
- Subject: [PATCH] 658097 Fix hovering over pointer dereference expression
- Date: Sat, 03 Sep 2011 01:07:16 +0200
Hello,
Consider the following pointer de-referencing expression:
foo->bar;
When I hover over the "foo" part of that expression, I want Nemiver to
show me the content of the foo variable. That works OK.
But when I hover over the "bar" part of the expression, I want Nemiver
to show me the content of the foo->bar variable. That doesn't work.
Nemiver tries to show me the content of an "hypothetical" bar
variable. That can even lead to some buggy behaviour, e.g:
struct S
{
int bar;
S() : bar(0) {}
}
void
fun()
{
int bar = 1;
S * foo = new S;
foo->bar = 2; //#0
}
On the line commented #0, if I hover over the "bar" part of the
foo->bar expression, the variable tooltip shows the content of the bar
variable which value is 1, instead of showing the value of the
foo->bar expression which is 2!
The patch below enhances the behaviour of the simplistic expression
parsing code that deals with recognizing things like foo->bar or
foo.bar.
Tested and applied to master and gtk2-branch
commit 7902ae8cddd7b5f1bfc758597f6943cabe86aa66
Author: Dodji Seketeli <dodji seketeli org>
Date: Sat Sep 3 00:28:00 2011 +0200
658097 Fix hovering over pointer dereference expression
* src/uicommon/nmv-source-editor.cc (parse_word_around_iter): New
function. Factorized and enhanced from ...
(SourceEditor::get_word_at_position): ... here.
* tests/pointer-deref.cc: Enhance this test to add some
de-referencing expression for testing purpose.
diff --git a/src/uicommon/nmv-source-editor.cc b/src/uicommon/nmv-source-editor.cc
index 42e9b1b..d93e18a 100644
--- a/src/uicommon/nmv-source-editor.cc
+++ b/src/uicommon/nmv-source-editor.cc
@@ -1106,58 +1106,95 @@ is_word_delimiter (gunichar a_char)
return false;
}
+/// Parse the name of the variable that surrounds a_iter. If a_iter
+/// is on the "bar" part of "foo->bar", the name returned is
+/// "foo->bar". If it's on the "foo" part, the name returned is
+/// "foo". Similarly for foo.bar.
+///
+/// \param a_iter the iterator from which the parsing starts
+///
+/// \param a_begin the resulting iterator pointing at the character
+/// that starts the variable name that has been parsed.
+///
+/// \param a_end the resulting iterator pointing at the character that
+/// ends the variable name that has been parsed.
+///
+/// \return true if the parsing succeeded, false otherwise.
+bool
+parse_word_around_iter (const Gtk::TextBuffer::iterator &a_iter,
+ Gtk::TextBuffer::iterator &a_begin,
+ Gtk::TextBuffer::iterator &a_end)
+{
+ if (!a_iter)
+ return false;
+
+ gunichar c = 0, prev_char = 0;
+ Gtk::TextBuffer::iterator iter = a_iter;
+
+ // First, go backward to find the first word delimiter before a_iter
+ while (iter.backward_char ()
+ && (!is_word_delimiter (c = iter.get_char ())
+ || c == '>' || c == '-' || c == '.')) {
+ if (c == '-') {
+ if (prev_char == '>') {
+ // this is the '-' of the "->" operator. Keep going.
+
+ } else {
+ // This is the minus operator. It's a word
+ // delimiter. Stop here.
+ iter.forward_char ();
+ break;
+ }
+ }
+ prev_char = c;
+ }
+ iter.forward_char ();
+ a_begin = iter;
+
+ // Then, go forward find the first word delimiter after a_iter
+ iter = a_iter;
+ while (iter.forward_char ()
+ && !is_word_delimiter (iter.get_char ())) {}
+ a_end = iter;
+
+ return true;
+}
+
bool
SourceEditor::get_word_at_position (int a_x,
- int a_y,
- UString &a_word,
- Gdk::Rectangle &a_start_rect,
- Gdk::Rectangle &a_end_rect) const
+ int a_y,
+ UString &a_word,
+ Gdk::Rectangle &a_start_rect,
+ Gdk::Rectangle &a_end_rect) const
{
LOG_FUNCTION_SCOPE_NORMAL_DD
THROW_IF_FAIL (m_priv);
int buffer_x=0, buffer_y=0;
source_view ().window_to_buffer_coords (Gtk::TEXT_WINDOW_TEXT,
- (int)a_x,
- (int)a_y,
- buffer_x, buffer_y);
+ (int)a_x,
+ (int)a_y,
+ buffer_x, buffer_y);
Gtk::TextBuffer::iterator clicked_at_iter;
source_view ().get_iter_at_location (clicked_at_iter, buffer_x, buffer_y);
if (!clicked_at_iter) {
- return false;
+ return false;
}
- //go find the first white word delimiter before clicked_at_iter
- Gtk::TextBuffer::iterator cur_iter = clicked_at_iter;
- if (!cur_iter) {return false;}
-
- while (cur_iter.backward_char ()
- && !is_word_delimiter (cur_iter.get_char ())) {}
- THROW_IF_FAIL (cur_iter.forward_char ());
- Gtk::TextBuffer::iterator start_word_iter = cur_iter;
-
- //go find the first word delimiter after clicked_at_iter
- cur_iter = clicked_at_iter;
- while (cur_iter.forward_char ()
- && !is_word_delimiter (cur_iter.get_char ())) {}
- Gtk::TextBuffer::iterator end_word_iter = cur_iter;
+ Gtk::TextBuffer::iterator start_word_iter, end_word_iter;
+ if (!parse_word_around_iter (clicked_at_iter,
+ start_word_iter,
+ end_word_iter))
+ return false;
UString var_name = start_word_iter.get_slice (end_word_iter);
- while (var_name != "" && !isalpha (var_name[0]) && var_name[0] != '_') {
- var_name.erase (0, 1);
- }
- while (var_name != ""
- && !isalnum (var_name[var_name.size () - 1])
- && var_name[var_name.size () - 1] != '_') {
- var_name.erase (var_name.size () - 1, 1);
- }
Gdk::Rectangle start_rect, end_rect;
source_view ().get_iter_location (start_word_iter, start_rect);
source_view ().get_iter_location (end_word_iter, end_rect);
if (!(start_rect.get_x () <= buffer_x) || !(buffer_x <= end_rect.get_x ())) {
- LOG_DD ("mouse not really on word: '" << var_name << "'");
- return false;
+ LOG_DD ("mouse not really on word: '" << var_name << "'");
+ return false;
}
LOG_DD ("got variable candidate name: '" << var_name << "'");
a_word = var_name;
diff --git a/tests/pointer-deref.cc b/tests/pointer-deref.cc
index 876c641..76cfeb1 100644
--- a/tests/pointer-deref.cc
+++ b/tests/pointer-deref.cc
@@ -1,6 +1,6 @@
#include <iostream>
-class baz {
+struct baz {
int m_a;
int m_b;
@@ -23,7 +23,7 @@ public:
};//end foo
-class bar {
+struct bar {
baz *m_baz;
public:
@@ -65,7 +65,7 @@ public:
}
};//end bar
-class foo {
+struct foo {
bar * m_bar;
public:
@@ -145,6 +145,23 @@ main ()
change_baz (baz_ptr);
change_baz_ptr (&baz_ptr);
+ if (foo_ptr->m_bar) {
+ ;
+ }
+
+ if (foo_ptr->m_bar->m_baz) {
+ ;
+ }
+
+ if (foo_ptr->m_bar->m_baz->m_a) {
+ ;
+ }
+
+ baz b;
+ if (b.m_b) {
+ ;
+ }
+
delete foo_ptr;
return 0;
--
Dodji
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]