Commit 338035aa by David Malcolm Committed by David Malcolm

Eliminate fixit_hint class hierarchy

The original implementation of fix-it hints (r230674) had an abstract
base class "fixit_hint" and three subclasses, representing
each of insertions, replacements, and deletions.

Having multiple classes for fix-it hints was a nuisance, as it required
per-class logic everywhere that the hints were handled.

In r239632 I eliminated the deletion subclass in favor of replacement
with the empty string (two subclasses are easier than three).

This patch eliminates the class hierarchy altogether by implementing
insertion in terms of replacement, by representing replacements via
a half-open interval (so that for an insertion, start == next location,
and we're effectively replacing an empty range at the insertion point
with the new string).

This greatly simplifies the code for handling fix-it hints; for example
it allows removal of a parallel class hierarchy of line_event within
edit-context.c.

It also improves consolidation of hints: we can now consolidate
insertions at the same location, affecting a couple of tests
(selftest::test_one_liner_many_fixits and
gcc.dg/Wmissing-braces-fixits.c).

gcc/ChangeLog:
	* diagnostic-show-locus.c (layout::get_expanded_location): Rewrite
	to use new fixit_hint representation, using the "replace" logic.
	(get_line_span_for_fixit_hint): Likewise.
	(layout::print_any_fixits): Likewise.
	(selftest::test_one_liner_many_fixits): Rename to...
	(selftest::test_one_liner_many_fixits_1): ...this, and update
	comment and expected output to reflect that the multiple fix-it
	hints are now consolidated into one insertion.
	(selftest::test_one_liner_many_fixits_2): New test.
	(selftest::test_diagnostic_show_locus_one_liner): Update for
	above.
	(selftest::test_fixit_consolidation): Update for fix-it API
	change.
	* diagnostic.c (print_parseable_fixits): Likewise.
	* edit-context.c (edited_line::m_line_events): Convert from
	auto_vec <line_event *> to auto_vec <line_event>.
	(class line_event): Convert from abstract base class to a concrete
	class, taking over the role of replace_event.
	(class insert_event): Delete.
	(class replace_event): Rename to class line_event.  Convert to
	half-open range.
	(edit_context::add_fixits): Reimplement.
	(edit_context::apply_insert): Delete.
	(edit_context::apply_replace): Rename to...
	(edit_context::apply_fixit): ...this.  Convert to half-open range.
	(edited_file::apply_insert): Delete.
	(edited_file::apply_replace): Rename to...
	(edited_file::apply_fixit): ...this.
	(edited_line::~edited_line): Drop deletion of events.
	(edited_line::apply_insert): Delete.
	(edited_line::apply_replace): Rename to...
	(edited_line::apply_fixit): ...this.  Convert to half-open range.
	Update for change to type of m_line_events.
	* edit-context.h (edit_context::apply_insert): Delete.
	(edit_context::apply_replace): Rename to...
	(edit_context::apply_fixit): ...this.

gcc/testsuite/ChangeLog:
	* gcc.dg/Wmissing-braces-fixits.c: Update expected output to
	reflect insertion fix-it hints at the same location now being
	consolidated.

