blob: a62b56979f6c1c32d47572725fe8a2cdc9341e6e [file] [log] [blame]
.. Copyright (C) 2024-2025 Free Software Foundation, Inc.
Originally contributed by David Malcolm <dmalcolm@redhat.com>
This is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see
<https://www.gnu.org/licenses/>.
.. default-domain:: c
Fix-it hints
============
Adding fix-it hints to a diagnostic
***********************************
A :type:`diagnostic` can 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.
There is only limited support for newline characters in fix-it hints:
only hints with newlines which insert an entire new line are permitted,
inserting at the start of a line, and finishing with a newline
(with no interior newline characters). Other attempts to add
fix-it hints containing newline characters will fail.
Similarly, attempts to delete or replace a range *affecting* multiple
lines will fail.
The API handles these failures gracefully, so that diagnostics can attempt
to add fix-it hints without each needing extensive checking.
Fix-it hints are printed to text sinks, and are emitted by SARIF sinks
as ``fix`` objects (see SARIF 2.1.0
`ยง3.55 fix object <https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html#_Toc141791131>`_).
Fix-it hints within a :type:`diagnostic` are "atomic": if any hints can't
be applied, none of them will be, and no fix-its hints will be displayed
for that diagnostic. 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.
All fix-it hints within one :type:`diagnostic` must affect the same
:type:`diagnostic_file`.
.. function:: void diagnostic_add_fix_it_hint_insert_before (diagnostic *diag, \
const diagnostic_physical_location *loc, \
const char *addition)
Add a fix-it hint to ``diag`` suggesting the insertion of the string
``addition`` before ``LOC``.
For example::
ptr = arr[0];
^~~~~~
&
This :type:`diagnostic` has a single location covering ``arr[0]``,
with the caret at the start. It has a single insertion fix-it hint,
inserting ``&`` before the start of ``loc``.
.. function:: void diagnostic_add_fix_it_hint_insert_after (diagnostic *diag, \
const diagnostic_physical_location *loc, \
const char *addition)
Add a fix-it hint to ``diag`` suggesting the insertion of the string
``addition`` after the end of ``LOC``.
For example, in::
#define FN(ARG0, ARG1, ARG2) fn(ARG0, ARG1, ARG2)
^~~~ ^~~~ ^~~~
( ) ( ) ( )
the :type:`diagnostic` has three physical locations, covering ``ARG0``,
``ARG1``, and ``ARG2``, and 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.
.. function:: void diagnostic_add_fix_it_hint_replace (diagnostic *diag, \
const diagnostic_physical_location *loc, \
const char *replacement)
Add a fix-it hint to ``diag`` suggesting the replacement of the text
at ``LOC`` with the string ``replacement``.
For example, in::
c = s.colour;
^~~~~~
color
This :type:`diagnostic` has a single physical location covering ``colour``,
and a single "replace" fix-it hint, covering the same range, suggesting
replacing it with ``color``.
.. function:: void diagnostic_add_fix_it_hint_delete (diagnostic *diag, \
const diagnostic_physical_location *loc)
Add a fix-it hint to ``diag`` suggesting the deletion of the text
at ``LOC``.
For example, in::
struct s {int i};;
^
-
This :type:`diagnostic` has a single physical location at the stray
trailing semicolon, along with a single removal fix-it hint, covering
the same location.
Generating patches
******************
.. function:: void diagnostic_manager_write_patch (diagnostic_manager *diag_mgr, \
FILE *dst_stream)
Write a patch to ``dst_stream`` consisting of the effect of all fix-it hints
on all diagnostics that have been finished on ``diag_mgr``.
Both parameters must be non-NULL.