From fe066ce3d8b45a687ddb9ebba6426a3746f3a8ca Mon Sep 17 00:00:00 2001 From: dmalcolm Date: Fri, 2 Sep 2016 18:00:57 +0000 Subject: Introduce class edit_context gcc/ChangeLog: * Makefile.in (OBJS-libcommon): Add edit-context.o. * diagnostic-color.c (color_dict): Add "diff-filename", "diff-hunk", "diff-delete", and "diff-insert". (parse_gcc_colors): Update default value of GCC_COLORS in comment to reflect above changes. * doc/invoke.texi (-fdiagnostics-color): Update description of default GCC_COLORS, and of the supported capabilities. * edit-context.c: New file. * edit-context.h: New file. * input.c (struct fcache): Add field "missing_trailing_newline". (diagnostics_file_cache_forcibly_evict_file): Initialize it to true. (add_file_to_cache_tab): Likewise. (fcache::fcache): Likewise. (get_next_line): Update c->missing_trailing_newline. (location_missing_trailing_newline): New function. * input.h (location_missing_trailing_newline): New decl. * selftest-run-tests.c (selftest::run_tests): Call edit_context_c_tests. * selftest.h (edit_context_c_tests): New decl. libcpp/ChangeLog: * include/line-map.h (rich_location::seen_impossible_fixit_p): New accessor. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@239963 138bc75d-0d04-0410-961f-82ee72b054a4 --- libcpp/include/line-map.h | 1 + 1 file changed, 1 insertion(+) (limited to 'libcpp/include') diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h index bef77957ffe..6b3c474a0de 100644 --- a/libcpp/include/line-map.h +++ b/libcpp/include/line-map.h @@ -1567,6 +1567,7 @@ class rich_location unsigned int get_num_fixit_hints () const { return m_fixit_hints.count (); } fixit_hint *get_fixit_hint (int idx) const { return m_fixit_hints[idx]; } fixit_hint *get_last_fixit_hint () const; + bool seen_impossible_fixit_p () const { return m_seen_impossible_fixit; } private: bool reject_impossible_fixit (source_location where); -- cgit v1.2.1 From 68ef907cd5704cca533b3cdf6db112b973e52b74 Mon Sep 17 00:00:00 2001 From: dmalcolm Date: Tue, 13 Sep 2016 16:08:59 +0000 Subject: 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 --- libcpp/include/line-map.h | 101 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 95 insertions(+), 6 deletions(-) (limited to 'libcpp/include') 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: -- cgit v1.2.1 From d9020fe61291812489bd4bb954c0c04ac088ac6f Mon Sep 17 00:00:00 2001 From: dmalcolm Date: Thu, 15 Sep 2016 23:57:01 +0000 Subject: fix-it hints can't contain newlines I hope to implement newline support within fix-it hints at some point, but currently it's not supported, and leads to misleading diagnostic output, so for now, fail gracefully. gcc/ChangeLog: * diagnostic-show-locus.c (selftest::test_fixit_insert_containing_newline): New function. (selftest::test_fixit_replace_containing_newline): New function. (selftest::diagnostic_show_locus_c_tests): Call the above. libcpp/ChangeLog: * include/line-map.h (class rich_location): Note that newlines aren't supported in fix-it text. * line-map.c (rich_location::add_fixit_insert_before): Reject attempts to add fix-its containing newlines. (rich_location::add_fixit_replace): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@240169 138bc75d-0d04-0410-961f-82ee72b054a4 --- libcpp/include/line-map.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'libcpp/include') diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h index 939bfcc5712..747609d4393 100644 --- a/libcpp/include/line-map.h +++ b/libcpp/include/line-map.h @@ -1551,6 +1551,8 @@ class fixit_hint; Attempts to add a fix-it hint within a macro expansion will fail. + We do not yet support newlines in fix-it text; attempts to do so 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. -- cgit v1.2.1