summaryrefslogtreecommitdiff
path: root/libcpp
diff options
context:
space:
mode:
Diffstat (limited to 'libcpp')
-rw-r--r--libcpp/ChangeLog20
-rw-r--r--libcpp/include/line-map.h101
-rw-r--r--libcpp/line-map.c65
3 files changed, 169 insertions, 17 deletions
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 792f76ae3b5..95e12a9ba6b 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,23 @@
+2016-09-13 David Malcolm <dmalcolm@redhat.com>
+
+ * include/line-map.h (class rich_location): Add description of
+ fix-it hints to leading comment.
+ (rich_location::add_fixit_insert): Rename both overloaded methods
+ to..
+ (rich_location::add_fixit_insert_before): ...this, updating their
+ comments.
+ (rich_location::add_fixit_insert_after): Two new overloaded
+ methods.
+ (rich_location::stop_supporting_fixits): New method.
+ * line-map.c (rich_location::add_fixit_insert): Rename both
+ overloaded methods to..
+ (rich_location::add_fixit_insert_before): ...this, updating their
+ comments.
+ (rich_location::add_fixit_insert_after): Two new methods.
+ (rich_location::reject_impossible_fixit): Split out
+ failure-handling into...
+ (rich_location::stop_supporting_fixits): New method.
+
2016-09-02 David Malcolm <dmalcolm@redhat.com>
* include/line-map.h (rich_location::seen_impossible_fixit_p): New
diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h
index 6b3c474a0de..939bfcc5712 100644
--- a/libcpp/include/line-map.h
+++ b/libcpp/include/line-map.h
@@ -1484,7 +1484,84 @@ class fixit_hint;
- range 0 is at the "%s" with start = caret = "%" and finish at
the "s".
- range 1 has start/finish covering the "101" and is not flagged for
- caret printing; it is perhaps at the start of "101". */
+ caret printing; it is perhaps at the start of "101".
+
+
+ Fix-it hints
+ ------------
+
+ Rich locations can also contain "fix-it hints", giving suggestions
+ for the user on how to edit their code to fix a problem. These
+ can be expressed as insertions, replacements, and removals of text.
+ The edits by default are relative to the zeroth range within the
+ rich_location, but optionally they can be expressed relative to
+ other locations (using various overloaded methods of the form
+ rich_location::add_fixit_*).
+
+ For example:
+
+ Example F: fix-it hint: insert_before
+ *************************************
+ ptr = arr[0];
+ ^~~~~~
+ &
+ This rich location has a single range (range 0) covering "arr[0]",
+ with the caret at the start. The rich location has a single
+ insertion fix-it hint, inserted before range 0, added via
+ richloc.add_fixit_insert_before ("&");
+
+ Example G: multiple fix-it hints: insert_before and insert_after
+ ****************************************************************
+ #define FN(ARG0, ARG1, ARG2) fn(ARG0, ARG1, ARG2)
+ ^~~~ ^~~~ ^~~~
+ ( ) ( ) ( )
+ This rich location has three ranges, covering "arg0", "arg1",
+ and "arg2", all with caret-printing enabled.
+ The rich location has 6 insertion fix-it hints: each arg
+ has a pair of insertion fix-it hints, suggesting wrapping
+ them with parentheses: one a '(' inserted before,
+ the other a ')' inserted after, added via
+ richloc.add_fixit_insert_before (LOC, "(");
+ and
+ richloc.add_fixit_insert_after (LOC, ")");
+
+ Example H: fix-it hint: removal
+ *******************************
+ struct s {int i};;
+ ^
+ -
+ This rich location has a single range at the stray trailing
+ semicolon, along with a single removal fix-it hint, covering
+ the same range, added via:
+ richloc.add_fixit_remove ();
+
+ Example I: fix-it hint: replace
+ *******************************
+ c = s.colour;
+ ^~~~~~
+ color
+ This rich location has a single range (range 0) covering "colour",
+ and a single "replace" fix-it hint, covering the same range,
+ added via
+ richloc.add_fixit_replace ("color");
+
+ Adding a fix-it hint can fail: for example, attempts to insert content
+ at the transition between two line maps may fail due to there being no
+ source_location (aka location_t) value to express the new location.
+
+ Attempts to add a fix-it hint within a macro expansion will fail.
+
+ The rich_location API handles these failures gracefully, so that
+ diagnostics can attempt to add fix-it hints without each needing
+ extensive checking.
+
+ Fix-it hints within a rich_location are "atomic": if any hints can't
+ be applied, none of them will be (tracked by the m_seen_impossible_fixit
+ flag), and no fix-its hints will be displayed for that rich_location.
+ This implies that diagnostic messages need to be worded in such a way
+ that they make sense whether or not the fix-it hints are displayed,
+ or that richloc.seen_impossible_fixit_p () should be checked before
+ issuing the diagnostics. */
class rich_location
{
@@ -1522,14 +1599,25 @@ class rich_location
/* Methods for adding insertion fix-it hints. */
- /* Suggest inserting NEW_CONTENT at the primary range's caret. */
+ /* Suggest inserting NEW_CONTENT immediately before the primary
+ range's start. */
void
- add_fixit_insert (const char *new_content);
+ add_fixit_insert_before (const char *new_content);
- /* Suggest inserting NEW_CONTENT at WHERE. */
+ /* Suggest inserting NEW_CONTENT immediately before the start of WHERE. */
void
- add_fixit_insert (source_location where,
- const char *new_content);
+ add_fixit_insert_before (source_location where,
+ const char *new_content);
+
+ /* Suggest inserting NEW_CONTENT immediately after the end of the primary
+ range. */
+ void
+ add_fixit_insert_after (const char *new_content);
+
+ /* Suggest inserting NEW_CONTENT immediately after the end of WHERE. */
+ void
+ add_fixit_insert_after (source_location where,
+ const char *new_content);
/* Methods for adding removal fix-it hints. */
@@ -1571,6 +1659,7 @@ class rich_location
private:
bool reject_impossible_fixit (source_location where);
+ void stop_supporting_fixits ();
void add_fixit (fixit_hint *hint);
public:
diff --git a/libcpp/line-map.c b/libcpp/line-map.c
index f69c60c7837..742af0a07bb 100644
--- a/libcpp/line-map.c
+++ b/libcpp/line-map.c
@@ -2109,26 +2109,61 @@ rich_location::set_range (line_maps * /*set*/, unsigned int idx,
/* Methods for adding insertion fix-it hints. */
/* Add a fixit-hint, suggesting insertion of NEW_CONTENT
- at the primary range's caret location. */
+ immediately before the primary range's start location. */
void
-rich_location::add_fixit_insert (const char *new_content)
+rich_location::add_fixit_insert_before (const char *new_content)
{
- add_fixit_insert (get_loc (), new_content);
+ add_fixit_insert_before (get_loc (), new_content);
}
/* Add a fixit-hint, suggesting insertion of NEW_CONTENT
- at WHERE. */
+ immediately before the start of WHERE. */
void
-rich_location::add_fixit_insert (source_location where,
- const char *new_content)
+rich_location::add_fixit_insert_before (source_location where,
+ const char *new_content)
{
- where = get_pure_location (m_line_table, where);
+ source_location start = get_range_from_loc (m_line_table, where).m_start;
- if (reject_impossible_fixit (where))
+ if (reject_impossible_fixit (start))
return;
- add_fixit (new fixit_insert (where, new_content));
+ add_fixit (new fixit_insert (start, new_content));
+}
+
+/* Add a fixit-hint, suggesting insertion of NEW_CONTENT
+ immediately after the primary range's end-point. */
+
+void
+rich_location::add_fixit_insert_after (const char *new_content)
+{
+ add_fixit_insert_after (get_loc (), new_content);
+}
+
+/* Add a fixit-hint, suggesting insertion of NEW_CONTENT
+ immediately after the end-point of WHERE. */
+
+void
+rich_location::add_fixit_insert_after (source_location where,
+ const char *new_content)
+{
+ source_location finish = get_range_from_loc (m_line_table, where).m_finish;
+
+ if (reject_impossible_fixit (finish))
+ return;
+
+ source_location next_loc
+ = linemap_position_for_loc_and_offset (m_line_table, finish, 1);
+
+ /* linemap_position_for_loc_and_offset can fail, if so, it returns
+ its input value. */
+ if (next_loc == finish)
+ {
+ stop_supporting_fixits ();
+ return;
+ }
+
+ add_fixit (new fixit_insert (next_loc, new_content));
}
/* Methods for adding removal fix-it hints. */
@@ -2278,14 +2313,22 @@ rich_location::reject_impossible_fixit (source_location where)
/* Otherwise we have an attempt to add a fix-it with an "awkward"
location: either one that we can't obtain column information
for (within an ordinary map), or one within a macro expansion. */
+ stop_supporting_fixits ();
+ return true;
+}
+
+/* Mark this rich_location as not supporting fixits, purging any that were
+ already added. */
+
+void
+rich_location::stop_supporting_fixits ()
+{
m_seen_impossible_fixit = true;
/* Purge the rich_location of any fix-its that were already added. */
for (unsigned int i = 0; i < m_fixit_hints.count (); i++)
delete get_fixit_hint (i);
m_fixit_hints.truncate (0);
-
- return true;
}
/* Add HINT to the fix-it hints in this rich_location. */