diff options
author | David Malcolm <dmalcolm@redhat.com> | 2018-05-01 00:10:10 +0000 |
---|---|---|
committer | David Malcolm <dmalcolm@gcc.gnu.org> | 2018-05-01 00:10:10 +0000 |
commit | 1a3a7b4eeb0444148adc4f007b91e120814c4cc5 (patch) | |
tree | ea1a9a931bb387718caee06b1c2785faf6296e9c /gcc/gcc-rich-location.c | |
parent | 47ae164c051c575234f4bef916f10346765d9565 (diff) | |
download | gcc-1a3a7b4eeb0444148adc4f007b91e120814c4cc5.zip gcc-1a3a7b4eeb0444148adc4f007b91e120814c4cc5.tar.gz gcc-1a3a7b4eeb0444148adc4f007b91e120814c4cc5.tar.bz2 |
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
Diffstat (limited to 'gcc/gcc-rich-location.c')
-rw-r--r-- | gcc/gcc-rich-location.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/gcc/gcc-rich-location.c b/gcc/gcc-rich-location.c index 3481425..0a0adf9 100644 --- a/gcc/gcc-rich-location.c +++ b/gcc/gcc-rich-location.c @@ -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); +} |