Skip to content

Commit

Permalink
Add '_spi(TokamakCore)' to ideally internal public members. (#386)
Browse files Browse the repository at this point in the history
Adds `_spi(TokamakCore)` to the modules:
1. TokamakCore
2. TokamakDOM
3. TokamakGTK
4. TokamakStaticHTML

The attribute is applied to:
1. All `View` bodies in TokamakCore — either primitive or regular like `Color`
2. `ViewDeferredToRenderer` bodies
4. `ParentView` `children` members
5. `View` modifiers (such as  `_onMount(perform:)`)
6. Other members of types (like `Color._withScheme`, and `_AnyApp._launch`) 

The attribute semantics (from my brief testing)
1. It can only be applied to `public` declarations
2. It ensures that every SPI declaration is exposed only by other SPI declarations (i.e. `@_spi(Module) public enum A {}; public var a: A` is illegal)
3. Regularly importing a library prohibits clients from accessing SPI declarations that are not protocol witnesses (with an error).
4. Regularly importing a library "discourages" clients from accessing SPI protocol witnesses by hiding them from the autocompletion suggestions (i.e. users can still access `body` of `Text`, but autocompletion hides it).
5. For a declaration marked with `@_spi(Module)`, a client has to write `@_spi(Module) import Library` in order to normally access such SPI declarations.

* Add '_spi(TokamakCore)' to ideally internal public members.

* Remove `_spi` attribute on '_ConditionalContent'.

* Remove spi from 'Path._PathBox', 'Font._Font', and '_TupleScene.body'.

* Remove spi from types.

* Remove trailing whitespace.

* Apply spi to 'View' modifiers.

* Add _spi imports.

* Introduce 'PrimitiveView'.

* Remove 'PrimitiveView' conformances outside of TokamakCore.

* Fix `PrimitiveView` default implementation.

* Remove "BubbleCore" references.
  • Loading branch information
filip-sakel committed Mar 8, 2021
1 parent 4a1101c commit 4d211af
Show file tree
Hide file tree
Showing 82 changed files with 131 additions and 164 deletions.
1 change: 1 addition & 0 deletions Sources/TokamakCore/App/AppStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ struct DefaultAppStorageEnvironmentKey: EnvironmentKey {
}

public extension EnvironmentValues {
@_spi(TokamakCore)
var _defaultAppStorage: _StorageProvider? {
get {
self[DefaultAppStorageEnvironmentKey.self]
Expand Down
1 change: 1 addition & 0 deletions Sources/TokamakCore/App/Scenes/WindowGroup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public struct WindowGroup<Content>: Scene, TitledScene where Content: View {
self.content = content()
}

@_spi(TokamakCore)
public var body: Never {
neverScene("WindowGroup")
}
Expand Down
1 change: 1 addition & 0 deletions Sources/TokamakCore/App/Scenes/_SceneModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public struct _SceneModifier_Content<Modifier>: Scene where Modifier: _SceneModi
public let modifier: Modifier
public let scene: _AnyScene

@_spi(TokamakCore)
public var body: Never {
neverScene("_SceneModifier_Content")
}
Expand Down
6 changes: 6 additions & 0 deletions Sources/TokamakCore/App/_AnyApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,32 @@ public struct _AnyApp: App {
bodyType = A.Body.self
}

@_spi(TokamakCore)
public var body: Never {
neverScene("_AnyApp")
}

@_spi(TokamakCore)
public init() {
fatalError("`_AnyApp` cannot be initialized without an underlying `App` type.")
}

@_spi(TokamakCore)
public static func _launch(_ app: Self, _ rootEnvironment: EnvironmentValues) {
fatalError("`_AnyApp` cannot be launched. Access underlying `app` value.")
}

@_spi(TokamakCore)
public static func _setTitle(_ title: String) {
fatalError("`title` cannot be set for `AnyApp`. Access underlying `app` value.")
}

@_spi(TokamakCore)
public var _phasePublisher: AnyPublisher<ScenePhase, Never> {
fatalError("`_AnyApp` cannot monitor scenePhase. Access underlying `app` value.")
}

@_spi(TokamakCore)
public var _colorSchemePublisher: AnyPublisher<ColorScheme, Never> {
fatalError("`_AnyApp` cannot monitor colorScheme. Access underlying `app` value.")
}
Expand Down
1 change: 1 addition & 0 deletions Sources/TokamakCore/App/_AnyScene.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public struct _AnyScene: Scene {
}
}

@_spi(TokamakCore)
public var body: Never {
neverScene("_AnyScene")
}
Expand Down
2 changes: 2 additions & 0 deletions Sources/TokamakCore/Modifiers/LifecycleModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@

// FIXME: these should have standalone implementations
public extension View {
@_spi(TokamakCore)
func _onMount(perform action: (() -> ())? = nil) -> some View {
modifier(_AppearanceActionModifier(appear: action))
}

@_spi(TokamakCore)
func _onUnmount(perform action: (() -> ())? = nil) -> some View {
modifier(_AppearanceActionModifier(disappear: action))
}
Expand Down
6 changes: 0 additions & 6 deletions Sources/TokamakCore/Preferences/PreferenceKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,6 @@ public protocol _PreferenceWritingModifierProtocol: ViewModifier
func body(_ content: Self.Content, with preferenceStore: inout _PreferenceStore) -> AnyView
}

public extension _PreferenceWritingViewProtocol where Self: View {
var body: Never {
neverBody(String(describing: Self.self))
}
}

public extension _PreferenceWritingModifierProtocol {
func body(content: Content) -> AnyView {
content.view
Expand Down
6 changes: 1 addition & 5 deletions Sources/TokamakCore/Shapes/Shape.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public struct FillStyle: Equatable, ShapeStyle {
}
}

public struct _ShapeView<Content, Style>: View where Content: Shape, Style: ShapeStyle {
public struct _ShapeView<Content, Style>: PrimitiveView where Content: Shape, Style: ShapeStyle {
@Environment(\.self) public var environment
@Environment(\.foregroundColor) public var foregroundColor
public var shape: Content
Expand All @@ -58,10 +58,6 @@ public struct _ShapeView<Content, Style>: View where Content: Shape, Style: Shap
self.style = style
self.fillStyle = fillStyle
}

public var body: Never {
neverBody("_ShapeView")
}
}

public extension Shape {
Expand Down
1 change: 1 addition & 0 deletions Sources/TokamakCore/State/TargetRef.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public struct _TargetRef<V: View, T>: View, TargetRefType {
public extension View {
/** Allows capturing target instance of aclosest descendant host view. The resulting instance
is written to a given `binding`. */
@_spi(TokamakCore)
func _targetRef<T: Target>(_ binding: Binding<T?>) -> _TargetRef<Self, T> {
.init(binding: binding, view: self)
}
Expand Down
5 changes: 1 addition & 4 deletions Sources/TokamakCore/Styles/ButtonStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,8 @@
// Created by Gene Z. Ragan on 07/22/2020.

public struct ButtonStyleConfiguration {
public struct Label: View {
public struct Label: PrimitiveView {
let content: AnyView
public var body: Never {
neverBody("ButtonStyleConfiguration.Label")
}
}

public let label: Label
Expand Down
1 change: 1 addition & 0 deletions Sources/TokamakCore/Styles/NavigationLinkStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ extension EnvironmentValues {
}

public extension View {
@_spi(TokamakCore)
func _navigationLinkStyle<S: _NavigationLinkStyle>(_ style: S) -> some View {
environment(\._navigationLinkStyle, _AnyNavigationLinkStyle(style))
}
Expand Down
2 changes: 2 additions & 0 deletions Sources/TokamakCore/Tokens/Color.swift
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ public struct Color: Hashable, Equatable {
}

/// Create a `Color` dependent on the current `ColorScheme`.
@_spi(TokamakCore)
public static func _withScheme(_ resolver: @escaping (ColorScheme) -> Self) -> Self {
.init(_EnvironmentDependentColorBox {
resolver($0.colorScheme)
Expand Down Expand Up @@ -344,6 +345,7 @@ public extension Color {

extension Color: ShapeStyle {}
extension Color: View {
@_spi(TokamakCore)
public var body: some View {
_ShapeView(shape: Rectangle(), style: self)
}
Expand Down
7 changes: 2 additions & 5 deletions Sources/TokamakCore/Views/AnyView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
//

/// A type-erased view.
public struct AnyView: View {
public struct AnyView: PrimitiveView {
/// The type of the underlying `view`.
let type: Any.Type

Expand Down Expand Up @@ -67,10 +67,6 @@ public struct AnyView: View {
}
}
}

public var body: Never {
neverBody("AnyView")
}
}

public func mapAnyView<T, V>(_ anyView: AnyView, transform: (V) -> T) -> T? {
Expand All @@ -80,6 +76,7 @@ public func mapAnyView<T, V>(_ anyView: AnyView, transform: (V) -> T) -> T? {
}

extension AnyView: ParentView {
@_spi(TokamakCore)
public var children: [AnyView] {
(view as? ParentView)?.children ?? []
}
Expand Down
8 changes: 3 additions & 5 deletions Sources/TokamakCore/Views/Buttons/Button.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,13 @@ public struct Button<Label>: View where Label: View {
implementation = _Button(action: action, label: label())
}

@_spi(TomkamakCore)
public var body: some View {
implementation
}
}

public struct _Button<Label>: View where Label: View {
public struct _Button<Label>: PrimitiveView where Label: View {
public let label: Label
public let action: () -> ()
@State public var isPressed = false
Expand All @@ -57,10 +58,6 @@ public struct _Button<Label>: View where Label: View {
self.label = label
self.action = action
}

public var body: Never {
neverBody("_Button")
}
}

public extension Button where Label == Text {
Expand All @@ -72,6 +69,7 @@ public extension Button where Label == Text {
}

extension Button: ParentView {
@_spi(TokamakCore)
public var children: [AnyView] {
(implementation.label as? GroupView)?.children ?? [AnyView(implementation.label)]
}
Expand Down
6 changes: 1 addition & 5 deletions Sources/TokamakCore/Views/Buttons/Link.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,13 @@

import struct Foundation.URL

public struct Link<Label>: View where Label: View {
public struct Link<Label>: PrimitiveView where Label: View {
let destination: URL
let label: Label

public init(destination: URL, @ViewBuilder label: () -> Label) {
(self.destination, self.label) = (destination, label())
}

public var body: Never {
neverBody("Link")
}
}

public extension Link where Label == Text {
Expand Down
6 changes: 1 addition & 5 deletions Sources/TokamakCore/Views/Containers/DisclosureGroup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// Created by Carson Katri on 7/3/20.
//

public struct DisclosureGroup<Label, Content>: View where Label: View, Content: View {
public struct DisclosureGroup<Label, Content>: PrimitiveView where Label: View, Content: View {
@State var isExpanded: Bool = false
let isExpandedBinding: Binding<Bool>?

Expand All @@ -39,10 +39,6 @@ public struct DisclosureGroup<Label, Content>: View where Label: View, Content:
self.label = label()
self.content = content
}

public var body: Never {
neverBody("DisclosureGroup")
}
}

public extension DisclosureGroup where Label == Text {
Expand Down
8 changes: 3 additions & 5 deletions Sources/TokamakCore/Views/Containers/ForEach.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ protocol ForEachProtocol: GroupView {
/// Text("\($0)")
/// }
/// }
public struct ForEach<Data, ID, Content>: View where Data: RandomAccessCollection, ID: Hashable,
public struct ForEach<Data, ID, Content>: PrimitiveView where Data: RandomAccessCollection,
ID: Hashable,
Content: View
{
let data: Data
Expand All @@ -47,10 +48,6 @@ public struct ForEach<Data, ID, Content>: View where Data: RandomAccessCollectio
self.id = id
self.content = content
}

public var body: Never {
neverBody("ForEach")
}
}

extension ForEach: ForEachProtocol where Data.Index == Int {
Expand Down Expand Up @@ -79,6 +76,7 @@ public extension ForEach where Data == Range<Int>, ID == Int {
}

extension ForEach: ParentView {
@_spi(TokamakCore)
public var children: [AnyView] {
data.map { AnyView(IDView(content($0), id: $0[keyPath: id])) }
}
Expand Down
7 changes: 2 additions & 5 deletions Sources/TokamakCore/Views/Containers/Group.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,10 @@ public struct Group<Content> {
}
}

extension Group: View where Content: View {
public var body: Never {
neverBody("Group")
}
}
extension Group: PrimitiveView & View where Content: View {}

extension Group: ParentView where Content: View {
@_spi(TokamakCore)
public var children: [AnyView] { (content as? ParentView)?.children ?? [AnyView(content)] }
}

Expand Down
1 change: 1 addition & 0 deletions Sources/TokamakCore/Views/Containers/List.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public struct List<SelectionValue, Content>: View
}
}

@_spi(TokamakCore)
public var body: some View {
if let style = style as? ListStyleDeferredToRenderer {
style.listBody(ScrollView {
Expand Down
2 changes: 2 additions & 0 deletions Sources/TokamakCore/Views/Containers/OutlineGroup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ public extension OutlineGroup where Parent: View,
}

extension OutlineGroup: View where Parent: View, Leaf: View, Subgroup: View {
@_spi(TokamakCore)
public var body: some View {
switch root {
case let .collection(data):
Expand Down Expand Up @@ -124,6 +125,7 @@ extension OutlineGroup: View where Parent: View, Leaf: View, Subgroup: View {
public struct OutlineSubgroupChildren: View {
let children: () -> AnyView

@_spi(TokamakCore)
public var body: some View {
children()
}
Expand Down
1 change: 1 addition & 0 deletions Sources/TokamakCore/Views/Containers/Section.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ extension Section: View, SectionView where Parent: View, Content: View, Footer:
}

@ViewBuilder
@_spi(TokamakCore)
public var body: TupleView<(Parent, Content, Footer)> {
header
content
Expand Down
6 changes: 1 addition & 5 deletions Sources/TokamakCore/Views/Containers/TupleView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,7 @@
/// A `View` created from a `Tuple` of `View` values.
///
/// Mainly for use with `@ViewBuilder`.
public struct TupleView<T>: View {
public var body: Never {
neverBody("TupleView")
}

public struct TupleView<T>: PrimitiveView {
public let value: T

let _children: [AnyView]
Expand Down
6 changes: 1 addition & 5 deletions Sources/TokamakCore/Views/Image.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

import Foundation

public struct Image: View {
public struct Image: PrimitiveView {
let label: Text?
let name: String
let bundle: Bundle?
Expand All @@ -39,10 +39,6 @@ public struct Image: View {
self.name = name
self.bundle = bundle
}

public var body: Never {
neverBody("Image")
}
}

/// This is a helper type that works around absence of "package private" access control in Swift
Expand Down
6 changes: 1 addition & 5 deletions Sources/TokamakCore/Views/Layout/GeometryReader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,9 @@ public func makeProxy(from size: CGSize) -> GeometryProxy {
// public subscript<T>(anchor: Anchor<T>) -> T {}
// }

public struct GeometryReader<Content>: View where Content: View {
public struct GeometryReader<Content>: PrimitiveView where Content: View {
public let content: (GeometryProxy) -> Content
public init(@ViewBuilder content: @escaping (GeometryProxy) -> Content) {
self.content = content
}

public var body: Never {
neverBody("GeometryReader")
}
}
Loading

0 comments on commit 4d211af

Please sign in to comment.