libcpp/ChangeLog:
	* include/line-map.h (source_range::intersects_line_p): Delete.
	(rich_location::add_fixit): Delete.
	(rich_location::maybe_add_fixit): New method.
	(class fixit_hint): Reimplement in terms of...
	(class fixit_replace): ...this.
	(class fixit_insert): Delete.
	* line-map.c (linemap_position_for_loc_and_offset): Drop overzealous
	linemap_assert_fails.
	(source_range::intersects_line_p): Rename to...
	(fixit_hint::affects_line_p): New function.
	(rich_location::add_fixit_insert_before): Reimplement in terms of
	maybe_add_fixit, moving validation there.
	(rich_location::add_fixit_insert_after): Likewise.
	(column_before_p): Delete.
	(rich_location::add_fixit_replace): Reimplement in terms of
	maybe_add_fixit, moving validation there.  Convert closed input range
	to half-open range.
	(rich_location::add_fixit): Delete.
	(rich_location::maybe_add_fixit): New function.
	(fixit_insert::fixit_insert): Delete.
	(fixit_insert::~fixit_insert): Delete.
	(fixit_insert::affects_line_p): Delete.
	(fixit_insert::maybe_append_replace): Delete.
	(fixit_replace::fixit_replace): Rename to...
	(fixit_hint::fixit_hint): ...this, rewriting as necessary.
	(fixit_replace::~fixit_replace): Delete.
	(fixit_replace::affects_line_p): Delete.
	(fixit_replace::maybe_append_replace): Rename to...
	(fixit_hint::maybe_append): ...this, rewriting as necessary.

