diff options
author | dmalcolm <dmalcolm@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-09-13 16:08:59 +0000 |
---|---|---|
committer | dmalcolm <dmalcolm@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-09-13 16:08:59 +0000 |
commit | 68ef907cd5704cca533b3cdf6db112b973e52b74 (patch) | |
tree | f49ba2c7c6f8a048ee6c7db0ecc48ec1bbe3d897 /libcpp | |
parent | f339fac19fcd0eb730be8b0bee8f0c5e178ffb8c (diff) | |
download | gcc-68ef907cd5704cca533b3cdf6db112b973e52b74.tar.gz |
fix-it hints: insert_before vs insert_after
The API for adding "insert text" fix-it hints was unclear
about exactly where the text should be inserted relative
to the given insertion point.
This patch clarifies things by renaming the pertinent methods from
richloc.add_fixit_insert
to
richloc.add_fixit_insert_before
and adding:
richloc.add_fixit_insert_after
The latter allows us to consolidate some failure-handling into
class rich_location, rather than having to have every such diagnostic
check for it.
The patch also adds a description of how fix-it hints work to the
comment for class rich_location within libcpp/include/line-map.h.
gcc/c-family/ChangeLog:
* c-common.c (warn_logical_not_parentheses): Replace
rich_location::add_fixit_insert calls with add_fixit_insert_before
and add_fixit_insert_after, eliminating the "next_loc" calculation.
gcc/c/ChangeLog:
* c-parser.c (c_parser_declaration_or_fndef): Update for renaming
of add_fixit_insert to add_fixit_insert_before.
gcc/cp/ChangeLog:
* parser.c (cp_parser_class_specifier_1): Update for renaming of
add_fixit_insert to add_fixit_insert_before.
(cp_parser_class_head): Likewise.
gcc/ChangeLog:
* diagnostic-show-locus.c (selftest::test_one_liner_fixit_insert):
Rename to...
(selftest::test_one_liner_fixit_insert_before): ...this, and update
for renaming of add_fixit_insert to add_fixit_insert_before.
(selftest::test_one_liner_fixit_insert_after): New function.
(selftest::test_one_liner_fixit_validation_adhoc_locations):
Update for renaming of add_fixit_insert to
add_fixit_insert_before.
(selftest::test_one_liner_many_fixits): Likewise.
(selftest::test_diagnostic_show_locus_one_liner): Update for
renaming, call new test function.
(selftest::test_diagnostic_show_locus_fixit_lines): Update for
renaming of add_fixit_insert to add_fixit_insert_before.
(selftest::test_fixit_consolidation): Likewise.
* diagnostic.c (selftest::test_print_parseable_fixits_insert):
Likewise.
* edit-context.c (selftest::test_applying_fixits_insert): Rename
to...
(selftest::test_applying_fixits_insert_before): ...this.
(selftest::test_applying_fixits_insert): Update for renaming of
add_fixit_insert to add_fixit_insert_before.
(selftest::test_applying_fixits_insert_after): New function.
(selftest::test_applying_fixits_insert_after_at_line_end): New
function.
(selftest::test_applying_fixits_insert_after_failure): New
function.
(selftest::test_applying_fixits_multiple): Update for renaming of
add_fixit_insert to add_fixit_insert_before.
(selftest::change_line): Likewise.
(selftest::test_applying_fixits_unreadable_file): Likewise.
(selftest::test_applying_fixits_line_out_of_range): Likewise.
(selftest::test_applying_fixits_column_validation): Likewise.
(selftest::test_applying_fixits_column_validation): Likewise.
(selftest::edit_context_c_tests): Update for renamed test
function; call new test functions.
gcc/testsuite/ChangeLog:
* gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
(test_show_locus): Replace rich_location::add_fixit_insert calls
with add_fixit_insert_before and add_fixit_insert_after.
libcpp/ChangeLog:
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@240115 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libcpp')
-rw-r--r-- | libcpp/ChangeLog | 20 | ||||
-rw-r--r-- | libcpp/include/line-map.h | 101 | ||||
-rw-r--r-- | libcpp/line-map.c | 65 |
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. */ |