Add machine-parseable Fix-It output as part of diagnostics, under the

flag -fdiagnostics-parseable-fixits, from Eelis van der Weegen!

llvm-svn: 111557
This commit is contained in:
Douglas Gregor 2010-08-19 20:24:43 +00:00
parent b2ca0d19f2
commit eec975ce5a
8 changed files with 64 additions and 0 deletions

View File

@ -358,6 +358,18 @@ exprs.c:47:15:{47:8-47:14}{47:17-47:24}: error: invalid operands to binary expre
<p>The {}'s are generated by -fdiagnostics-print-source-range-info.</p>
</dd>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<dt id="opt_fdiagnostics-parseable-fixits">
<b>-fdiagnostics-parseable-fixits</b>:
Print Fix-Its in a machine parseable form.</dt>
<dd><p>This option makes Clang print available Fix-Its in a machine parseable format at the end of diagnostics. The following example illustrates the format:</p>
<pre>
fix-it: "t.cpp":{7:25-7:29}: "Gamma"
</pre>
<p>The range printed is a half-open range, so in this example the characters at column 25 up to but not including column 29 on line 7 in t.cpp should be replaced with the string "Gamma". Either the range or the replacement string may be empty (representing strict insertions and strict erasures, respectively). Both the file name and the insertion string escape '\', tabs (as "\n"), newlines (as "\n"), double quotes(as "\n") and non-printable characters (as octal "\xxx").</p>
</dd>
</dl>

View File

@ -395,6 +395,7 @@ Show commands to run and use verbose output.
B<-fshow-source-location>
B<-fcaret-diagnostics>
B<-fdiagnostics-fixit-info>
B<-fdiagnostics-parseable-fixits>
B<-fdiagnostics-print-source-range-info>
B<-fprint-source-range-info>
B<-fdiagnostics-show-option>

View File

@ -215,6 +215,8 @@ def W : Joined<"-W">;
def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">,
HelpText<"Print source range spans in numeric form">;
def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">,
HelpText<"Print fix-its in machine parseable form">;
def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">,
HelpText<"Print diagnostic name with mappable diagnostics">;
def fdiagnostics_show_category : Separate<"-fdiagnostics-show-category">,

View File

@ -261,6 +261,7 @@ def fdebug_pass_structure : Flag<"-fdebug-pass-structure">, Group<f_Group>;
def fdiagnostics_binary : Flag<"-fdiagnostics-binary">, Group<f_Group>, Flags<[HelpHidden]>;
def fdiagnostics_fixit_info : Flag<"-fdiagnostics-fixit-info">, Group<f_Group>;
def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, Group<f_Group>;
def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, Group<f_Group>;
def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, Group<f_Group>;
def fdiagnostics_show_category_EQ : Joined<"-fdiagnostics-show-category=">, Group<f_Group>;
def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, Group<f_Group>;

View File

@ -30,6 +30,7 @@ public:
unsigned ShowCarets : 1; /// Show carets in diagnostics.
unsigned ShowFixits : 1; /// Show fixit information.
unsigned ShowSourceRanges : 1; /// Show source ranges in numeric form.
unsigned ShowParseableFixits : 1; /// Show machine parseable fix-its.
unsigned ShowOptionNames : 1; /// Show the diagnostic name for mappable
/// diagnostics.
unsigned ShowCategories : 2; /// Show categories: 0 -> none, 1 -> Number,
@ -83,6 +84,7 @@ public:
ShowOptionNames = 0;
ShowCategories = 0;
ShowSourceRanges = 0;
ShowParseableFixits = 0;
VerifyDiagnostics = 0;
BinaryOutput = 0;
ErrorLimit = 0;

View File

@ -1207,6 +1207,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fno_show_column);
Args.AddLastArg(CmdArgs, options::OPT_fobjc_sender_dependent_dispatch);
Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_print_source_range_info);
Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_parseable_fixits);
Args.AddLastArg(CmdArgs, options::OPT_ftime_report);
Args.AddLastArg(CmdArgs, options::OPT_ftrapv);
Args.AddLastArg(CmdArgs, options::OPT_fwrapv);

View File

@ -244,6 +244,8 @@ static void DiagnosticOptsToArgs(const DiagnosticOptions &Opts,
Res.push_back("-fno-diagnostics-fixit-info");
if (Opts.ShowSourceRanges)
Res.push_back("-fdiagnostics-print-source-range-info");
if (Opts.ShowParseableFixits)
Res.push_back("-fdiagnostics-parseable-fixits");
if (Opts.ShowColors)
Res.push_back("-fcolor-diagnostics");
if (Opts.VerifyDiagnostics)
@ -933,6 +935,7 @@ static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
<< ShowCategory;
Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info);
Opts.ShowParseableFixits = Args.hasArg(OPT_fdiagnostics_parseable_fixits);
Opts.VerifyDiagnostics = Args.hasArg(OPT_verify);
Opts.BinaryOutput = Args.hasArg(OPT_fdiagnostics_binary);
Opts.ErrorLimit = Args.getLastArgIntValue(OPT_ferror_limit, 0, Diags);

View File

@ -537,6 +537,48 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
if (DiagOpts->ShowColors)
OS.resetColor();
}
if (DiagOpts->ShowParseableFixits) {
// We follow FixItRewriter's example in not (yet) handling
// fix-its in macros.
bool BadApples = false;
for (const FixItHint *Hint = Hints; Hint != Hints + NumHints; ++Hint) {
if (Hint->RemoveRange.isInvalid() ||
Hint->RemoveRange.getBegin().isMacroID() ||
Hint->RemoveRange.getEnd().isMacroID()) {
BadApples = true;
break;
}
}
if (!BadApples) {
for (const FixItHint *Hint = Hints; Hint != Hints + NumHints; ++Hint) {
SourceLocation B = Hint->RemoveRange.getBegin();
SourceLocation E = Hint->RemoveRange.getEnd();
std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B);
std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E);
// Adjust for token ranges.
if (Hint->RemoveRange.isTokenRange())
EInfo.second += Lexer::MeasureTokenLength(E, SM, *LangOpts);
// We specifically do not do word-wrapping or tab-expansion here,
// because this is supposed to be easy to parse.
OS << " fix-it: \"";
OS.write_escaped(SM.getPresumedLoc(B).getFilename());
OS << "\":{" << SM.getLineNumber(BInfo.first, BInfo.second)
<< ':' << SM.getColumnNumber(BInfo.first, BInfo.second)
<< '-' << SM.getLineNumber(EInfo.first, EInfo.second)
<< ':' << SM.getColumnNumber(EInfo.first, EInfo.second)
<< "}: \"";
OS.write_escaped(Hint->CodeToInsert);
OS << "\"\n";
}
}
}
}
/// \brief Skip over whitespace in the string, starting at the given