mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-03 07:10:28 +08:00
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. From-SVN: r240115
This commit is contained in:
parent
c77b8713a7
commit
254830bab2
@ -1,3 +1,41 @@
|
||||
2016-09-13 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2016-09-13 Pat Haugen <pthaugen@us.ibm.com>
|
||||
|
||||
PR tree-optimization/77536
|
||||
|
@ -1,3 +1,9 @@
|
||||
2016-09-13 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2016-09-13 Jason Merrill <jason@redhat.com>
|
||||
Tom de Vries <tom@codesourcery.com>
|
||||
|
||||
|
@ -1544,11 +1544,8 @@ warn_logical_not_parentheses (location_t location, enum tree_code code,
|
||||
{
|
||||
location_t lhs_loc = EXPR_LOCATION (lhs);
|
||||
rich_location richloc (line_table, lhs_loc);
|
||||
richloc.add_fixit_insert (lhs_loc, "(");
|
||||
location_t finish = get_finish (lhs_loc);
|
||||
location_t next_loc
|
||||
= linemap_position_for_loc_and_offset (line_table, finish, 1);
|
||||
richloc.add_fixit_insert (next_loc, ")");
|
||||
richloc.add_fixit_insert_before (lhs_loc, "(");
|
||||
richloc.add_fixit_insert_after (lhs_loc, ")");
|
||||
inform_at_rich_loc (&richloc, "add parentheses around left hand side "
|
||||
"expression to silence this warning");
|
||||
}
|
||||
|
@ -1,3 +1,8 @@
|
||||
2016-09-13 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* c-parser.c (c_parser_declaration_or_fndef): Update for renaming
|
||||
of add_fixit_insert to add_fixit_insert_before.
|
||||
|
||||
2016-09-13 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
* c-typeck.c (build_unary_op): Rename FLAG parameter to NOCONVERT. Use
|
||||
|
@ -1685,7 +1685,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
|
||||
if (tag_exists_p (RECORD_TYPE, name))
|
||||
{
|
||||
/* This is not C++ with its implicit typedef. */
|
||||
richloc.add_fixit_insert ("struct ");
|
||||
richloc.add_fixit_insert_before ("struct ");
|
||||
error_at_rich_loc (&richloc,
|
||||
"unknown type name %qE;"
|
||||
" use %<struct%> keyword to refer to the type",
|
||||
@ -1693,7 +1693,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
|
||||
}
|
||||
else if (tag_exists_p (UNION_TYPE, name))
|
||||
{
|
||||
richloc.add_fixit_insert ("union ");
|
||||
richloc.add_fixit_insert_before ("union ");
|
||||
error_at_rich_loc (&richloc,
|
||||
"unknown type name %qE;"
|
||||
" use %<union%> keyword to refer to the type",
|
||||
@ -1701,7 +1701,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
|
||||
}
|
||||
else if (tag_exists_p (ENUMERAL_TYPE, name))
|
||||
{
|
||||
richloc.add_fixit_insert ("enum ");
|
||||
richloc.add_fixit_insert_before ("enum ");
|
||||
error_at_rich_loc (&richloc,
|
||||
"unknown type name %qE;"
|
||||
" use %<enum%> keyword to refer to the type",
|
||||
|
@ -1,3 +1,9 @@
|
||||
2016-09-13 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* parser.c (cp_parser_class_specifier_1): Update for renaming of
|
||||
add_fixit_insert to add_fixit_insert_before.
|
||||
(cp_parser_class_head): Likewise.
|
||||
|
||||
2016-09-12 Bernd Edlinger <bernd.edlinger@hotmail.de>
|
||||
|
||||
PR c++/77496
|
||||
|
@ -21594,7 +21594,7 @@ cp_parser_class_specifier_1 (cp_parser* parser)
|
||||
next_loc = linemap_position_for_loc_and_offset (line_table, loc, 1);
|
||||
|
||||
rich_location richloc (line_table, next_loc);
|
||||
richloc.add_fixit_insert (next_loc, ";");
|
||||
richloc.add_fixit_insert_before (next_loc, ";");
|
||||
|
||||
if (CLASSTYPE_DECLARED_CLASS (type))
|
||||
error_at_rich_loc (&richloc,
|
||||
@ -22037,7 +22037,8 @@ cp_parser_class_head (cp_parser* parser,
|
||||
class_head_start_location,
|
||||
get_finish (type_start_token->location));
|
||||
rich_location richloc (line_table, reported_loc);
|
||||
richloc.add_fixit_insert (class_head_start_location, "template <> ");
|
||||
richloc.add_fixit_insert_before (class_head_start_location,
|
||||
"template <> ");
|
||||
error_at_rich_loc
|
||||
(&richloc,
|
||||
"an explicit specialization must be preceded by %<template <>%>");
|
||||
|
@ -1661,12 +1661,12 @@ test_one_liner_multiple_carets_and_ranges ()
|
||||
/* Insertion fix-it hint: adding an "&" to the front of "bar.field". */
|
||||
|
||||
static void
|
||||
test_one_liner_fixit_insert ()
|
||||
test_one_liner_fixit_insert_before ()
|
||||
{
|
||||
test_diagnostic_context dc;
|
||||
location_t caret = linemap_position_for_column (line_table, 7);
|
||||
rich_location richloc (line_table, caret);
|
||||
richloc.add_fixit_insert ("&");
|
||||
richloc.add_fixit_insert_before ("&");
|
||||
diagnostic_show_locus (&dc, &richloc, DK_ERROR);
|
||||
ASSERT_STREQ ("\n"
|
||||
" foo = bar.field;\n"
|
||||
@ -1675,6 +1675,25 @@ test_one_liner_fixit_insert ()
|
||||
pp_formatted_text (dc.printer));
|
||||
}
|
||||
|
||||
/* Insertion fix-it hint: adding a "[0]" after "foo". */
|
||||
|
||||
static void
|
||||
test_one_liner_fixit_insert_after ()
|
||||
{
|
||||
test_diagnostic_context dc;
|
||||
location_t start = linemap_position_for_column (line_table, 1);
|
||||
location_t finish = linemap_position_for_column (line_table, 3);
|
||||
location_t foo = make_location (start, start, finish);
|
||||
rich_location richloc (line_table, foo);
|
||||
richloc.add_fixit_insert_after ("[0]");
|
||||
diagnostic_show_locus (&dc, &richloc, DK_ERROR);
|
||||
ASSERT_STREQ ("\n"
|
||||
" foo = bar.field;\n"
|
||||
" ^~~\n"
|
||||
" [0]\n",
|
||||
pp_formatted_text (dc.printer));
|
||||
}
|
||||
|
||||
/* Removal fix-it hint: removal of the ".field". */
|
||||
|
||||
static void
|
||||
@ -1785,7 +1804,7 @@ test_one_liner_fixit_validation_adhoc_locations ()
|
||||
/* Insert. */
|
||||
{
|
||||
rich_location richloc (line_table, loc);
|
||||
richloc.add_fixit_insert (loc, "test");
|
||||
richloc.add_fixit_insert_before (loc, "test");
|
||||
/* It should not have been discarded by the validator. */
|
||||
ASSERT_EQ (1, richloc.get_num_fixit_hints ());
|
||||
|
||||
@ -1843,7 +1862,7 @@ test_one_liner_many_fixits ()
|
||||
location_t equals = linemap_position_for_column (line_table, 5);
|
||||
rich_location richloc (line_table, equals);
|
||||
for (int i = 0; i < 19; i++)
|
||||
richloc.add_fixit_insert ("a");
|
||||
richloc.add_fixit_insert_before ("a");
|
||||
ASSERT_EQ (19, richloc.get_num_fixit_hints ());
|
||||
diagnostic_show_locus (&dc, &richloc, DK_ERROR);
|
||||
ASSERT_STREQ ("\n"
|
||||
@ -1898,7 +1917,8 @@ test_diagnostic_show_locus_one_liner (const line_table_case &case_)
|
||||
test_one_liner_simple_caret ();
|
||||
test_one_liner_caret_and_range ();
|
||||
test_one_liner_multiple_carets_and_ranges ();
|
||||
test_one_liner_fixit_insert ();
|
||||
test_one_liner_fixit_insert_before ();
|
||||
test_one_liner_fixit_insert_after ();
|
||||
test_one_liner_fixit_remove ();
|
||||
test_one_liner_fixit_replace ();
|
||||
test_one_liner_fixit_replace_non_equal_range ();
|
||||
@ -1949,7 +1969,7 @@ test_diagnostic_show_locus_fixit_lines (const line_table_case &case_)
|
||||
const location_t colon
|
||||
= linemap_position_for_line_and_column (line_table, ord_map, 2, 25);
|
||||
rich_location richloc (line_table, colon);
|
||||
richloc.add_fixit_insert (x, ".");
|
||||
richloc.add_fixit_insert_before (x, ".");
|
||||
richloc.add_fixit_replace (colon, "=");
|
||||
diagnostic_show_locus (&dc, &richloc, DK_ERROR);
|
||||
ASSERT_STREQ ("\n"
|
||||
@ -1970,7 +1990,7 @@ test_diagnostic_show_locus_fixit_lines (const line_table_case &case_)
|
||||
const location_t colon
|
||||
= linemap_position_for_line_and_column (line_table, ord_map, 6, 25);
|
||||
rich_location richloc (line_table, colon);
|
||||
richloc.add_fixit_insert (y, ".");
|
||||
richloc.add_fixit_insert_before (y, ".");
|
||||
richloc.add_fixit_replace (colon, "=");
|
||||
diagnostic_show_locus (&dc, &richloc, DK_ERROR);
|
||||
ASSERT_STREQ ("\n"
|
||||
@ -2012,8 +2032,8 @@ test_fixit_consolidation (const line_table_case &case_)
|
||||
/* Insert + insert. */
|
||||
{
|
||||
rich_location richloc (line_table, caret);
|
||||
richloc.add_fixit_insert (c10, "foo");
|
||||
richloc.add_fixit_insert (c15, "bar");
|
||||
richloc.add_fixit_insert_before (c10, "foo");
|
||||
richloc.add_fixit_insert_before (c15, "bar");
|
||||
|
||||
if (c15 > LINE_MAP_MAX_LOCATION_WITH_COLS)
|
||||
/* Bogus column info for 2nd fixit, so no fixits. */
|
||||
@ -2026,7 +2046,7 @@ test_fixit_consolidation (const line_table_case &case_)
|
||||
/* Insert + replace. */
|
||||
{
|
||||
rich_location richloc (line_table, caret);
|
||||
richloc.add_fixit_insert (c10, "foo");
|
||||
richloc.add_fixit_insert_before (c10, "foo");
|
||||
richloc.add_fixit_replace (source_range::from_locations (c15, c17),
|
||||
"bar");
|
||||
|
||||
@ -2043,7 +2063,7 @@ test_fixit_consolidation (const line_table_case &case_)
|
||||
rich_location richloc (line_table, caret);
|
||||
richloc.add_fixit_replace (source_range::from_locations (c10, c15),
|
||||
"bar");
|
||||
richloc.add_fixit_insert (c17, "foo");
|
||||
richloc.add_fixit_insert_before (c17, "foo");
|
||||
|
||||
if (c17 > LINE_MAP_MAX_LOCATION_WITH_COLS)
|
||||
/* Bogus column info for 2nd fixit, so no fixits. */
|
||||
|
@ -1504,7 +1504,7 @@ test_print_parseable_fixits_insert ()
|
||||
linemap_line_start (line_table, 5, 100);
|
||||
linemap_add (line_table, LC_LEAVE, false, NULL, 0);
|
||||
location_t where = linemap_position_for_column (line_table, 10);
|
||||
richloc.add_fixit_insert (where, "added content");
|
||||
richloc.add_fixit_insert_before (where, "added content");
|
||||
|
||||
print_parseable_fixits (&pp, &richloc);
|
||||
ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
|
||||
|
@ -918,10 +918,10 @@ test_get_content ()
|
||||
}
|
||||
}
|
||||
|
||||
/* Test applying an "insert" fixit. */
|
||||
/* Test applying an "insert" fixit, using insert_before. */
|
||||
|
||||
static void
|
||||
test_applying_fixits_insert (const line_table_case &case_)
|
||||
test_applying_fixits_insert_before (const line_table_case &case_)
|
||||
{
|
||||
/* Create a tempfile and write some text to it.
|
||||
.........................0000000001111111.
|
||||
@ -937,7 +937,7 @@ test_applying_fixits_insert (const line_table_case &case_)
|
||||
/* Add a comment in front of "bar.field". */
|
||||
location_t start = linemap_position_for_column (line_table, 7);
|
||||
rich_location richloc (line_table, start);
|
||||
richloc.add_fixit_insert ("/* inserted */");
|
||||
richloc.add_fixit_insert_before ("/* inserted */");
|
||||
|
||||
if (start > LINE_MAP_MAX_LOCATION_WITH_COLS)
|
||||
return;
|
||||
@ -971,6 +971,142 @@ test_applying_fixits_insert (const line_table_case &case_)
|
||||
" /* after */\n", diff);
|
||||
}
|
||||
|
||||
/* Test applying an "insert" fixit, using insert_after, with
|
||||
a range of length > 1 (to ensure that the end-point of
|
||||
the input range is used). */
|
||||
|
||||
static void
|
||||
test_applying_fixits_insert_after (const line_table_case &case_)
|
||||
{
|
||||
/* Create a tempfile and write some text to it.
|
||||
.........................0000000001111111.
|
||||
.........................1234567890123456. */
|
||||
const char *old_content = ("/* before */\n"
|
||||
"foo = bar.field;\n"
|
||||
"/* after */\n");
|
||||
temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
|
||||
const char *filename = tmp.get_filename ();
|
||||
line_table_test ltt (case_);
|
||||
linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 2);
|
||||
|
||||
/* Add a comment after "field". */
|
||||
location_t start = linemap_position_for_column (line_table, 11);
|
||||
location_t finish = linemap_position_for_column (line_table, 15);
|
||||
location_t field = make_location (start, start, finish);
|
||||
rich_location richloc (line_table, field);
|
||||
richloc.add_fixit_insert_after ("/* inserted */");
|
||||
|
||||
if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
|
||||
return;
|
||||
|
||||
/* Verify that the text was inserted after the end of "field". */
|
||||
edit_context edit;
|
||||
edit.add_fixits (&richloc);
|
||||
auto_free <char *> new_content = edit.get_content (filename);
|
||||
ASSERT_STREQ ("/* before */\n"
|
||||
"foo = bar.field/* inserted */;\n"
|
||||
"/* after */\n", new_content);
|
||||
|
||||
/* Verify diff. */
|
||||
auto_free <char *> diff = edit.generate_diff (false);
|
||||
ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
|
||||
" /* before */\n"
|
||||
"-foo = bar.field;\n"
|
||||
"+foo = bar.field/* inserted */;\n"
|
||||
" /* after */\n", diff);
|
||||
}
|
||||
|
||||
/* Test applying an "insert" fixit, using insert_after at the end of
|
||||
a line (contrast with test_applying_fixits_insert_after_failure
|
||||
below). */
|
||||
|
||||
static void
|
||||
test_applying_fixits_insert_after_at_line_end (const line_table_case &case_)
|
||||
{
|
||||
/* Create a tempfile and write some text to it.
|
||||
.........................0000000001111111.
|
||||
.........................1234567890123456. */
|
||||
const char *old_content = ("/* before */\n"
|
||||
"foo = bar.field;\n"
|
||||
"/* after */\n");
|
||||
temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
|
||||
const char *filename = tmp.get_filename ();
|
||||
line_table_test ltt (case_);
|
||||
linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 2);
|
||||
|
||||
/* Add a comment after the semicolon. */
|
||||
location_t loc = linemap_position_for_column (line_table, 16);
|
||||
rich_location richloc (line_table, loc);
|
||||
richloc.add_fixit_insert_after ("/* inserted */");
|
||||
|
||||
if (loc > LINE_MAP_MAX_LOCATION_WITH_COLS)
|
||||
return;
|
||||
|
||||
edit_context edit;
|
||||
edit.add_fixits (&richloc);
|
||||
auto_free <char *> new_content = edit.get_content (filename);
|
||||
ASSERT_STREQ ("/* before */\n"
|
||||
"foo = bar.field;/* inserted */\n"
|
||||
"/* after */\n", new_content);
|
||||
|
||||
/* Verify diff. */
|
||||
auto_free <char *> diff = edit.generate_diff (false);
|
||||
ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
|
||||
" /* before */\n"
|
||||
"-foo = bar.field;\n"
|
||||
"+foo = bar.field;/* inserted */\n"
|
||||
" /* after */\n", diff);
|
||||
}
|
||||
|
||||
/* Test of a failed attempt to apply an "insert" fixit, using insert_after,
|
||||
due to the relevant linemap ending. Contrast with
|
||||
test_applying_fixits_insert_after_at_line_end above. */
|
||||
|
||||
static void
|
||||
test_applying_fixits_insert_after_failure (const line_table_case &case_)
|
||||
{
|
||||
/* Create a tempfile and write some text to it.
|
||||
.........................0000000001111111.
|
||||
.........................1234567890123456. */
|
||||
const char *old_content = ("/* before */\n"
|
||||
"foo = bar.field;\n"
|
||||
"/* after */\n");
|
||||
temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
|
||||
const char *filename = tmp.get_filename ();
|
||||
line_table_test ltt (case_);
|
||||
linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 2);
|
||||
|
||||
/* Add a comment after the semicolon. */
|
||||
location_t loc = linemap_position_for_column (line_table, 16);
|
||||
rich_location richloc (line_table, loc);
|
||||
|
||||
/* We want a failure of linemap_position_for_loc_and_offset.
|
||||
We can do this by starting a new linemap at line 3, so that
|
||||
there is no appropriate location value for the insertion point
|
||||
within the linemap for line 2. */
|
||||
linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 3);
|
||||
|
||||
/* The failure fails to happen at the transition point from
|
||||
packed ranges to unpacked ranges (where there are some "spare"
|
||||
location_t values). Skip the test there. */
|
||||
if (loc >= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES)
|
||||
return;
|
||||
|
||||
/* Offsetting "loc" should now fail (by returning the input loc. */
|
||||
ASSERT_EQ (loc, linemap_position_for_loc_and_offset (line_table, loc, 1));
|
||||
|
||||
/* Hence attempting to use add_fixit_insert_after at the end of the line
|
||||
should now fail. */
|
||||
richloc.add_fixit_insert_after ("/* inserted */");
|
||||
ASSERT_TRUE (richloc.seen_impossible_fixit_p ());
|
||||
|
||||
edit_context edit;
|
||||
edit.add_fixits (&richloc);
|
||||
ASSERT_FALSE (edit.valid_p ());
|
||||
ASSERT_EQ (NULL, edit.get_content (filename));
|
||||
ASSERT_EQ (NULL, edit.generate_diff (false));
|
||||
}
|
||||
|
||||
/* Test applying a "replace" fixit that grows the affected line. */
|
||||
|
||||
static void
|
||||
@ -1135,11 +1271,11 @@ test_applying_fixits_multiple (const line_table_case &case_)
|
||||
|
||||
/* Add a comment in front of "bar.field". */
|
||||
rich_location insert_a (line_table, c7);
|
||||
insert_a.add_fixit_insert (c7, "/* alpha */");
|
||||
insert_a.add_fixit_insert_before (c7, "/* alpha */");
|
||||
|
||||
/* Add a comment after "bar.field;". */
|
||||
rich_location insert_b (line_table, c17);
|
||||
insert_b.add_fixit_insert (c17, "/* beta */");
|
||||
insert_b.add_fixit_insert_before (c17, "/* beta */");
|
||||
|
||||
/* Replace "bar" with "pub". */
|
||||
rich_location replace_a (line_table, c7);
|
||||
@ -1203,7 +1339,7 @@ change_line (edit_context &edit, int line_num)
|
||||
}
|
||||
|
||||
rich_location insert (line_table, loc);
|
||||
insert.add_fixit_insert ("CHANGED: ");
|
||||
insert.add_fixit_insert_before ("CHANGED: ");
|
||||
edit.add_fixits (&insert);
|
||||
return loc;
|
||||
}
|
||||
@ -1371,8 +1507,8 @@ test_applying_fixits_unreadable_file ()
|
||||
location_t loc = linemap_position_for_column (line_table, 1);
|
||||
|
||||
rich_location insert (line_table, loc);
|
||||
insert.add_fixit_insert ("change 1");
|
||||
insert.add_fixit_insert ("change 2");
|
||||
insert.add_fixit_insert_before ("change 1");
|
||||
insert.add_fixit_insert_before ("change 2");
|
||||
|
||||
edit_context edit;
|
||||
/* Attempting to add the fixits affecting the unreadable file
|
||||
@ -1403,7 +1539,7 @@ test_applying_fixits_line_out_of_range ()
|
||||
location_t loc = linemap_position_for_column (line_table, 1);
|
||||
|
||||
rich_location insert (line_table, loc);
|
||||
insert.add_fixit_insert ("change");
|
||||
insert.add_fixit_insert_before ("change");
|
||||
|
||||
/* Verify that attempting the insertion puts an edit_context
|
||||
into an invalid state. */
|
||||
@ -1440,7 +1576,7 @@ test_applying_fixits_column_validation (const line_table_case &case_)
|
||||
/* Verify inserting at the end of the line. */
|
||||
{
|
||||
rich_location richloc (line_table, c11);
|
||||
richloc.add_fixit_insert (c15, " change");
|
||||
richloc.add_fixit_insert_before (c15, " change");
|
||||
|
||||
/* Col 15 is at the end of the line, so the insertion
|
||||
should succeed. */
|
||||
@ -1456,7 +1592,7 @@ test_applying_fixits_column_validation (const line_table_case &case_)
|
||||
/* Verify inserting beyond the end of the line. */
|
||||
{
|
||||
rich_location richloc (line_table, c11);
|
||||
richloc.add_fixit_insert (c16, " change");
|
||||
richloc.add_fixit_insert_before (c16, " change");
|
||||
|
||||
/* Col 16 is beyond the end of the line, so the insertion
|
||||
should fail gracefully. */
|
||||
@ -1510,7 +1646,10 @@ void
|
||||
edit_context_c_tests ()
|
||||
{
|
||||
test_get_content ();
|
||||
for_each_line_table_case (test_applying_fixits_insert);
|
||||
for_each_line_table_case (test_applying_fixits_insert_before);
|
||||
for_each_line_table_case (test_applying_fixits_insert_after);
|
||||
for_each_line_table_case (test_applying_fixits_insert_after_at_line_end);
|
||||
for_each_line_table_case (test_applying_fixits_insert_after_failure);
|
||||
for_each_line_table_case (test_applying_fixits_growing_replace);
|
||||
for_each_line_table_case (test_applying_fixits_shrinking_replace);
|
||||
for_each_line_table_case (test_applying_fixits_remove);
|
||||
|
@ -1,3 +1,9 @@
|
||||
2016-09-13 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2016-09-13 Jason Merrill <jason@redhat.com>
|
||||
Tom de Vries <tom@codesourcery.com>
|
||||
|
||||
|
@ -263,8 +263,8 @@ test_show_locus (function *fun)
|
||||
location_t start = get_loc (line, 19);
|
||||
location_t finish = get_loc (line, 22);
|
||||
rich_location richloc (line_table, make_location (start, start, finish));
|
||||
richloc.add_fixit_insert (start, "{");
|
||||
richloc.add_fixit_insert (get_loc (line, 23), "}");
|
||||
richloc.add_fixit_insert_before ("{");
|
||||
richloc.add_fixit_insert_after ("}");
|
||||
warning_at_rich_loc (&richloc, 0, "example of insertion hints");
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user