Add gcc_rich_location::add_fixit_insert_formatted
This patch adds a support function to class gcc_rich_location to make it easier for fix-it hints to use idiomatic C/C++ indentation, for use by the patch for PR c++/85523. gcc/ChangeLog: PR c++/85523 * gcc-rich-location.c (blank_line_before_p): New function. (use_new_line): New function. (gcc_rich_location::add_fixit_insert_formatted): New function. * gcc-rich-location.h (gcc_rich_location::add_fixit_insert_formatted): New function. gcc/testsuite/ChangeLog: PR c++/85523 * gcc.dg/plugin/diagnostic-test-show-locus-generate-patch.c (test_add_fixit_insert_formatted_single_line): New function. (test_add_fixit_insert_formatted_multiline): New function. Extend expected output of generated patch to include fix-it hints for these. * gcc.dg/plugin/diagnostic_plugin_test_show_locus.c: Include "gcc-rich-location.h". Add test coverage for gcc_rich_location::add_fixit_insert_formatted. From-SVN: r259783
This commit is contained in:
parent
47ae164c05
commit
1a3a7b4eeb
6 changed files with 224 additions and 0 deletions
|
@ -1,3 +1,12 @@
|
|||
2018-04-30 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR c++/85523
|
||||
* gcc-rich-location.c (blank_line_before_p): New function.
|
||||
(use_new_line): New function.
|
||||
(gcc_rich_location::add_fixit_insert_formatted): New function.
|
||||
* gcc-rich-location.h
|
||||
(gcc_rich_location::add_fixit_insert_formatted): New function.
|
||||
|
||||
2018-04-30 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* selftest.c (assert_streq): Rename "expected" and "actual" to
|
||||
|
|
|
@ -69,3 +69,114 @@ gcc_rich_location::add_fixit_misspelled_id (location_t misspelled_token_loc,
|
|||
|
||||
add_fixit_replace (misspelled_token_loc, IDENTIFIER_POINTER (hint_id));
|
||||
}
|
||||
|
||||
/* Return true if there is nothing on LOC's line before LOC. */
|
||||
|
||||
static bool
|
||||
blank_line_before_p (location_t loc)
|
||||
{
|
||||
expanded_location exploc = expand_location (loc);
|
||||
char_span line = location_get_source_line (exploc.file, exploc.line);
|
||||
if (!line)
|
||||
return false;
|
||||
if (line.length () < (size_t)exploc.column)
|
||||
return false;
|
||||
/* Columns are 1-based. */
|
||||
for (int column = 1; column < exploc.column; ++column)
|
||||
if (!ISSPACE (line[column - 1]))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Subroutine of gcc_rich_location::add_fixit_insert_formatted.
|
||||
Return true if we should add the content on its own line,
|
||||
false otherwise.
|
||||
If true is returned then *OUT_START_OF_LINE is written to. */
|
||||
|
||||
static bool
|
||||
use_new_line (location_t insertion_point, location_t indent,
|
||||
location_t *out_start_of_line)
|
||||
{
|
||||
if (indent == UNKNOWN_LOCATION)
|
||||
return false;
|
||||
const line_map *indent_map = linemap_lookup (line_table, indent);
|
||||
if (linemap_macro_expansion_map_p (indent_map))
|
||||
return false;
|
||||
|
||||
if (!blank_line_before_p (insertion_point))
|
||||
return false;
|
||||
|
||||
/* Locate the start of the line containing INSERTION_POINT. */
|
||||
const line_map *insertion_point_map
|
||||
= linemap_lookup (line_table, insertion_point);
|
||||
if (linemap_macro_expansion_map_p (insertion_point_map))
|
||||
return false;
|
||||
const line_map_ordinary *ordmap
|
||||
= linemap_check_ordinary (insertion_point_map);
|
||||
expanded_location exploc_insertion_point = expand_location (insertion_point);
|
||||
location_t start_of_line
|
||||
= linemap_position_for_line_and_column (line_table, ordmap,
|
||||
exploc_insertion_point.line, 1);
|
||||
*out_start_of_line = start_of_line;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Add a fix-it hint suggesting the insertion of CONTENT before
|
||||
INSERTION_POINT.
|
||||
|
||||
Attempt to handle formatting: if INSERTION_POINT is the first thing on
|
||||
its line, and INDENT is sufficiently sane, then add CONTENT on its own
|
||||
line, using the indentation of INDENT.
|
||||
Otherwise, add CONTENT directly before INSERTION_POINT.
|
||||
|
||||
For example, adding "CONTENT;" with the closing brace as the insertion
|
||||
point and "INDENT;" as the indentation point:
|
||||
|
||||
if ()
|
||||
{
|
||||
INDENT;
|
||||
}
|
||||
|
||||
would lead to:
|
||||
|
||||
if ()
|
||||
{
|
||||
INDENT;
|
||||
CONTENT;
|
||||
}
|
||||
|
||||
but adding it to:
|
||||
|
||||
if () {INDENT;}
|
||||
|
||||
would lead to:
|
||||
|
||||
if () {INDENT;CONTENT;}
|
||||
*/
|
||||
|
||||
void
|
||||
gcc_rich_location::add_fixit_insert_formatted (const char *content,
|
||||
location_t insertion_point,
|
||||
location_t indent)
|
||||
{
|
||||
location_t start_of_line;
|
||||
if (use_new_line (insertion_point, indent, &start_of_line))
|
||||
{
|
||||
/* Add CONTENT on its own line, using the indentation of INDENT. */
|
||||
|
||||
/* Generate an insertion string, indenting by the amount INDENT
|
||||
was indented. */
|
||||
int indent_column = LOCATION_COLUMN (get_start (indent));
|
||||
pretty_printer tmp_pp;
|
||||
pretty_printer *pp = &tmp_pp;
|
||||
/* Columns are 1-based. */
|
||||
for (int column = 1; column < indent_column; ++column)
|
||||
pp_space (pp);
|
||||
pp_string (pp, content);
|
||||
pp_newline (pp);
|
||||
|
||||
add_fixit_insert_before (start_of_line, pp_formatted_text (pp));
|
||||
}
|
||||
else
|
||||
add_fixit_insert_before (insertion_point, content);
|
||||
}
|
||||
|
|
|
@ -61,6 +61,42 @@ class gcc_rich_location : public rich_location
|
|||
Implemented in diagnostic-show-locus.c. */
|
||||
|
||||
bool add_location_if_nearby (location_t loc);
|
||||
|
||||
/* Add a fix-it hint suggesting the insertion of CONTENT before
|
||||
INSERTION_POINT.
|
||||
|
||||
Attempt to handle formatting: if INSERTION_POINT is the first thing on
|
||||
its line, and INDENT is sufficiently sane, then add CONTENT on its own
|
||||
line, using the indentation of INDENT.
|
||||
Otherwise, add CONTENT directly before INSERTION_POINT.
|
||||
|
||||
For example, adding "CONTENT;" with the closing brace as the insertion
|
||||
point and using "INDENT;" for indentation:
|
||||
|
||||
if ()
|
||||
{
|
||||
INDENT;
|
||||
}
|
||||
|
||||
would lead to:
|
||||
|
||||
if ()
|
||||
{
|
||||
INDENT;
|
||||
CONTENT;
|
||||
}
|
||||
|
||||
but adding it to:
|
||||
|
||||
if () {INDENT;}
|
||||
|
||||
would lead to:
|
||||
|
||||
if () {INDENT;CONTENT;}
|
||||
*/
|
||||
void add_fixit_insert_formatted (const char *content,
|
||||
location_t insertion_point,
|
||||
location_t indent);
|
||||
};
|
||||
|
||||
#endif /* GCC_RICH_LOCATION_H */
|
||||
|
|
|
@ -1,3 +1,15 @@
|
|||
2018-04-30 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR c++/85523
|
||||
* gcc.dg/plugin/diagnostic-test-show-locus-generate-patch.c
|
||||
(test_add_fixit_insert_formatted_single_line): New function.
|
||||
(test_add_fixit_insert_formatted_multiline): New function.
|
||||
Extend expected output of generated patch to include fix-it hints
|
||||
for these.
|
||||
* gcc.dg/plugin/diagnostic_plugin_test_show_locus.c: Include
|
||||
"gcc-rich-location.h". Add test coverage for
|
||||
gcc_rich_location::add_fixit_insert_formatted.
|
||||
|
||||
2018-04-30 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
|
||||
|
|
|
@ -64,6 +64,21 @@ void test_mutually_exclusive_suggestions (void)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* Unit tests for add_fixit_insert_formatted. */
|
||||
|
||||
void test_add_fixit_insert_formatted_single_line (void)
|
||||
{
|
||||
{}
|
||||
}
|
||||
|
||||
void test_add_fixit_insert_formatted_multiline (void)
|
||||
{
|
||||
if (1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Verify the output from -fdiagnostics-generate-patch.
|
||||
We expect a header, containing the filename. This is the absolute path,
|
||||
so we can only capture it via regexps. */
|
||||
|
@ -108,4 +123,21 @@ void test_mutually_exclusive_suggestions (void)
|
|||
case 'b':
|
||||
x = b;
|
||||
}
|
||||
@@ -68,7 +69,7 @@
|
||||
|
||||
void test_add_fixit_insert_formatted_single_line (void)
|
||||
{
|
||||
- {}
|
||||
+ {INSERTED-CONTENT}
|
||||
}
|
||||
|
||||
void test_add_fixit_insert_formatted_multiline (void)
|
||||
@@ -76,6 +77,7 @@
|
||||
if (1)
|
||||
{
|
||||
}
|
||||
+ INSERTED-CONTENT
|
||||
}
|
||||
|
||||
|
||||
{ dg-end-multiline-output "" } */
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#include "diagnostic.h"
|
||||
#include "context.h"
|
||||
#include "print-tree.h"
|
||||
#include "gcc-rich-location.h"
|
||||
|
||||
int plugin_is_GPL_compatible;
|
||||
|
||||
|
@ -333,6 +334,29 @@ test_show_locus (function *fun)
|
|||
}
|
||||
}
|
||||
|
||||
/* Tests of gcc_rich_location::add_fixit_insert_formatted. */
|
||||
|
||||
if (0 == strcmp (fnname, "test_add_fixit_insert_formatted_single_line"))
|
||||
{
|
||||
const int line = fnstart_line + 1;
|
||||
location_t insertion_point = get_loc (line, 3);
|
||||
location_t indent = get_loc (line, 2);
|
||||
gcc_rich_location richloc (insertion_point);
|
||||
richloc.add_fixit_insert_formatted ("INSERTED-CONTENT",
|
||||
insertion_point, indent);
|
||||
inform (&richloc, "single-line insertion");
|
||||
}
|
||||
|
||||
if (0 == strcmp (fnname, "test_add_fixit_insert_formatted_multiline"))
|
||||
{
|
||||
location_t insertion_point = fun->function_end_locus;
|
||||
location_t indent = get_loc (fnstart_line + 1, 2);
|
||||
gcc_rich_location richloc (insertion_point);
|
||||
richloc.add_fixit_insert_formatted ("INSERTED-CONTENT",
|
||||
insertion_point, indent);
|
||||
inform (&richloc, "multiline insertion");
|
||||
}
|
||||
|
||||
/* Example of two carets where both carets appear to have an off-by-one
|
||||
error appearing one column early.
|
||||
Seen with gfortran.dg/associate_5.f03.
|
||||
|
|
Loading…
Add table
Reference in a new issue