From-SVN: r247445
parent 4d82d0bc
2017-05-01 David Malcolm <dmalcolm@redhat.com>
* diagnostic-show-locus.c (layout::get_expanded_location): Rewrite
to use new fixit_hint representation, using the "replace" logic.
(get_line_span_for_fixit_hint): Likewise.
(layout::print_any_fixits): Likewise.
(selftest::test_one_liner_many_fixits): Rename to...
(selftest::test_one_liner_many_fixits_1): ...this, and update
comment and expected output to reflect that the multiple fix-it
hints are now consolidated into one insertion.
(selftest::test_one_liner_many_fixits_2): New test.
(selftest::test_diagnostic_show_locus_one_liner): Update for
above.
(selftest::test_fixit_consolidation): Update for fix-it API
change.
* diagnostic.c (print_parseable_fixits): Likewise.
* edit-context.c (edited_line::m_line_events): Convert from
auto_vec <line_event *> to auto_vec <line_event>.
(class line_event): Convert from abstract base class to a concrete
class, taking over the role of replace_event.
(class insert_event): Delete.
(class replace_event): Rename to class line_event. Convert to
half-open range.
(edit_context::add_fixits): Reimplement.
(edit_context::apply_insert): Delete.
(edit_context::apply_replace): Rename to...
(edit_context::apply_fixit): ...this. Convert to half-open range.
(edited_file::apply_insert): Delete.
(edited_file::apply_replace): Rename to...
(edited_file::apply_fixit): ...this.
(edited_line::~edited_line): Drop deletion of events.
(edited_line::apply_insert): Delete.
(edited_line::apply_replace): Rename to...
(edited_line::apply_fixit): ...this. Convert to half-open range.
Update for change to type of m_line_events.
* edit-context.h (edit_context::apply_insert): Delete.
(edit_context::apply_replace): Rename to...
(edit_context::apply_fixit): ...this.
2017-05-01 Martin Sebor <msebor@redhat.com> 2017-05-01 Martin Sebor <msebor@redhat.com>
* gimple-ssa-sprintf.c (format_integer): Set knownrange when it's * gimple-ssa-sprintf.c (format_integer): Set knownrange when it's
......
...@@ -757,43 +757,13 @@ print_parseable_fixits (pretty_printer *pp, rich_location *richloc) ...@@ -757,43 +757,13 @@ print_parseable_fixits (pretty_printer *pp, rich_location *richloc)
expanded_location start_exploc = expand_location (start_loc); expanded_location start_exploc = expand_location (start_loc);
pp_string (pp, "fix-it:"); pp_string (pp, "fix-it:");
print_escaped_string (pp, start_exploc.file); print_escaped_string (pp, start_exploc.file);
source_location end_loc;
/* For compatibility with clang, print as a half-open range. */ /* For compatibility with clang, print as a half-open range. */
if (hint->maybe_get_end_loc (&end_loc)) source_location next_loc = hint->get_next_loc ();
{ expanded_location next_exploc = expand_location (next_loc);
expanded_location end_exploc = expand_location (end_loc); pp_printf (pp, ":{%i:%i-%i:%i}:",
pp_printf (pp, ":{%i:%i-%i:%i}:", start_exploc.line, start_exploc.column,
start_exploc.line, start_exploc.column, next_exploc.line, next_exploc.column);
end_exploc.line, end_exploc.column + 1); print_escaped_string (pp, hint->get_string ());
}
else
{
pp_printf (pp, ":{%i:%i-%i:%i}:",
start_exploc.line, start_exploc.column,
start_exploc.line, start_exploc.column);
}
switch (hint->get_kind ())
{
case fixit_hint::INSERT:
{
const fixit_insert *insert
= static_cast <const fixit_insert *> (hint);
print_escaped_string (pp, insert->get_string ());
}
break;
case fixit_hint::REPLACE:
{
const fixit_replace *replace
= static_cast <const fixit_replace *> (hint);
print_escaped_string (pp, replace->get_string ());
}
break;
default:
gcc_unreachable ();
}
pp_newline (pp); pp_newline (pp);
} }
} }
......
...@@ -56,8 +56,7 @@ class edit_context ...@@ -56,8 +56,7 @@ class edit_context
void print_diff (pretty_printer *pp, bool show_filenames); void print_diff (pretty_printer *pp, bool show_filenames);
private: private:
bool apply_insert (const fixit_insert *insert); bool apply_fixit (const fixit_hint *hint);
bool apply_replace (const fixit_replace *replace);
edited_file *get_file (const char *filename); edited_file *get_file (const char *filename);
edited_file &get_or_insert_file (const char *filename); edited_file &get_or_insert_file (const char *filename);
......
2017-05-01 David Malcolm <dmalcolm@redhat.com>
* gcc.dg/Wmissing-braces-fixits.c: Update expected output to
reflect insertion fix-it hints at the same location now being
consolidated.
2017-05-01 Martin Sebor <msebor@redhat.com> 2017-05-01 Martin Sebor <msebor@redhat.com>
* tree-ssa/builtin-sprintf-warn-18.c: Adjust to avoid failures * tree-ssa/builtin-sprintf-warn-18.c: Adjust to avoid failures
......
...@@ -48,13 +48,9 @@ int arr_2_2_3[2][2][3] = \ ...@@ -48,13 +48,9 @@ int arr_2_2_3[2][2][3] = \
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
{ 0, 1, 2, 3, 4, 5, { 0, 1, 2, 3, 4, 5,
^ ^
{ {{ } { }}
{ } { }
}
6, 7, 8, 9, 10, 11}; 6, 7, 8, 9, 10, 11};
{ {{ } { }}
{ } { }
}
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
int arr_2_3_2[2][3][2] = \ int arr_2_3_2[2][3][2] = \
...@@ -63,13 +59,9 @@ int arr_2_3_2[2][3][2] = \ ...@@ -63,13 +59,9 @@ int arr_2_3_2[2][3][2] = \
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
{ 0, 1, 2, 3, 4, 5, { 0, 1, 2, 3, 4, 5,
^ ^
{ {{ } { } { }}
{ } { } { }
}
6, 7, 8, 9, 10, 11}; 6, 7, 8, 9, 10, 11};
{ {{ } { } { }}
{ } { } { }
}
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
int arr_6_2[6][2] = \ int arr_6_2[6][2] = \
...@@ -89,15 +81,9 @@ int arr_3_2_2[3][2][2] = \ ...@@ -89,15 +81,9 @@ int arr_3_2_2[3][2][2] = \
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
{ 0, 1, 2, 3, 4, 5, { 0, 1, 2, 3, 4, 5,
^ ^
{ {{ } { }}{{ }
{ } { }
} {
{ }
6, 7, 8, 9, 10, 11}; 6, 7, 8, 9, 10, 11};
{ } { }}{{ } { }}
} {
{ } { }
}
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
int arr_3_4[3][4] = \ int arr_3_4[3][4] = \
...@@ -128,13 +114,9 @@ int arr_2_1_6[2][1][6] = \ ...@@ -128,13 +114,9 @@ int arr_2_1_6[2][1][6] = \
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
{ 0, 1, 2, 3, 4, 5, { 0, 1, 2, 3, 4, 5,
^ ^
{ {{ }}
{ }
}
6, 7, 8, 9, 10, 11}; 6, 7, 8, 9, 10, 11};
{ {{ }}
{ }
}
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
struct sf2 arr_6_sf2[6] = \ struct sf2 arr_6_sf2[6] = \
...@@ -165,21 +147,9 @@ struct sa2 arr_6_sa2[6] = \ ...@@ -165,21 +147,9 @@ struct sa2 arr_6_sa2[6] = \
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
{ 0, 1, 2, 3, 4, 5, { 0, 1, 2, 3, 4, 5,
^ ^
{ {{ }}{{ }}{{ }}
{ }
} {
{ }
} {
{ }
}
6, 7, 8, 9, 10, 11}; 6, 7, 8, 9, 10, 11};
{ {{ }}{{ }}{{ }}
{ }
} {
{ }
} {
{ }
}
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
struct sa3 arr_4_sa3[4] = \ struct sa3 arr_4_sa3[4] = \
...@@ -188,15 +158,7 @@ struct sa3 arr_4_sa3[4] = \ ...@@ -188,15 +158,7 @@ struct sa3 arr_4_sa3[4] = \
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
{ 0, 1, 2, 3, 4, 5, { 0, 1, 2, 3, 4, 5,
^ ^
{ {{ }}{{ }}
{ }
} {
{ }
}
6, 7, 8, 9, 10, 11}; 6, 7, 8, 9, 10, 11};
{ {{ }}{{ }}
{ }
} {
{ }
}
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
2017-05-01 David Malcolm <dmalcolm@redhat.com>
* include/line-map.h (source_range::intersects_line_p): Delete.
(rich_location::add_fixit): Delete.
(rich_location::maybe_add_fixit): New method.
(class fixit_hint): Reimplement in terms of...
(class fixit_replace): ...this.
(class fixit_insert): Delete.
* line-map.c (linemap_position_for_loc_and_offset): Drop overzealous
linemap_assert_fails.
(source_range::intersects_line_p): Rename to...
(fixit_hint::affects_line_p): New function.
(rich_location::add_fixit_insert_before): Reimplement in terms of
maybe_add_fixit, moving validation there.
(rich_location::add_fixit_insert_after): Likewise.
(column_before_p): Delete.
(rich_location::add_fixit_replace): Reimplement in terms of
maybe_add_fixit, moving validation there. Convert closed input range
to half-open range.
(rich_location::add_fixit): Delete.
(rich_location::maybe_add_fixit): New function.
(fixit_insert::fixit_insert): Delete.
(fixit_insert::~fixit_insert): Delete.
(fixit_insert::affects_line_p): Delete.
(fixit_insert::maybe_append_replace): Delete.
(fixit_replace::fixit_replace): Rename to...
(fixit_hint::fixit_hint): ...this, rewriting as necessary.
(fixit_replace::~fixit_replace): Delete.
(fixit_replace::affects_line_p): Delete.
(fixit_replace::maybe_append_replace): Rename to...
(fixit_hint::maybe_append): ...this, rewriting as necessary.
2017-04-03 Jonathan Wakely <jwakely@redhat.com> 2017-04-03 Jonathan Wakely <jwakely@redhat.com>
* include/line-map.h (LINEMAPS_MACRO_MAPS): Fix typo in comment. * include/line-map.h (LINEMAPS_MACRO_MAPS): Fix typo in comment.
......
...@@ -305,9 +305,6 @@ struct GTY(()) source_range ...@@ -305,9 +305,6 @@ struct GTY(()) source_range
result.m_finish = finish; result.m_finish = finish;
return result; return result;
} }
/* Is there any part of this range on the given line? */
bool intersects_line_p (const char *file, int line) const;
}; };
/* Memory allocation function typedef. Works like xrealloc. */ /* Memory allocation function typedef. Works like xrealloc. */
...@@ -1416,8 +1413,6 @@ semi_embedded_vec<T, NUM_EMBEDDED>::truncate (int len) ...@@ -1416,8 +1413,6 @@ semi_embedded_vec<T, NUM_EMBEDDED>::truncate (int len)
} }
class fixit_hint; class fixit_hint;
class fixit_insert;
class fixit_replace;
/* A "rich" source code location, for use when printing diagnostics. /* A "rich" source code location, for use when printing diagnostics.
A rich_location has one or more carets&ranges, where the carets A rich_location has one or more carets&ranges, where the carets
...@@ -1667,7 +1662,9 @@ class rich_location ...@@ -1667,7 +1662,9 @@ class rich_location
private: private:
bool reject_impossible_fixit (source_location where); bool reject_impossible_fixit (source_location where);
void stop_supporting_fixits (); void stop_supporting_fixits ();
void add_fixit (fixit_hint *hint); void maybe_add_fixit (source_location start,
source_location next_loc,
const char *new_content);
public: public:
static const int STATICALLY_ALLOCATED_RANGES = 3; static const int STATICALLY_ALLOCATED_RANGES = 3;
...@@ -1687,72 +1684,41 @@ protected: ...@@ -1687,72 +1684,41 @@ protected:
bool m_seen_impossible_fixit; bool m_seen_impossible_fixit;
}; };
class fixit_hint /* A fix-it hint: a suggested insertion, replacement, or deletion of text.
{ We handle these three types of edit with one class, by representing
public: them as replacement of a half-open range:
enum kind {INSERT, REPLACE}; [start, next_loc)
Insertions have start == next_loc: "replace" the empty string at the
virtual ~fixit_hint () {} start location with the new string.
Deletions are replacement with the empty string. */
virtual enum kind get_kind () const = 0;
virtual bool affects_line_p (const char *file, int line) const = 0;
virtual source_location get_start_loc () const = 0;
virtual bool maybe_get_end_loc (source_location *out) const = 0;
/* Vfunc for consolidating successor fixits. */
virtual bool maybe_append_replace (line_maps *set,
source_range src_range,
const char *new_content) = 0;
};
class fixit_insert : public fixit_hint
{
public:
fixit_insert (source_location where,
const char *new_content);
~fixit_insert ();
enum kind get_kind () const { return INSERT; }
bool affects_line_p (const char *file, int line) const;
source_location get_start_loc () const { return m_where; }
bool maybe_get_end_loc (source_location *) const { return false; }
bool maybe_append_replace (line_maps *set,
source_range src_range,
const char *new_content);
source_location get_location () const { return m_where; }
const char *get_string () const { return m_bytes; }
size_t get_length () const { return m_len; }
private: class fixit_hint
source_location m_where;
char *m_bytes;
size_t m_len;
};
class fixit_replace : public fixit_hint
{ {
public: public:
fixit_replace (source_range src_range, fixit_hint (source_location start,
const char *new_content); source_location next_loc,
~fixit_replace (); const char *new_content);
~fixit_hint () { free (m_bytes); }
enum kind get_kind () const { return REPLACE; }
bool affects_line_p (const char *file, int line) const; bool affects_line_p (const char *file, int line) const;
source_location get_start_loc () const { return m_src_range.m_start; } source_location get_start_loc () const { return m_start; }
bool maybe_get_end_loc (source_location *out) const source_location get_next_loc () const { return m_next_loc; }
{ bool maybe_append (source_location start,
*out = m_src_range.m_finish; source_location next_loc,
return true; const char *new_content);
}
bool maybe_append_replace (line_maps *set,
source_range src_range,
const char *new_content);
source_range get_range () const { return m_src_range; }
const char *get_string () const { return m_bytes; } const char *get_string () const { return m_bytes; }
size_t get_length () const { return m_len; } size_t get_length () const { return m_len; }
bool insertion_p () const { return m_start == m_next_loc; }
private: private:
source_range m_src_range; /* We don't use source_range here since, unlike most places,
this is a half-open/half-closed range:
[start, next_loc)
so that we can support insertion via start == next_loc. */
source_location m_start;
source_location m_next_loc;
char *m_bytes; char *m_bytes;
size_t m_len; size_t m_len;
}; };
......
...@@ -881,8 +881,7 @@ linemap_position_for_loc_and_offset (struct line_maps *set, ...@@ -881,8 +881,7 @@ linemap_position_for_loc_and_offset (struct line_maps *set,
loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus; loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
/* This function does not support virtual locations yet. */ /* This function does not support virtual locations yet. */
if (linemap_assert_fails if (linemap_location_from_macro_expansion_p (set, loc))
(!linemap_location_from_macro_expansion_p (set, loc)))
return loc; return loc;
if (column_offset == 0 if (column_offset == 0
...@@ -2003,28 +2002,6 @@ line_table_dump (FILE *stream, struct line_maps *set, unsigned int num_ordinary, ...@@ -2003,28 +2002,6 @@ line_table_dump (FILE *stream, struct line_maps *set, unsigned int num_ordinary,
} }
} }
/* struct source_range. */
/* Is there any part of this range on the given line? */
bool
source_range::intersects_line_p (const char *file, int line) const
{
expanded_location exploc_start
= linemap_client_expand_location_to_spelling_point (m_start);
if (file != exploc_start.file)
return false;
if (line < exploc_start.line)
return false;
expanded_location exploc_finish
= linemap_client_expand_location_to_spelling_point (m_finish);
if (file != exploc_finish.file)
return false;
if (line > exploc_finish.line)
return false;
return true;
}
/* class rich_location. */ /* class rich_location. */
/* Construct a rich_location with location LOC as its initial range. */ /* Construct a rich_location with location LOC as its initial range. */
...@@ -2173,16 +2150,7 @@ rich_location::add_fixit_insert_before (source_location where, ...@@ -2173,16 +2150,7 @@ rich_location::add_fixit_insert_before (source_location where,
const char *new_content) const char *new_content)
{ {
source_location start = get_range_from_loc (m_line_table, where).m_start; source_location start = get_range_from_loc (m_line_table, where).m_start;
maybe_add_fixit (start, start, new_content);
if (reject_impossible_fixit (start))
return;
/* We do not yet support newlines within fix-it hints. */
if (strchr (new_content, '\n'))
{
stop_supporting_fixits ();
return;
}
add_fixit (new fixit_insert (start, new_content));
} }
/* Add a fixit-hint, suggesting insertion of NEW_CONTENT /* Add a fixit-hint, suggesting insertion of NEW_CONTENT
...@@ -2202,10 +2170,6 @@ rich_location::add_fixit_insert_after (source_location where, ...@@ -2202,10 +2170,6 @@ rich_location::add_fixit_insert_after (source_location where,
const char *new_content) const char *new_content)
{ {
source_location finish = get_range_from_loc (m_line_table, where).m_finish; source_location finish = get_range_from_loc (m_line_table, where).m_finish;
if (reject_impossible_fixit (finish))
return;
source_location next_loc source_location next_loc
= linemap_position_for_loc_and_offset (m_line_table, finish, 1); = linemap_position_for_loc_and_offset (m_line_table, finish, 1);
...@@ -2217,7 +2181,7 @@ rich_location::add_fixit_insert_after (source_location where, ...@@ -2217,7 +2181,7 @@ rich_location::add_fixit_insert_after (source_location where,
return; return;
} }
add_fixit (new fixit_insert (next_loc, new_content)); maybe_add_fixit (next_loc, next_loc, new_content);
} }
/* Methods for adding removal fix-it hints. */ /* Methods for adding removal fix-it hints. */
...@@ -2250,44 +2214,6 @@ rich_location::add_fixit_remove (source_range src_range) ...@@ -2250,44 +2214,6 @@ rich_location::add_fixit_remove (source_range src_range)
add_fixit_replace (src_range, ""); add_fixit_replace (src_range, "");
} }
/* Return true iff A is in the column directly before B, on the
same line of the same source file. */
static bool
column_before_p (line_maps *set, source_location a, source_location b)
{
if (IS_ADHOC_LOC (a))
a = get_location_from_adhoc_loc (set, a);
if (IS_ADHOC_LOC (b))
b = get_location_from_adhoc_loc (set, b);
/* They must both be in ordinary maps. */
const struct line_map *linemap_a = linemap_lookup (set, a);
if (linemap_macro_expansion_map_p (linemap_a))
return false;
const struct line_map *linemap_b = linemap_lookup (set, b);
if (linemap_macro_expansion_map_p (linemap_b))
return false;
/* To be on the same line, they must be in the same ordinary map. */
if (linemap_a != linemap_b)
return false;
linenum_type line_a
= SOURCE_LINE (linemap_check_ordinary (linemap_a), a);
linenum_type line_b
= SOURCE_LINE (linemap_check_ordinary (linemap_b), b);
if (line_a != line_b)
return false;
linenum_type column_a
= SOURCE_COLUMN (linemap_check_ordinary (linemap_a), a);
linenum_type column_b
= SOURCE_COLUMN (linemap_check_ordinary (linemap_b), b);
return column_b == column_a + 1;
}
/* Add a fixit-hint, suggesting replacement of the content covered /* Add a fixit-hint, suggesting replacement of the content covered
by range 0 with NEW_CONTENT. */ by range 0 with NEW_CONTENT. */
...@@ -2317,28 +2243,22 @@ void ...@@ -2317,28 +2243,22 @@ void
rich_location::add_fixit_replace (source_range src_range, rich_location::add_fixit_replace (source_range src_range,
const char *new_content) const char *new_content)
{ {
src_range.m_start = get_pure_location (m_line_table, src_range.m_start); source_location start = get_pure_location (m_line_table, src_range.m_start);
src_range.m_finish = get_pure_location (m_line_table, src_range.m_finish); source_location finish = get_pure_location (m_line_table, src_range.m_finish);
if (reject_impossible_fixit (src_range.m_start))
return;
if (reject_impossible_fixit (src_range.m_finish))
return;
/* We do not yet support newlines within fix-it hints. */ /* Fix-it hints use half-closed ranges, so attempt to offset the endpoint. */
if (strchr (new_content, '\n')) 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 (); stop_supporting_fixits ();
return; return;
} }
finish = next_loc;
/* Consolidate neighboring fixits. */ maybe_add_fixit (start, finish, new_content);
fixit_hint *prev = get_last_fixit_hint ();
if (prev)
if (prev->maybe_append_replace (m_line_table, src_range, new_content))
return;
add_fixit (new fixit_replace (src_range, new_content));
} }
/* Get the last fix-it hint within this rich_location, or NULL if none. */ /* Get the last fix-it hint within this rich_location, or NULL if none. */
...@@ -2392,89 +2312,85 @@ rich_location::stop_supporting_fixits () ...@@ -2392,89 +2312,85 @@ rich_location::stop_supporting_fixits ()
m_fixit_hints.truncate (0); m_fixit_hints.truncate (0);
} }
/* Add HINT to the fix-it hints in this rich_location. */ /* Add HINT to the fix-it hints in this rich_location,
consolidating into the prior fixit if possible. */
void void
rich_location::add_fixit (fixit_hint *hint) rich_location::maybe_add_fixit (source_location start,
source_location next_loc,
const char *new_content)
{ {
m_fixit_hints.push (hint); if (reject_impossible_fixit (start))
} return;
if (reject_impossible_fixit (next_loc))
/* class fixit_insert. */ return;
fixit_insert::fixit_insert (source_location where,
const char *new_content)
: m_where (where),
m_bytes (xstrdup (new_content)),
m_len (strlen (new_content))
{
}
fixit_insert::~fixit_insert ()
{
free (m_bytes);
}
/* Implementation of fixit_hint::affects_line_p for fixit_insert. */
bool /* We do not yet support newlines within fix-it hints. */
fixit_insert::affects_line_p (const char *file, int line) const if (strchr (new_content, '\n'))
{ {
expanded_location exploc stop_supporting_fixits ();
= linemap_client_expand_location_to_spelling_point (m_where); return;
if (file == exploc.file) }
if (line == exploc.line)
return true;
return false;
}
/* Implementation of maybe_append_replace for fixit_insert. Reject /* Consolidate neighboring fixits. */
the attempt to consolidate fix-its. */ fixit_hint *prev = get_last_fixit_hint ();
if (prev)
if (prev->maybe_append (start, next_loc, new_content))
return;
bool m_fixit_hints.push (new fixit_hint (start, next_loc, new_content));
fixit_insert::maybe_append_replace (line_maps *, source_range, const char *)
{
return false;
} }
/* class fixit_replace. */ /* class fixit_hint. */
fixit_replace::fixit_replace (source_range src_range, fixit_hint::fixit_hint (source_location start,
const char *new_content) source_location next_loc,
: m_src_range (src_range), const char *new_content)
: m_start (start),
m_next_loc (next_loc),
m_bytes (xstrdup (new_content)), m_bytes (xstrdup (new_content)),
m_len (strlen (new_content)) m_len (strlen (new_content))
{ {
} }
fixit_replace::~fixit_replace () /* Does this fix-it hint affect the given line? */
{
free (m_bytes);
}
/* Implementation of fixit_hint::affects_line_p for fixit_replace. */
bool bool
fixit_replace::affects_line_p (const char *file, int line) const fixit_hint::affects_line_p (const char *file, int line) const
{ {
return m_src_range.intersects_line_p (file, line); expanded_location exploc_start
= linemap_client_expand_location_to_spelling_point (m_start);
if (file != exploc_start.file)
return false;
if (line < exploc_start.line)
return false;
expanded_location exploc_next_loc
= linemap_client_expand_location_to_spelling_point (m_next_loc);
if (file != exploc_next_loc.file)
return false;
if (line > exploc_next_loc.line)
return false;
return true;
} }
/* Implementation of maybe_append_replace for fixit_replace. If /* Method for consolidating fix-it hints, for use by
possible, merge the new replacement into this one and return true. rich_location::maybe_add_fixit.
If possible, merge a pending fix-it hint with the given params
into this one and return true.
Otherwise return false. */ Otherwise return false. */
bool bool
fixit_replace::maybe_append_replace (line_maps *set, fixit_hint::maybe_append (source_location start,
source_range src_range, source_location next_loc,
const char *new_content) const char *new_content)
{ {
/* Does SRC_RANGE start immediately after this one finishes? */ /* For consolidation to be possible, START must be at this hint's
if (!column_before_p (set, m_src_range.m_finish, src_range.m_start)) m_next_loc. */
if (start != m_next_loc)
return false; return false;
/* We have neighboring replacements; merge them. */ /* If so, we have neighboring replacements; merge them. */
m_src_range.m_finish = src_range.m_finish; m_next_loc = next_loc;
size_t extra_len = strlen (new_content); size_t extra_len = strlen (new_content);
m_bytes = (char *)xrealloc (m_bytes, m_len + extra_len + 1); m_bytes = (char *)xrealloc (m_bytes, m_len + extra_len + 1);
memcpy (m_bytes + m_len, new_content, extra_len); memcpy (m_bytes + m_len, new_content, extra_len);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment