[Migrator] Refactor fixit filter from JSONFixitWriter to common code

This filter is used for both applying fix-its during the normal
migration flow and by the -emit-fixits-path output for a normal
-typecheck frontend invocation, for example.

rdar://problem/30926261
This commit is contained in:
David Farler
2017-04-20 17:10:06 -07:00
parent 49daaea85f
commit 72e8642a05
4 changed files with 124 additions and 100 deletions

View File

@@ -46,6 +46,7 @@
#include "swift/Frontend/SerializedDiagnosticConsumer.h"
#include "swift/Immediate/Immediate.h"
#include "swift/Option/Options.h"
#include "swift/Migrator/FixitFilter.h"
#include "swift/Migrator/Migrator.h"
#include "swift/PrintAsObjC/PrintAsObjC.h"
#include "swift/Serialization/SerializationOptions.h"
@@ -209,7 +210,8 @@ namespace {
/// If there is an error with fixits it writes the fixits as edits in json
/// format.
class JSONFixitWriter : public DiagnosticConsumer {
class JSONFixitWriter
: public DiagnosticConsumer, public migrator::FixitFilter {
std::unique_ptr<llvm::raw_ostream> OSPtr;
bool FixitAll;
std::vector<SingleEdit> AllEdits;
@@ -229,89 +231,12 @@ private:
StringRef FormatString,
ArrayRef<DiagnosticArgument> FormatArgs,
const DiagnosticInfo &Info) override {
if (!shouldFix(Kind, Info))
if (!(FixitAll || shouldTakeFixit(Kind, Info)))
return;
for (const auto &Fix : Info.FixIts) {
AllEdits.push_back({SM, Fix.getRange(), Fix.getText()});
}
}
bool shouldFix(DiagnosticKind Kind, const DiagnosticInfo &Info) {
if (FixitAll)
return true;
// Do not add a semi or comma as it is wrong in most cases during migration
if (Info.ID == diag::statement_same_line_without_semi.ID ||
Info.ID == diag::declaration_same_line_without_semi.ID ||
Info.ID == diag::expected_separator.ID)
return false;
// The following interact badly with the swift migrator, they are undoing
// migration of arguments to preserve the no-label for first argument.
if (Info.ID == diag::witness_argument_name_mismatch.ID ||
Info.ID == diag::missing_argument_labels.ID ||
Info.ID == diag::override_argument_name_mismatch.ID)
return false;
// This also interacts badly with the swift migrator, it unnecessary adds
// @objc(selector) attributes triggered by the mismatched label changes.
if (Info.ID == diag::objc_witness_selector_mismatch.ID ||
Info.ID == diag::witness_non_objc.ID)
return false;
// This interacts badly with the migrator. For such code:
// func test(p: Int, _: String) {}
// test(0, "")
// the compiler bizarrely suggests to change order of arguments in the call
// site.
if (Info.ID == diag::argument_out_of_order_unnamed_unnamed.ID)
return false;
// The following interact badly with the swift migrator by removing @IB*
// attributes when there is some unrelated type issue.
if (Info.ID == diag::invalid_iboutlet.ID ||
Info.ID == diag::iboutlet_nonobjc_class.ID ||
Info.ID == diag::iboutlet_nonobjc_protocol.ID ||
Info.ID == diag::iboutlet_nonobject_type.ID ||
Info.ID == diag::iboutlet_only_mutable.ID ||
Info.ID == diag::invalid_ibdesignable_extension.ID ||
Info.ID == diag::invalid_ibinspectable.ID ||
Info.ID == diag::invalid_ibaction_decl.ID)
return false;
// Adding type(of:) interacts poorly with the swift migrator by
// invalidating some inits with type errors.
if (Info.ID == diag::init_not_instance_member.ID)
return false;
// Renaming enum cases interacts poorly with the swift migrator by
// reverting changes made by the migrator.
if (Info.ID == diag::could_not_find_enum_case.ID)
return false;
if (Kind == DiagnosticKind::Error)
return true;
// Fixits from warnings/notes that should be applied.
if (Info.ID == diag::forced_downcast_coercion.ID ||
Info.ID == diag::forced_downcast_noop.ID ||
Info.ID == diag::variable_never_mutated.ID ||
Info.ID == diag::function_type_no_parens.ID ||
Info.ID == diag::convert_let_to_var.ID ||
Info.ID == diag::parameter_extraneous_double_up.ID ||
Info.ID == diag::attr_decl_attr_now_on_type.ID ||
Info.ID == diag::noescape_parameter.ID ||
Info.ID == diag::noescape_autoclosure.ID ||
Info.ID == diag::where_inside_brackets.ID ||
Info.ID == diag::selector_construction_suggest.ID ||
Info.ID == diag::selector_literal_deprecated_suggest.ID ||
Info.ID == diag::attr_noescape_deprecated.ID ||
Info.ID == diag::attr_autoclosure_escaping_deprecated.ID ||
Info.ID == diag::attr_warn_unused_result_removed.ID ||
Info.ID == diag::any_as_anyobject_fixit.ID ||
Info.ID == diag::deprecated_protocol_composition.ID ||
Info.ID == diag::deprecated_protocol_composition_single.ID ||
Info.ID == diag::deprecated_any_composition.ID ||
Info.ID == diag::deprecated_operator_body.ID ||
Info.ID == diag::unbound_generic_parameter_explicit_fix.ID)
return true;
return false;
}
};
} // anonymous namespace