Skip to content

[Migrator] Conservative and Minimal @objc inference workflows #9116

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 29, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion include/swift/Migrator/FixitFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,10 @@ struct FixitFilter {
Info.ID == diag::deprecated_any_composition.ID ||
Info.ID == diag::deprecated_operator_body.ID ||
Info.ID == diag::unbound_generic_parameter_explicit_fix.ID ||
Info.ID == diag::objc_inference_swift3_addobjc.ID)
Info.ID == diag::objc_inference_swift3_addobjc.ID ||
Info.ID == diag::objc_inference_swift3_dynamic.ID ||
Info.ID == diag::override_swift3_objc_inference.ID ||
Info.ID == diag::objc_inference_swift3_objc_derived.ID)
return true;

return false;
Expand Down
2 changes: 1 addition & 1 deletion include/swift/Migrator/MigratorOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace swift {
struct MigratorOptions {
/// Add `@objc` to declarations that would've been implicitly
/// visible to the Objective-C runtime in Swift 3.
bool AddObjC = false;
bool KeepObjcVisibility = false;

/// Skip the migration phase that repeatedly asks for fix-its from the
/// compiler and applies them. This is generally for debugging.
Expand Down
4 changes: 4 additions & 0 deletions include/swift/Option/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@ def update_code : Flag<["-"], "update-code">,
HelpText<"Update Swift code">,
Flags<[FrontendOption, HelpHidden, NoInteractiveOption, DoesNotAffectIncrementalBuild]>;

def migrate_keep_objc_visibility: Flag<["-"], "migrate-keep-objc-visibility">,
Flags<[FrontendOption, NoInteractiveOption]>,
HelpText<"When migrating, add '@objc' to declarations that would've been implicitly visible in Swift 3">;

def disable_migrator_fixits: Flag<["-"], "disable-migrator-fixits">,
Flags<[FrontendOption, NoInteractiveOption]>,
HelpText<"Disable the Migrator phase which automatically applies fix-its">;
Expand Down
4 changes: 4 additions & 0 deletions lib/Driver/ToolChains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,10 @@ ToolChain::constructInvocation(const CompileJobAction &job,
Arguments.push_back(LoadedModuleTracePath.c_str());
}

if (context.Args.hasArg(options::OPT_migrate_keep_objc_visibility)) {
Arguments.push_back("-migrate-keep-objc-visibility");
}

const std::string &FixitsPath =
context.Output.getAdditionalOutputForType(types::TY_Remapping);
if (!FixitsPath.empty()) {
Expand Down
2 changes: 1 addition & 1 deletion lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1578,7 +1578,7 @@ bool ParseMigratorArgs(MigratorOptions &Opts, llvm::Triple &Triple,
DiagnosticEngine &Diags) {
using namespace options;

Opts.AddObjC |= Args.hasArg(OPT_warn_swift3_objc_inference);
Opts.KeepObjcVisibility |= Args.hasArg(OPT_migrate_keep_objc_visibility);
Opts.DumpUsr = Args.hasArg(OPT_dump_usr);

if (Args.hasArg(OPT_disable_migrator_fixits)) {
Expand Down
16 changes: 14 additions & 2 deletions lib/Migrator/Migrator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,20 @@ Migrator::performAFixItMigration() {
Invocation.clearInputs();
Invocation.getLangOptions().EffectiveLanguageVersion = { 4, 0, 0 };

const auto OrigPrimaryInput =
StartInvocation.getFrontendOptions().PrimaryInput.getValue();
// The default subset of @objc fix-its, referred to as "minimal" migration
// in SE-0160, adds @objc to things that clearly must be visible to the
// Objective-C runtime. These are compiler error fix-its.
Invocation.getLangOptions().WarnSwift3ObjCInference = true;
Invocation.getLangOptions().EnableSwift3ObjCInference = false;

// However, if the user selects the workflow to keep the behavior of Swift 3's
// implicit Objective-C visibility, force Swift 3 @objc inference to be on.
// Coupled with the -warn-swift3-objc-inference flag above, we'll get warning
// fix-its from the compiler.
if (getMigratorOptions().KeepObjcVisibility) {
Invocation.getLangOptions().EnableSwift3ObjCInference = true;
}

const auto &OrigFrontendOpts = StartInvocation.getFrontendOptions();

auto InputBuffers = OrigFrontendOpts.InputBuffers;
Expand Down
4 changes: 4 additions & 0 deletions test/Driver/driver_migration.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// RUN: %swiftc_driver -update-code -migrate-keep-objc-visibility -### %s 2>&1 | %FileCheck -check-prefix=CHECK-KEEP-OBJC %s

// CHECK-KEEP-OBJC: -migrate-keep-objc-visibility
// CHECK-KEEP-OBJC: -emit-remap-file-path {{.*}}.remap
17 changes: 17 additions & 0 deletions test/Migrator/Inputs/conservative_objc_inference.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Foundation

class MyClass : NSObject {
var property : NSObject? = nil
dynamic var dynamicProperty: Int { return 2 }
func foo() {}
func baz() {}
}

extension MyClass {
func bar() {}
}

class MySubClass : MyClass {
override func foo() {}
override func bar() {}
}
25 changes: 25 additions & 0 deletions test/Migrator/Inputs/minimal_objc_inference.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import Foundation

class MyClass : NSObject {
var propertyUsedInKeyPath : NSObject? = nil
dynamic var dynamicVarUsedInSelector : Int { return 2 }
func overridden() {}
func usedViaAnyObject() {}
func unused() {}
}

extension MyClass {
func inExtensionAndOverridden() {}
}

class MySubClass : MyClass {
override func overridden() {}
override func inExtensionAndOverridden() {}
}

func test(object: AnyObject, mine: MyClass) {
_ = #selector(MyClass.overridden)
_ = #selector(getter: MyClass.dynamicVarUsedInSelector)
_ = #keyPath(MyClass.propertyUsedInKeyPath)
_ = object.usedViaAnyObject?()
}
9 changes: 9 additions & 0 deletions test/Migrator/conservative_objc_inference.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -migrate-keep-objc-visibility -primary-file %S/Inputs/conservative_objc_inference.swift -emit-migrated-file-path %t/migrated_conservative_objc_inference.swift -emit-remap-file-path %t/migrated_conservative_objc_inference.swift.remap -o /dev/null
// RUN: %FileCheck %s < %t/migrated_conservative_objc_inference.swift
// REQUIRES: objc_interop

// CHECK: @objc var property : NSObject? = nil
// CHECK: @objc dynamic var dynamicProperty: Int { return 2 }
// CHECK: @objc func foo() {}
// CHECK: @objc func baz() {}
// CHECK: @objc func bar() {}
2 changes: 1 addition & 1 deletion test/Migrator/member.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// REQUIRES: objc_interop
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -primary-file %s -F %S/mock-sdk -api-diff-data-file %S/API.json -emit-migrated-file-path %t/member.swift.result -emit-remap-file-path %t/member.swift.remap
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -primary-file %s -F %S/mock-sdk -api-diff-data-file %S/API.json -emit-migrated-file-path %t/member.swift.result -emit-remap-file-path %t/member.swift.remap -o /dev/null
// RUN: diff -u %S/member.swift.expected %t/member.swift.result

import Bar
Expand Down
2 changes: 1 addition & 1 deletion test/Migrator/member.swift.expected
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// REQUIRES: objc_interop
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -primary-file %s -F %S/mock-sdk -api-diff-data-file %S/API.json -emit-migrated-file-path %t/member.swift.result -emit-remap-file-path %t/member.swift.remap
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -primary-file %s -F %S/mock-sdk -api-diff-data-file %S/API.json -emit-migrated-file-path %t/member.swift.result -emit-remap-file-path %t/member.swift.remap -o /dev/null
// RUN: diff -u %S/member.swift.expected %t/member.swift.result

import Bar
Expand Down
11 changes: 11 additions & 0 deletions test/Migrator/minimal_objc_inference.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -primary-file %S/Inputs/minimal_objc_inference.swift -emit-migrated-file-path %t/migrated_minimal_objc_inference.swift -emit-remap-file-path %t/migrated_minimal_objc_inference.swift.remap -o /dev/null
// RUN: %FileCheck %s < %t/migrated_minimal_objc_inference.swift
// REQUIRES: objc_interop

// CHECK-NOT: @objc var propertyUsedInKeyPath: NSObject? = nil
// CHECK: @objc dynamic var dynamicVarUsedInSelector : Int { return 2 }
// CHECK-NOT: @objc func overridden() {}
// CHECK-NOT: @objc func usedViaAnyObject() {}
// CHECK-NOT: @objc func inExtensionAndOverridden() {}
// CHECK-NOT: @objc func unused() {}

2 changes: 1 addition & 1 deletion test/Migrator/null_migration.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -primary-file %s -emit-migrated-file-path %t/migrated_null_migration.swift -emit-remap-file-path %t/null_migration.remap
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -primary-file %s -emit-migrated-file-path %t/migrated_null_migration.swift -emit-remap-file-path %t/null_migration.remap -o /dev/null
// RUN: diff -u %s %t/migrated_null_migration.swift

// This file tests that, if all migration passes are no-op,
Expand Down
37 changes: 0 additions & 37 deletions test/Migrator/objc_inference.swift

This file was deleted.

2 changes: 1 addition & 1 deletion test/Migrator/property.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// REQUIRES: objc_interop
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -primary-file %s -F %S/mock-sdk -api-diff-data-file %S/API.json -emit-migrated-file-path %t/property.swift.result -disable-migrator-fixits
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -primary-file %s -F %S/mock-sdk -api-diff-data-file %S/API.json -emit-migrated-file-path %t/property.swift.result -disable-migrator-fixits -o /dev/null
// RUN: diff -u %S/property.swift.expected %t/property.swift.result

import Bar
Expand Down
2 changes: 1 addition & 1 deletion test/Migrator/property.swift.expected
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// REQUIRES: objc_interop
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -primary-file %s -F %S/mock-sdk -api-diff-data-file %S/API.json -emit-migrated-file-path %t/property.swift.result -disable-migrator-fixits
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -primary-file %s -F %S/mock-sdk -api-diff-data-file %S/API.json -emit-migrated-file-path %t/property.swift.result -disable-migrator-fixits -o /dev/null
// RUN: diff -u %S/property.swift.expected %t/property.swift.result

import Bar
Expand Down
2 changes: 1 addition & 1 deletion test/Migrator/rename-init.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// REQUIRES: objc_interop
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -primary-file %s -F %S/mock-sdk -api-diff-data-file %S/API.json -emit-migrated-file-path %t/rename-init.swift.result -disable-migrator-fixits
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -primary-file %s -F %S/mock-sdk -api-diff-data-file %S/API.json -emit-migrated-file-path %t/rename-init.swift.result -disable-migrator-fixits -o /dev/null
// RUN: diff -u %S/rename-init.swift.expected %t/rename-init.swift.result

import Bar
Expand Down
2 changes: 1 addition & 1 deletion test/Migrator/rename-init.swift.expected
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// REQUIRES: objc_interop
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -primary-file %s -F %S/mock-sdk -api-diff-data-file %S/API.json -emit-migrated-file-path %t/rename-init.swift.result -disable-migrator-fixits
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -primary-file %s -F %S/mock-sdk -api-diff-data-file %S/API.json -emit-migrated-file-path %t/rename-init.swift.result -disable-migrator-fixits -o /dev/null
// RUN: diff -u %S/rename-init.swift.expected %t/rename-init.swift.result

import Bar
Expand Down
2 changes: 1 addition & 1 deletion test/Migrator/rename.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// REQUIRES: objc_interop
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -primary-file %s -F %S/mock-sdk -api-diff-data-file %S/API.json -emit-migrated-file-path %t/rename.swift.result -emit-remap-file-path %t/rename.swift.remap
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -primary-file %s -F %S/mock-sdk -api-diff-data-file %S/API.json -emit-migrated-file-path %t/rename.swift.result -emit-remap-file-path %t/rename.swift.remap -o /dev/null
// RUN: diff -u %S/rename.swift.expected %t/rename.swift.result

import Bar
Expand Down
2 changes: 1 addition & 1 deletion test/Migrator/rename.swift.expected
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// REQUIRES: objc_interop
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -primary-file %s -F %S/mock-sdk -api-diff-data-file %S/API.json -emit-migrated-file-path %t/rename.swift.result -emit-remap-file-path %t/rename.swift.remap
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -primary-file %s -F %S/mock-sdk -api-diff-data-file %S/API.json -emit-migrated-file-path %t/rename.swift.result -emit-remap-file-path %t/rename.swift.remap -o /dev/null
// RUN: diff -u %S/rename.swift.expected %t/rename.swift.result

import Bar
Expand Down
2 changes: 1 addition & 1 deletion test/Migrator/wrap_optional.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// REQUIRES: objc_interop
// RUN: rm -rf %t.mod && mkdir -p %t.mod
// RUN: %target-swift-frontend -emit-module -o %t.mod/cities.swiftmodule %S/Inputs/cities.swift -module-name Cities -parse-as-library
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -api-diff-data-file %S/API.json -emit-migrated-file-path %t/wrap_optional.swift.result -o %t/wrap_optional.swift.remap
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -api-diff-data-file %S/API.json -emit-migrated-file-path %t/wrap_optional.swift.result -o %t/wrap_optional.swift.remap -o /dev/null
// RUN: diff -u %S/wrap_optional.swift.expected %t/wrap_optional.swift.result

import Cities
Expand Down
2 changes: 1 addition & 1 deletion test/Migrator/wrap_optional.swift.expected
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// REQUIRES: objc_interop
// RUN: rm -rf %t.mod && mkdir -p %t.mod
// RUN: %target-swift-frontend -emit-module -o %t.mod/cities.swiftmodule %S/Inputs/cities.swift -module-name Cities -parse-as-library
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -api-diff-data-file %S/API.json -emit-migrated-file-path %t/wrap_optional.swift.result -o %t/wrap_optional.swift.remap
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -api-diff-data-file %S/API.json -emit-migrated-file-path %t/wrap_optional.swift.result -o %t/wrap_optional.swift.remap -o /dev/null
// RUN: diff -u %S/wrap_optional.swift.expected %t/wrap_optional.swift.result

import Cities
Expand Down