Skip to content
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
12 changes: 12 additions & 0 deletions lib/IRGen/TBDGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,18 @@ void swift::writeTBDFile(ModuleDecl *M, llvm::raw_ostream &os,
class APIGenRecorder final : public APIRecorder {
static bool isSPI(const Decl *decl) {
assert(decl);

if (auto value = dyn_cast<ValueDecl>(decl)) {
auto accessScope =
value->getFormalAccessScope(/*useDC=*/nullptr,
/*treatUsableFromInlineAsPublic=*/true);
// Only declarations with a public access scope (`public` or `open`)
// can be APIs. Exported declarations with other access scopes (`package`)
// should be SPI.
if (!accessScope.isPublic())
return true;
}

return decl->isSPI() || decl->isAvailableAsSPI();
}

Expand Down
120 changes: 116 additions & 4 deletions test/APIJSON/apigen.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// REQUIRES: objc_interop, OS=macosx
// RUN: %empty-directory(%t)
// RUN: %empty-directory(%t/ModuleCache)
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 -emit-api-descriptor-path %t/api.json
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -package-name MyModule -swift-version 5
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -package-name MyModule -swift-version 5 -emit-api-descriptor-path %t/api.json
// RUN: %validate-json %t/api.json | %FileCheck %s

import Foundation
Expand All @@ -19,6 +19,21 @@ public class Test : NSObject {
public class Derived : Test {
@objc public override func method1() {}
public override func nonObjc() {}

private var _readOnly : Int
package init(readOnly: Int) {
_readOnly = readOnly
}
public package(set) var readOnly : Int {
get { _readOnly }
set { _readOnly = newValue }
}
}

// Member declarations inside a `public extension` are public implicitly
public extension Derived {
func inheritlyPublic() {}
private func privateFunc() {}
}

// Not derived from NSObject. ObjC metadata is still emitted but not exported.
Expand All @@ -35,7 +50,7 @@ public class Test3 : NSObject {
}

@available(macOS 10.13, *)
public func myFunction() -> Int {
package func myFunction() -> Int {
return 0
}

Expand All @@ -45,14 +60,24 @@ public func myFunction1() {}
@available(*, unavailable)
public func myFunction2() {}

package func packageFunction() {}

internal func internalFunction() {}

private func privateFunction() {}

fileprivate func fileprivateFunction() {}

func implicitInternalFunction() {}

@available(macOS 10.13, *)
public var myGlobalVar: Int = 42

// CHECK: "target"
// CHECK-NEXT: "globals": [
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule10myFunctionSiyF",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "access": "private",
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift",
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
Expand Down Expand Up @@ -93,6 +118,12 @@ public var myGlobalVar: Int = 42
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule15packageFunctionyyF",
// CHECK-NEXT: "access": "private",
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule4TestC7method1yyFTj",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift",
Expand Down Expand Up @@ -316,6 +347,80 @@ public var myGlobalVar: Int = 42
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule7DerivedC15inheritlyPublicyyF",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule7DerivedC8readOnlyACSi_tcfC",
// CHECK-NEXT: "access": "private",
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule7DerivedC8readOnlyACSi_tcfCTj",
// CHECK-NEXT: "access": "private",
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule7DerivedC8readOnlyACSi_tcfCTq",
// CHECK-NEXT: "access": "private",
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule7DerivedC8readOnlyACSi_tcfc",
// CHECK-NEXT: "access": "private",
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule7DerivedC8readOnlySivMTj",
// CHECK-NEXT: "access": "private",
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift",
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule7DerivedC8readOnlySivMTq",
// CHECK-NEXT: "access": "private",
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift",
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule7DerivedC8readOnlySivgTj",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule7DerivedC8readOnlySivgTq",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule7DerivedC8readOnlySivpMV",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule7DerivedC8readOnlySivsTj",
// CHECK-NEXT: "access": "private",
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule7DerivedC8readOnlySivsTq",
// CHECK-NEXT: "access": "private",
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule7DerivedCACycfC",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift",
Expand Down Expand Up @@ -349,6 +454,13 @@ public var myGlobalVar: Int = 42
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule7DerivedCMu",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift",
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule7DerivedCN",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift",
Expand Down