mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Frontend] Allow additional files for diagnostic verifier
This change adds a frontend flag, -verify-additional-file, which can be used to pass extra files directly to the diagnostic verifier. These files are not otherwise considered to be Swift source files; they are not compiled or even properly parsed. This feature can be used to verify diagnostics emitted in non-source files, such as in module interfaces or header files.
This commit is contained in:
committed by
Alexis Laferrière
parent
ba00258c66
commit
5036a55550
@@ -41,6 +41,10 @@ public:
|
|||||||
/// Indicates whether diagnostic passes should be skipped.
|
/// Indicates whether diagnostic passes should be skipped.
|
||||||
bool SkipDiagnosticPasses = false;
|
bool SkipDiagnosticPasses = false;
|
||||||
|
|
||||||
|
/// Additional non-source files which will have diagnostics emitted in them,
|
||||||
|
/// and which should be scanned for expectations by the diagnostic verifier.
|
||||||
|
std::vector<std::string> AdditionalVerifierFiles;
|
||||||
|
|
||||||
/// Keep emitting subsequent diagnostics after a fatal error.
|
/// Keep emitting subsequent diagnostics after a fatal error.
|
||||||
bool ShowDiagnosticsAfterFatalError = false;
|
bool ShowDiagnosticsAfterFatalError = false;
|
||||||
|
|
||||||
@@ -54,22 +58,23 @@ public:
|
|||||||
/// Treat all warnings as errors
|
/// Treat all warnings as errors
|
||||||
bool WarningsAsErrors = false;
|
bool WarningsAsErrors = false;
|
||||||
|
|
||||||
// When printing diagnostics, include the diagnostic name at the end
|
/// When printing diagnostics, include the diagnostic name (diag::whatever) at
|
||||||
|
/// the end.
|
||||||
bool PrintDiagnosticNames = false;
|
bool PrintDiagnosticNames = false;
|
||||||
|
|
||||||
/// If set to true, include educational notes in printed output if available.
|
/// If set to true, include educational notes in printed output if available.
|
||||||
/// Educational notes are documentation which supplement diagnostics.
|
/// Educational notes are documentation which supplement diagnostics.
|
||||||
bool PrintEducationalNotes = false;
|
bool PrintEducationalNotes = false;
|
||||||
|
|
||||||
// If set to true, use the more descriptive experimental formatting style for
|
/// Whether to emit diagnostics in the terse LLVM style or in a more
|
||||||
// diagnostics.
|
/// descriptive style that's specific to Swift (currently experimental).
|
||||||
FormattingStyle PrintedFormattingStyle = FormattingStyle::LLVM;
|
FormattingStyle PrintedFormattingStyle = FormattingStyle::LLVM;
|
||||||
|
|
||||||
std::string DiagnosticDocumentationPath = "";
|
std::string DiagnosticDocumentationPath = "";
|
||||||
|
|
||||||
std::string LocalizationCode = "";
|
std::string LocalizationCode = "";
|
||||||
|
|
||||||
// Diagnostic messages directory path.
|
/// Path to a directory of diagnostic localization tables.
|
||||||
std::string LocalizationPath = "";
|
std::string LocalizationPath = "";
|
||||||
|
|
||||||
/// Return a hash code of any components from these options that should
|
/// Return a hash code of any components from these options that should
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ class DiagnosticVerifier : public DiagnosticConsumer {
|
|||||||
SourceManager &SM;
|
SourceManager &SM;
|
||||||
std::vector<CapturedDiagnosticInfo> CapturedDiagnostics;
|
std::vector<CapturedDiagnosticInfo> CapturedDiagnostics;
|
||||||
ArrayRef<unsigned> BufferIDs;
|
ArrayRef<unsigned> BufferIDs;
|
||||||
|
SmallVector<unsigned, 4> AdditionalBufferIDs;
|
||||||
bool AutoApplyFixes;
|
bool AutoApplyFixes;
|
||||||
bool IgnoreUnknown;
|
bool IgnoreUnknown;
|
||||||
|
|
||||||
@@ -74,6 +75,10 @@ public:
|
|||||||
: SM(SM), BufferIDs(BufferIDs), AutoApplyFixes(AutoApplyFixes),
|
: SM(SM), BufferIDs(BufferIDs), AutoApplyFixes(AutoApplyFixes),
|
||||||
IgnoreUnknown(IgnoreUnknown) {}
|
IgnoreUnknown(IgnoreUnknown) {}
|
||||||
|
|
||||||
|
void appendAdditionalBufferID(unsigned bufferID) {
|
||||||
|
AdditionalBufferIDs.push_back(bufferID);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void handleDiagnostic(SourceManager &SM,
|
virtual void handleDiagnostic(SourceManager &SM,
|
||||||
const DiagnosticInfo &Info) override;
|
const DiagnosticInfo &Info) override;
|
||||||
|
|
||||||
|
|||||||
@@ -560,8 +560,11 @@ private:
|
|||||||
bool setUpInputs();
|
bool setUpInputs();
|
||||||
bool setUpASTContextIfNeeded();
|
bool setUpASTContextIfNeeded();
|
||||||
void setupStatsReporter();
|
void setupStatsReporter();
|
||||||
void setupDiagnosticVerifierIfNeeded();
|
|
||||||
void setupDependencyTrackerIfNeeded();
|
void setupDependencyTrackerIfNeeded();
|
||||||
|
|
||||||
|
/// \return false if successsful, true on error.
|
||||||
|
bool setupDiagnosticVerifierIfNeeded();
|
||||||
|
|
||||||
Optional<unsigned> setUpCodeCompletionBuffer();
|
Optional<unsigned> setUpCodeCompletionBuffer();
|
||||||
|
|
||||||
/// Find a buffer for a given input file and ensure it is recorded in
|
/// Find a buffer for a given input file and ensure it is recorded in
|
||||||
|
|||||||
@@ -114,6 +114,8 @@ def tbd_is_installapi: Flag<["-"], "tbd-is-installapi">,
|
|||||||
def verify : Flag<["-"], "verify">,
|
def verify : Flag<["-"], "verify">,
|
||||||
HelpText<"Verify diagnostics against expected-{error|warning|note} "
|
HelpText<"Verify diagnostics against expected-{error|warning|note} "
|
||||||
"annotations">;
|
"annotations">;
|
||||||
|
def verify_additional_file : Separate<["-"], "verify-additional-file">,
|
||||||
|
HelpText<"Verify diagnostics in this file in addition to source files">;
|
||||||
def verify_apply_fixes : Flag<["-"], "verify-apply-fixes">,
|
def verify_apply_fixes : Flag<["-"], "verify-apply-fixes">,
|
||||||
HelpText<"Like -verify, but updates the original source file">;
|
HelpText<"Like -verify, but updates the original source file">;
|
||||||
def verify_ignore_unknown: Flag<["-"], "verify-ignore-unknown">,
|
def verify_ignore_unknown: Flag<["-"], "verify-ignore-unknown">,
|
||||||
|
|||||||
@@ -957,6 +957,9 @@ static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
|
|||||||
Opts.ShowDiagnosticsAfterFatalError |=
|
Opts.ShowDiagnosticsAfterFatalError |=
|
||||||
Args.hasArg(OPT_show_diagnostics_after_fatal);
|
Args.hasArg(OPT_show_diagnostics_after_fatal);
|
||||||
|
|
||||||
|
for (Arg *A : Args.filtered(OPT_verify_additional_file))
|
||||||
|
Opts.AdditionalVerifierFiles.push_back(A->getValue());
|
||||||
|
|
||||||
Opts.UseColor |=
|
Opts.UseColor |=
|
||||||
Args.hasFlag(OPT_color_diagnostics,
|
Args.hasFlag(OPT_color_diagnostics,
|
||||||
OPT_no_color_diagnostics,
|
OPT_no_color_diagnostics,
|
||||||
|
|||||||
@@ -978,7 +978,9 @@ void DiagnosticVerifier::handleDiagnostic(SourceManager &SM,
|
|||||||
bool DiagnosticVerifier::finishProcessing() {
|
bool DiagnosticVerifier::finishProcessing() {
|
||||||
DiagnosticVerifier::Result Result = {false, false};
|
DiagnosticVerifier::Result Result = {false, false};
|
||||||
|
|
||||||
for (auto &BufferID : BufferIDs) {
|
ArrayRef<unsigned> BufferIDLists[2] = { BufferIDs, AdditionalBufferIDs };
|
||||||
|
for (ArrayRef<unsigned> BufferIDList : BufferIDLists)
|
||||||
|
for (auto &BufferID : BufferIDList) {
|
||||||
DiagnosticVerifier::Result FileResult = verifyFile(BufferID);
|
DiagnosticVerifier::Result FileResult = verifyFile(BufferID);
|
||||||
Result.HadError |= FileResult.HadError;
|
Result.HadError |= FileResult.HadError;
|
||||||
Result.HadUnexpectedDiag |= FileResult.HadUnexpectedDiag;
|
Result.HadUnexpectedDiag |= FileResult.HadUnexpectedDiag;
|
||||||
|
|||||||
@@ -290,15 +290,31 @@ void CompilerInstance::setupStatsReporter() {
|
|||||||
Stats = std::move(Reporter);
|
Stats = std::move(Reporter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompilerInstance::setupDiagnosticVerifierIfNeeded() {
|
bool CompilerInstance::setupDiagnosticVerifierIfNeeded() {
|
||||||
auto &diagOpts = Invocation.getDiagnosticOptions();
|
auto &diagOpts = Invocation.getDiagnosticOptions();
|
||||||
|
bool hadError = false;
|
||||||
|
|
||||||
if (diagOpts.VerifyMode != DiagnosticOptions::NoVerify) {
|
if (diagOpts.VerifyMode != DiagnosticOptions::NoVerify) {
|
||||||
DiagVerifier = std::make_unique<DiagnosticVerifier>(
|
DiagVerifier = std::make_unique<DiagnosticVerifier>(
|
||||||
SourceMgr, InputSourceCodeBufferIDs,
|
SourceMgr, InputSourceCodeBufferIDs,
|
||||||
diagOpts.VerifyMode == DiagnosticOptions::VerifyAndApplyFixes,
|
diagOpts.VerifyMode == DiagnosticOptions::VerifyAndApplyFixes,
|
||||||
diagOpts.VerifyIgnoreUnknown);
|
diagOpts.VerifyIgnoreUnknown);
|
||||||
|
for (const auto &filename : diagOpts.AdditionalVerifierFiles) {
|
||||||
|
auto result = getFileSystem().getBufferForFile(filename);
|
||||||
|
if (!result) {
|
||||||
|
Diagnostics.diagnose(SourceLoc(), diag::error_open_input_file,
|
||||||
|
filename, result.getError().message());
|
||||||
|
hadError |= true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto bufferID = SourceMgr.addNewSourceBuffer(std::move(result.get()));
|
||||||
|
DiagVerifier->appendAdditionalBufferID(bufferID);
|
||||||
|
}
|
||||||
|
|
||||||
addDiagnosticConsumer(DiagVerifier.get());
|
addDiagnosticConsumer(DiagVerifier.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return hadError;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompilerInstance::setupDependencyTrackerIfNeeded() {
|
void CompilerInstance::setupDependencyTrackerIfNeeded() {
|
||||||
@@ -347,7 +363,9 @@ bool CompilerInstance::setup(const CompilerInvocation &Invok) {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
setupStatsReporter();
|
setupStatsReporter();
|
||||||
setupDiagnosticVerifierIfNeeded();
|
|
||||||
|
if (setupDiagnosticVerifierIfNeeded())
|
||||||
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user