aboutsummaryrefslogtreecommitdiff
path: root/gcc/gcc-rich-location.c
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2018-05-01 00:10:10 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2018-05-01 00:10:10 +0000
commit1a3a7b4eeb0444148adc4f007b91e120814c4cc5 (patch)
treeea1a9a931bb387718caee06b1c2785faf6296e9c /gcc/gcc-rich-location.c
parent47ae164c051c575234f4bef916f10346765d9565 (diff)
downloadgcc-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.c111
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);
+}