@swiftbrowser/swift 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (400) hide show
  1. package/Package.swift +214 -0
  2. package/README.md +10 -2
  3. package/Sources/AVFoundation/AVFoundation.swift +131 -0
  4. package/Sources/AVFoundation/Asset.swift +487 -0
  5. package/Sources/AVFoundation/AudioSession.swift +144 -0
  6. package/Sources/AVFoundation/CMTime.swift +303 -0
  7. package/Sources/AVFoundation/Capture.swift +688 -0
  8. package/Sources/AVFoundation/Player.swift +749 -0
  9. package/Sources/AVFoundation/PlayerView.swift +117 -0
  10. package/Sources/AVKit/AVKit.swift +132 -0
  11. package/Sources/Accelerate/Accelerate.swift +122 -0
  12. package/Sources/AppIntents/AppIntents.swift +144 -0
  13. package/Sources/AppIntents/Parameters.swift +220 -0
  14. package/Sources/AppIntents/Shortcuts.swift +159 -0
  15. package/Sources/AudioToolbox/AudioToolbox.swift +55 -0
  16. package/Sources/AuthenticationServices/AuthenticationServices.swift +257 -0
  17. package/Sources/AuthenticationServices/Authorization.swift +251 -0
  18. package/Sources/Charts/Charts.swift +61 -0
  19. package/Sources/Combine/AnyCancellable.swift +65 -0
  20. package/Sources/Combine/AnyPublisher.swift +148 -0
  21. package/Sources/Combine/AnySubscriber.swift +230 -0
  22. package/Sources/Combine/Cancellable.swift +35 -0
  23. package/Sources/Combine/Codable.swift +29 -0
  24. package/Sources/Combine/CombineIdentifier.swift +45 -0
  25. package/Sources/Combine/Concurrency/ConcurrencyHelpers.swift +24 -0
  26. package/Sources/Combine/Concurrency/Future+Concurrency.swift +136 -0
  27. package/Sources/Combine/Concurrency/GENERATED-Publisher+Concurrency.swift +397 -0
  28. package/Sources/Combine/CurrentValueSubject.swift +252 -0
  29. package/Sources/Combine/CustomCombineIdentifierConvertible.swift +28 -0
  30. package/Sources/Combine/Future.swift +228 -0
  31. package/Sources/Combine/GENERATED-RootProtocols.swift +426 -0
  32. package/Sources/Combine/Helpers/ConduitBase.swift +40 -0
  33. package/Sources/Combine/Helpers/ConduitList.swift +59 -0
  34. package/Sources/Combine/Helpers/DebugHook.swift +177 -0
  35. package/Sources/Combine/Helpers/FilterProducer.swift +174 -0
  36. package/Sources/Combine/Helpers/Locking.swift +30 -0
  37. package/Sources/Combine/Helpers/PartialCompletion.swift +26 -0
  38. package/Sources/Combine/Helpers/ReduceProducer.swift +249 -0
  39. package/Sources/Combine/Helpers/SubjectSubscriber.swift +96 -0
  40. package/Sources/Combine/Helpers/SubscriberTap.swift +69 -0
  41. package/Sources/Combine/Helpers/SubscriptionStatus.swift +33 -0
  42. package/Sources/Combine/Helpers/SubscriptionTap.swift +33 -0
  43. package/Sources/Combine/Helpers/Utils.swift +30 -0
  44. package/Sources/Combine/Helpers/Violations.swift +33 -0
  45. package/Sources/Combine/ImmediateScheduler.swift +178 -0
  46. package/Sources/Combine/LICENSE +21 -0
  47. package/Sources/Combine/NotificationPublisher.swift +48 -0
  48. package/Sources/Combine/ObjectWillChange.swift +46 -0
  49. package/Sources/Combine/PassthroughSubject.swift +222 -0
  50. package/Sources/Combine/Publisher+Subscribe.swift +53 -0
  51. package/Sources/Combine/Publishers/Deferred.swift +48 -0
  52. package/Sources/Combine/Publishers/Empty.swift +54 -0
  53. package/Sources/Combine/Publishers/Fail.swift +42 -0
  54. package/Sources/Combine/Publishers/GENERATED-Publishers.Catch.swift +673 -0
  55. package/Sources/Combine/Publishers/GENERATED-Publishers.Encode.swift +388 -0
  56. package/Sources/Combine/Publishers/GENERATED-Publishers.MapKeyPath.swift +384 -0
  57. package/Sources/Combine/Publishers/Just.swift +313 -0
  58. package/Sources/Combine/Publishers/Optional.Publisher.swift +315 -0
  59. package/Sources/Combine/Publishers/Publishers.AllSatisfy.swift +217 -0
  60. package/Sources/Combine/Publishers/Publishers.AssertNoFailure.swift +158 -0
  61. package/Sources/Combine/Publishers/Publishers.Autoconnect.swift +193 -0
  62. package/Sources/Combine/Publishers/Publishers.Breakpoint.swift +231 -0
  63. package/Sources/Combine/Publishers/Publishers.Buffer.swift +356 -0
  64. package/Sources/Combine/Publishers/Publishers.Collect.swift +102 -0
  65. package/Sources/Combine/Publishers/Publishers.CollectByCount.swift +195 -0
  66. package/Sources/Combine/Publishers/Publishers.CompactMap.swift +241 -0
  67. package/Sources/Combine/Publishers/Publishers.Comparison.swift +371 -0
  68. package/Sources/Combine/Publishers/Publishers.Concatenate.swift +474 -0
  69. package/Sources/Combine/Publishers/Publishers.Contains.swift +293 -0
  70. package/Sources/Combine/Publishers/Publishers.Count.swift +87 -0
  71. package/Sources/Combine/Publishers/Publishers.Debounce.swift +332 -0
  72. package/Sources/Combine/Publishers/Publishers.Delay.swift +269 -0
  73. package/Sources/Combine/Publishers/Publishers.Drop.swift +155 -0
  74. package/Sources/Combine/Publishers/Publishers.DropUntilOutput.swift +283 -0
  75. package/Sources/Combine/Publishers/Publishers.DropWhile.swift +378 -0
  76. package/Sources/Combine/Publishers/Publishers.Filter.swift +248 -0
  77. package/Sources/Combine/Publishers/Publishers.First.swift +261 -0
  78. package/Sources/Combine/Publishers/Publishers.FlatMap.swift +533 -0
  79. package/Sources/Combine/Publishers/Publishers.HandleEvents.swift +260 -0
  80. package/Sources/Combine/Publishers/Publishers.IgnoreOutput.swift +109 -0
  81. package/Sources/Combine/Publishers/Publishers.Last.swift +252 -0
  82. package/Sources/Combine/Publishers/Publishers.MakeConnectable.swift +82 -0
  83. package/Sources/Combine/Publishers/Publishers.Map.swift +351 -0
  84. package/Sources/Combine/Publishers/Publishers.MapError.swift +140 -0
  85. package/Sources/Combine/Publishers/Publishers.MeasureInterval.swift +187 -0
  86. package/Sources/Combine/Publishers/Publishers.Multicast.swift +284 -0
  87. package/Sources/Combine/Publishers/Publishers.Output.swift +241 -0
  88. package/Sources/Combine/Publishers/Publishers.PrefixUntilOutput.swift +197 -0
  89. package/Sources/Combine/Publishers/Publishers.PrefixWhile.swift +176 -0
  90. package/Sources/Combine/Publishers/Publishers.Print.swift +206 -0
  91. package/Sources/Combine/Publishers/Publishers.ReceiveOn.swift +227 -0
  92. package/Sources/Combine/Publishers/Publishers.Reduce.swift +204 -0
  93. package/Sources/Combine/Publishers/Publishers.RemoveDuplicates.swift +264 -0
  94. package/Sources/Combine/Publishers/Publishers.ReplaceEmpty.swift +201 -0
  95. package/Sources/Combine/Publishers/Publishers.ReplaceError.swift +211 -0
  96. package/Sources/Combine/Publishers/Publishers.Retry.swift +274 -0
  97. package/Sources/Combine/Publishers/Publishers.Scan.swift +331 -0
  98. package/Sources/Combine/Publishers/Publishers.Sequence.swift +437 -0
  99. package/Sources/Combine/Publishers/Publishers.SetFailureType.swift +120 -0
  100. package/Sources/Combine/Publishers/Publishers.Share.swift +104 -0
  101. package/Sources/Combine/Publishers/Publishers.SubscribeOn.swift +197 -0
  102. package/Sources/Combine/Publishers/Publishers.SwitchToLatest.swift +444 -0
  103. package/Sources/Combine/Publishers/Publishers.Throttle.swift +359 -0
  104. package/Sources/Combine/Publishers/Publishers.Timeout.swift +301 -0
  105. package/Sources/Combine/Publishers/Publishers.Zip.swift +720 -0
  106. package/Sources/Combine/Publishers/Publishers.swift +13 -0
  107. package/Sources/Combine/Publishers/Record.swift +237 -0
  108. package/Sources/Combine/Publishers/Result.Publisher.swift +337 -0
  109. package/Sources/Combine/Result.swift +46 -0
  110. package/Sources/Combine/Scheduler.swift +89 -0
  111. package/Sources/Combine/Schedulers.swift +211 -0
  112. package/Sources/Combine/Subject+Void.swift +17 -0
  113. package/Sources/Combine/Subscriber+Void.swift +20 -0
  114. package/Sources/Combine/Subscribers/Subscribers.Assign.swift +175 -0
  115. package/Sources/Combine/Subscribers/Subscribers.Completion.swift +90 -0
  116. package/Sources/Combine/Subscribers/Subscribers.Demand.swift +476 -0
  117. package/Sources/Combine/Subscribers/Subscribers.Sink.swift +206 -0
  118. package/Sources/Combine/Subscribers/Subscribers.swift +9 -0
  119. package/Sources/Combine/Subscription.swift +22 -0
  120. package/Sources/Combine/Subscriptions.swift +42 -0
  121. package/Sources/Combine/SwiftUIObservation.swift +10 -0
  122. package/Sources/Combine/_Introspection.swift +107 -0
  123. package/Sources/CommonCrypto/CommonCrypto.swift +80 -0
  124. package/Sources/Compression/Compression.swift +365 -0
  125. package/Sources/Compression/Deflate.swift +407 -0
  126. package/Sources/Compression/Zlib.swift +179 -0
  127. package/Sources/CoreFoundationTypes/CoreFoundationTypes.swift +101 -0
  128. package/Sources/CoreGraphics/CoreGraphics.swift +411 -0
  129. package/Sources/CoreGraphics/ProjectionTransforms.swift +28 -0
  130. package/Sources/CoreHaptics/CoreHaptics.swift +399 -0
  131. package/Sources/CoreImage/CIColor.swift +41 -0
  132. package/Sources/CoreImage/CIContext.swift +31 -0
  133. package/Sources/CoreImage/CIDetector.swift +57 -0
  134. package/Sources/CoreImage/CIFilter.swift +243 -0
  135. package/Sources/CoreImage/CIFilterBuiltins.swift +136 -0
  136. package/Sources/CoreImage/CIImage.swift +162 -0
  137. package/Sources/CoreImage/QRCode.swift +393 -0
  138. package/Sources/CoreLocation/Coordinate.swift +30 -0
  139. package/Sources/CoreLocation/Location.swift +65 -0
  140. package/Sources/CoreML/Evaluation.swift +414 -0
  141. package/Sources/CoreML/FeatureValue.swift +266 -0
  142. package/Sources/CoreML/Model.swift +269 -0
  143. package/Sources/CoreML/MultiArray.swift +92 -0
  144. package/Sources/CoreML/Specification.swift +233 -0
  145. package/Sources/CoreText/CoreText.swift +64 -0
  146. package/Sources/CoreTransferable/CoreTransferable.swift +606 -0
  147. package/Sources/CryptoKit/ChaChaPoly.swift +258 -0
  148. package/Sources/CryptoKit/CryptoKit.swift +375 -0
  149. package/Sources/CryptoKit/Curve25519.swift +317 -0
  150. package/Sources/CryptoKit/P256.swift +321 -0
  151. package/Sources/FoundationBridge/AppStorage.swift +165 -0
  152. package/Sources/FoundationBridge/AssetResources.swift +90 -0
  153. package/Sources/FoundationBridge/AsyncBytes.swift +128 -0
  154. package/Sources/FoundationBridge/AsyncImage.swift +116 -0
  155. package/Sources/FoundationBridge/AttributedStrings.swift +16 -0
  156. package/Sources/FoundationBridge/Bundle.swift +119 -0
  157. package/Sources/FoundationBridge/CombineExports.swift +8 -0
  158. package/Sources/FoundationBridge/CoreFoundation.swift +77 -0
  159. package/Sources/FoundationBridge/Dispatch.swift +458 -0
  160. package/Sources/FoundationBridge/EnvironmentFoundation.swift +41 -0
  161. package/Sources/FoundationBridge/FileImporter.swift +128 -0
  162. package/Sources/FoundationBridge/FileSystem.swift +68 -0
  163. package/Sources/FoundationBridge/FoundationBridge.swift +29 -0
  164. package/Sources/FoundationBridge/HostResolution.swift +31 -0
  165. package/Sources/FoundationBridge/ItemProvider.swift +655 -0
  166. package/Sources/FoundationBridge/KeyValueObserving.swift +138 -0
  167. package/Sources/FoundationBridge/Links.swift +127 -0
  168. package/Sources/FoundationBridge/ListFormatter.swift +32 -0
  169. package/Sources/FoundationBridge/Locale.swift +86 -0
  170. package/Sources/FoundationBridge/Localization.swift +149 -0
  171. package/Sources/FoundationBridge/Locks.swift +50 -0
  172. package/Sources/FoundationBridge/Markdown.swift +527 -0
  173. package/Sources/FoundationBridge/MeasurementFormat.swift +95 -0
  174. package/Sources/FoundationBridge/NotificationCenter.swift +154 -0
  175. package/Sources/FoundationBridge/OpenURLHandlers.swift +60 -0
  176. package/Sources/FoundationBridge/Operation.swift +195 -0
  177. package/Sources/FoundationBridge/ProcessInfo.swift +32 -0
  178. package/Sources/FoundationBridge/RelativeDateTimeFormatter.swift +136 -0
  179. package/Sources/FoundationBridge/SceneStorage.swift +78 -0
  180. package/Sources/FoundationBridge/SecurityExports.swift +8 -0
  181. package/Sources/FoundationBridge/Selector.swift +226 -0
  182. package/Sources/FoundationBridge/StringComparators.swift +17 -0
  183. package/Sources/FoundationBridge/Table.swift +211 -0
  184. package/Sources/FoundationBridge/TextAttributes.swift +42 -0
  185. package/Sources/FoundationBridge/Timer.swift +53 -0
  186. package/Sources/FoundationBridge/UITextChecker.swift +30 -0
  187. package/Sources/FoundationBridge/URLSession.swift +718 -0
  188. package/Sources/FoundationBridge/UserDefaults.swift +183 -0
  189. package/Sources/FoundationBridge/WebAuthRedirects.swift +227 -0
  190. package/Sources/FoundationBridge/WebSocket.swift +187 -0
  191. package/Sources/FoundationModels/FoundationModels.swift +1098 -0
  192. package/Sources/ImageIO/GIF.swift +72 -0
  193. package/Sources/ImageIO/ImageIO.swift +248 -0
  194. package/Sources/ImageIO/ImageTypes.swift +28 -0
  195. package/Sources/LinkPresentation/LinkPresentation.swift +249 -0
  196. package/Sources/LocalAuthentication/LAContext.swift +86 -0
  197. package/Sources/MapKit/Geometry.swift +223 -0
  198. package/Sources/MapKit/Map.swift +638 -0
  199. package/Sources/MapKit/MapView.swift +229 -0
  200. package/Sources/MobileCoreServices/MobileCoreServices.swift +28 -0
  201. package/Sources/NaturalLanguage/LanguageIdentifier.swift +317 -0
  202. package/Sources/NaturalLanguage/NaturalLanguage.swift +135 -0
  203. package/Sources/OSLog/OSLog.swift +6 -0
  204. package/Sources/Photos/Photos.swift +572 -0
  205. package/Sources/PhotosUI/PhotosPicker.swift +248 -0
  206. package/Sources/PhotosUI/PhotosPickerItem.swift +261 -0
  207. package/Sources/QuickLook/QuickLook.swift +168 -0
  208. package/Sources/SafariServices/SafariServices.swift +106 -0
  209. package/Sources/Security/Security.swift +332 -0
  210. package/Sources/StoreKit/AppStore.swift +207 -0
  211. package/Sources/StoreKit/Products.swift +280 -0
  212. package/Sources/StoreKit/RequestReview.swift +28 -0
  213. package/Sources/StoreKit/StoreKit1.swift +486 -0
  214. package/Sources/StoreKit/StoreViews.swift +428 -0
  215. package/Sources/StoreKit/Transactions.swift +197 -0
  216. package/Sources/SwiftData/Macros.swift +58 -0
  217. package/Sources/SwiftData/ModelActor.swift +38 -0
  218. package/Sources/SwiftData/ModelContainer.swift +129 -0
  219. package/Sources/SwiftData/ModelContext.swift +451 -0
  220. package/Sources/SwiftData/PersistentModel.swift +238 -0
  221. package/Sources/SwiftData/Properties.swift +261 -0
  222. package/Sources/SwiftData/Query.swift +256 -0
  223. package/Sources/SwiftData/Schema.swift +192 -0
  224. package/Sources/SwiftData/Store.swift +146 -0
  225. package/Sources/SwiftData/StringPredicates.swift +125 -0
  226. package/Sources/SwiftDataMacros/EntryMacro.swift +82 -0
  227. package/Sources/SwiftDataMacros/GenerableMacro.swift +183 -0
  228. package/Sources/SwiftDataMacros/ModelActorMacro.swift +46 -0
  229. package/Sources/SwiftDataMacros/ModelMacro.swift +260 -0
  230. package/Sources/SwiftDataMacros/Plugin.swift +18 -0
  231. package/Sources/SwiftDataMacros/PredicateMacro.swift +1244 -0
  232. package/Sources/SwiftUI/API/Accessibility.swift +181 -0
  233. package/Sources/SwiftUI/API/AccessibilityExtras.swift +33 -0
  234. package/Sources/SwiftUI/API/AccessibilityFocus.swift +63 -0
  235. package/Sources/SwiftUI/API/Alert.swift +221 -0
  236. package/Sources/SwiftUI/API/AlignmentGuides.swift +65 -0
  237. package/Sources/SwiftUI/API/Animation.swift +285 -0
  238. package/Sources/SwiftUI/API/App.swift +87 -0
  239. package/Sources/SwiftUI/API/BindingCollections.swift +35 -0
  240. package/Sources/SwiftUI/API/BindingForEach.swift +27 -0
  241. package/Sources/SwiftUI/API/Bitmaps.swift +254 -0
  242. package/Sources/SwiftUI/API/ButtonStyles.swift +96 -0
  243. package/Sources/SwiftUI/API/Canvas.swift +337 -0
  244. package/Sources/SwiftUI/API/Color.swift +237 -0
  245. package/Sources/SwiftUI/API/ColorEffects.swift +52 -0
  246. package/Sources/SwiftUI/API/ColorPickerAndLabeledContent.swift +138 -0
  247. package/Sources/SwiftUI/API/ColorSpaces.swift +161 -0
  248. package/Sources/SwiftUI/API/Commands.swift +106 -0
  249. package/Sources/SwiftUI/API/ContainerBackground.swift +28 -0
  250. package/Sources/SwiftUI/API/ContentShape.swift +33 -0
  251. package/Sources/SwiftUI/API/ContentSizeCategory.swift +35 -0
  252. package/Sources/SwiftUI/API/ContentUnavailable.swift +101 -0
  253. package/Sources/SwiftUI/API/Controls.swift +300 -0
  254. package/Sources/SwiftUI/API/CustomLayout.swift +442 -0
  255. package/Sources/SwiftUI/API/CustomToolbarContent.swift +46 -0
  256. package/Sources/SwiftUI/API/Decorations.swift +92 -0
  257. package/Sources/SwiftUI/API/EditMode.swift +212 -0
  258. package/Sources/SwiftUI/API/Effects.swift +388 -0
  259. package/Sources/SwiftUI/API/Entry.swift +8 -0
  260. package/Sources/SwiftUI/API/Environment.swift +439 -0
  261. package/Sources/SwiftUI/API/EnvironmentSendable.swift +6 -0
  262. package/Sources/SwiftUI/API/Focus.swift +137 -0
  263. package/Sources/SwiftUI/API/Font.swift +131 -0
  264. package/Sources/SwiftUI/API/Gauge.swift +290 -0
  265. package/Sources/SwiftUI/API/Geometry.swift +89 -0
  266. package/Sources/SwiftUI/API/GeometryEffects.swift +232 -0
  267. package/Sources/SwiftUI/API/GeometryReader.swift +135 -0
  268. package/Sources/SwiftUI/API/GestureState.swift +65 -0
  269. package/Sources/SwiftUI/API/Gestures.swift +342 -0
  270. package/Sources/SwiftUI/API/Glass.swift +127 -0
  271. package/Sources/SwiftUI/API/Grid.swift +188 -0
  272. package/Sources/SwiftUI/API/GroupBoxAndControlGroup.swift +130 -0
  273. package/Sources/SwiftUI/API/KeyPress.swift +54 -0
  274. package/Sources/SwiftUI/API/LabelStyle.swift +124 -0
  275. package/Sources/SwiftUI/API/Layout.swift +220 -0
  276. package/Sources/SwiftUI/API/LazyStacks.swift +49 -0
  277. package/Sources/SwiftUI/API/LegacyAlert.swift +97 -0
  278. package/Sources/SwiftUI/API/Lists.swift +331 -0
  279. package/Sources/SwiftUI/API/Menu.swift +58 -0
  280. package/Sources/SwiftUI/API/Modifiers.swift +313 -0
  281. package/Sources/SwiftUI/API/MoreModifiers.swift +100 -0
  282. package/Sources/SwiftUI/API/Namespace.swift +44 -0
  283. package/Sources/SwiftUI/API/Navigation.swift +386 -0
  284. package/Sources/SwiftUI/API/NavigationDestinationBindings.swift +55 -0
  285. package/Sources/SwiftUI/API/ObservableObject.swift +293 -0
  286. package/Sources/SwiftUI/API/OnChange.swift +48 -0
  287. package/Sources/SwiftUI/API/Path.swift +543 -0
  288. package/Sources/SwiftUI/API/Phase8Controls.swift +411 -0
  289. package/Sources/SwiftUI/API/PhaseAnimator.swift +130 -0
  290. package/Sources/SwiftUI/API/Picker.swift +185 -0
  291. package/Sources/SwiftUI/API/PointerAndKeyboard.swift +77 -0
  292. package/Sources/SwiftUI/API/Popover.swift +41 -0
  293. package/Sources/SwiftUI/API/Preferences.swift +262 -0
  294. package/Sources/SwiftUI/API/Presentation.swift +122 -0
  295. package/Sources/SwiftUI/API/PresentationExtras.swift +60 -0
  296. package/Sources/SwiftUI/API/Primitives.swift +517 -0
  297. package/Sources/SwiftUI/API/Publishers.swift +107 -0
  298. package/Sources/SwiftUI/API/Redaction.swift +75 -0
  299. package/Sources/SwiftUI/API/RowActions.swift +84 -0
  300. package/Sources/SwiftUI/API/Scenes.swift +131 -0
  301. package/Sources/SwiftUI/API/ScrollModifiers.swift +132 -0
  302. package/Sources/SwiftUI/API/ScrollTargets.swift +104 -0
  303. package/Sources/SwiftUI/API/ScrollViewReader.swift +144 -0
  304. package/Sources/SwiftUI/API/SectionSupplements.swift +96 -0
  305. package/Sources/SwiftUI/API/Shape.swift +214 -0
  306. package/Sources/SwiftUI/API/ShapeStyle.swift +409 -0
  307. package/Sources/SwiftUI/API/ShapeTrim.swift +78 -0
  308. package/Sources/SwiftUI/API/Sharing.swift +193 -0
  309. package/Sources/SwiftUI/API/StackLayouts.swift +199 -0
  310. package/Sources/SwiftUI/API/State.swift +144 -0
  311. package/Sources/SwiftUI/API/StatusGaps.swift +121 -0
  312. package/Sources/SwiftUI/API/StrokeStyle.swift +30 -0
  313. package/Sources/SwiftUI/API/SymbolEffects.swift +203 -0
  314. package/Sources/SwiftUI/API/TabContent.swift +841 -0
  315. package/Sources/SwiftUI/API/Table.swift +382 -0
  316. package/Sources/SwiftUI/API/Tabs.swift +263 -0
  317. package/Sources/SwiftUI/API/Tasks.swift +35 -0
  318. package/Sources/SwiftUI/API/Text.swift +386 -0
  319. package/Sources/SwiftUI/API/TextDates.swift +61 -0
  320. package/Sources/SwiftUI/API/TextDecorations.swift +52 -0
  321. package/Sources/SwiftUI/API/TextFieldAxis.swift +103 -0
  322. package/Sources/SwiftUI/API/TextFieldCommit.swift +52 -0
  323. package/Sources/SwiftUI/API/Timeline.swift +212 -0
  324. package/Sources/SwiftUI/API/Toolbar.swift +251 -0
  325. package/Sources/SwiftUI/API/Transfer.swift +145 -0
  326. package/Sources/SwiftUI/API/UnevenRoundedRectangle.swift +66 -0
  327. package/Sources/SwiftUI/API/Video.swift +64 -0
  328. package/Sources/SwiftUI/API/View.swift +215 -0
  329. package/Sources/SwiftUI/API/ViewModifier.swift +43 -0
  330. package/Sources/SwiftUI/API/VisualEffect.swift +155 -0
  331. package/Sources/SwiftUI/API/Windows.swift +25 -0
  332. package/Sources/SwiftUI/Charts/Axis.swift +325 -0
  333. package/Sources/SwiftUI/Charts/AxisFormatsAndRanges.swift +68 -0
  334. package/Sources/SwiftUI/Charts/Chart.swift +660 -0
  335. package/Sources/SwiftUI/Charts/ChartContent.swift +376 -0
  336. package/Sources/SwiftUI/Charts/ChartProxy.swift +57 -0
  337. package/Sources/SwiftUI/Charts/Marks.swift +204 -0
  338. package/Sources/SwiftUI/Charts/Plottable.swift +99 -0
  339. package/Sources/SwiftUI/Charts/Scales.swift +326 -0
  340. package/Sources/SwiftUI/Localization/Localization.swift +498 -0
  341. package/Sources/SwiftUI/Localization/PluralRules.swift +127 -0
  342. package/Sources/SwiftUI/Runtime/Executor.swift +85 -0
  343. package/Sources/SwiftUI/Runtime/Exports.swift +101 -0
  344. package/Sources/SwiftUI/Runtime/ImageSource.swift +310 -0
  345. package/Sources/SwiftUI/Runtime/JSON.swift +143 -0
  346. package/Sources/SwiftUI/Runtime/JSONParser.swift +443 -0
  347. package/Sources/SwiftUI/Runtime/LazyRows.swift +99 -0
  348. package/Sources/SwiftUI/Runtime/Measurements.swift +140 -0
  349. package/Sources/SwiftUI/Runtime/Ops.swift +152 -0
  350. package/Sources/SwiftUI/Runtime/Reconciler.swift +219 -0
  351. package/Sources/SwiftUI/Runtime/Replay.swift +382 -0
  352. package/Sources/SwiftUI/Runtime/Runtime.swift +2146 -0
  353. package/Sources/SwiftUI/Runtime/Sameness.swift +152 -0
  354. package/Sources/SwiftUI/Runtime/ViewPath.swift +89 -0
  355. package/Sources/SwiftUI/Runtime/ViewTraits.swift +175 -0
  356. package/Sources/SwiftUI/Runtime/WebAuthHeadless.swift +49 -0
  357. package/Sources/Symbols/Symbols.swift +25 -0
  358. package/Sources/Translation/Translation.swift +423 -0
  359. package/Sources/UIKit/Activity.swift +213 -0
  360. package/Sources/UIKit/Alerts.swift +69 -0
  361. package/Sources/UIKit/AppDelegate.swift +222 -0
  362. package/Sources/UIKit/Appearance.swift +84 -0
  363. package/Sources/UIKit/ColorConversions.swift +70 -0
  364. package/Sources/UIKit/Controls.swift +225 -0
  365. package/Sources/UIKit/Device.swift +200 -0
  366. package/Sources/UIKit/Feedback.swift +65 -0
  367. package/Sources/UIKit/Font.swift +307 -0
  368. package/Sources/UIKit/Graphics.swift +204 -0
  369. package/Sources/UIKit/HostingController.swift +185 -0
  370. package/Sources/UIKit/Identity.swift +24 -0
  371. package/Sources/UIKit/Introspectable.swift +510 -0
  372. package/Sources/UIKit/Pasteboard.swift +363 -0
  373. package/Sources/UIKit/PhotoAlbum.swift +81 -0
  374. package/Sources/UIKit/RemoteNotifications.swift +15 -0
  375. package/Sources/UIKit/Representable.swift +288 -0
  376. package/Sources/UIKit/SafeArea.swift +12 -0
  377. package/Sources/UIKit/SceneDelegates.swift +132 -0
  378. package/Sources/UIKit/Scenes.swift +40 -0
  379. package/Sources/UIKit/ScrollView.swift +157 -0
  380. package/Sources/UIKit/ShortcutItems.swift +67 -0
  381. package/Sources/UIKit/SymbolConfiguration.swift +124 -0
  382. package/Sources/UIKit/TargetAction.swift +123 -0
  383. package/Sources/UIKit/TextPaste.swift +161 -0
  384. package/Sources/UIKit/TextView.swift +538 -0
  385. package/Sources/UIKit/UIKit.swift +292 -0
  386. package/Sources/UIKit/UIView.swift +855 -0
  387. package/Sources/UIKit/ViewTranslation.swift +311 -0
  388. package/Sources/UniformTypeIdentifiers/UTType.swift +196 -0
  389. package/Sources/UserNotifications/Content.swift +370 -0
  390. package/Sources/UserNotifications/NotificationCenter.swift +309 -0
  391. package/Sources/WeatherKit/WeatherKit.swift +228 -0
  392. package/Sources/WebKit/WebKit.swift +245 -0
  393. package/Sources/os/os.swift +376 -0
  394. package/Sources/zlib/zlib.swift +6 -0
  395. package/index.d.ts +2 -0
  396. package/index.mjs +16 -0
  397. package/manifest.d.mts +2 -0
  398. package/manifest.mjs +39 -0
  399. package/package.json +30 -4
  400. package/sync-sources.mjs +33 -0
@@ -0,0 +1,1244 @@
1
+ // Vendored from swift-foundation (Sources/FoundationMacros/PredicateMacro.swift,
2
+ // tag swift-6.4.x-DEVELOPMENT-SNAPSHOT-2026-09-26-a), Apache License v2.0 with
3
+ // Runtime Library Exception; see https://swift.org/LICENSE.txt.
4
+ //
5
+ // SwiftBrowser's changes, so that `#Predicate` accepts what it does on Apple
6
+ // platforms: `localizedStandardContains`, `localizedCompare` and
7
+ // `caseInsensitiveCompare` are listed as supported functions (the open-source
8
+ // build lists them only for Apple's Foundation, `FOUNDATION_FRAMEWORK`, whose
9
+ // expressions corelibs Foundation lacks), and their `build_` functions are
10
+ // SwiftData's (Sources/SwiftData/StringPredicates.swift). Apps that import SwiftData
11
+ // get this macro in place of Foundation's through a declaration the CLI
12
+ // generates in the app module (docs/ops-protocol.md, "Phase 18").
13
+
14
+
15
+ import SwiftSyntax
16
+ import SwiftSyntaxMacros
17
+ import SwiftDiagnostics
18
+ import SwiftSyntaxBuilder
19
+
20
+ // A list of all functions supported by Predicate/Expression itself, any other functions called will be diagnosed as an error
21
+ // This allows for checking the function name, the number of arguments, and the argument labels, but the types of the arguments will need to be validated by the post-expansion type checking pass
22
+ // The closure specification is used to determine whether keypaths should be transformed/expanded into closures and whether dropping the final argument in favor of a trailing closure is allowed
23
+ private let _knownSupportedFunctions: Set<FunctionStructure> = [
24
+ FunctionStructure("contains", arguments: [.unlabeled]),
25
+ FunctionStructure("contains", arguments: [.closure(labeled: "where")]),
26
+ FunctionStructure("allSatisfy", arguments: [.closure(labeled: nil)]),
27
+ FunctionStructure("flatMap", arguments: [.closure(labeled: nil)]),
28
+ FunctionStructure("filter", arguments: [.closure(labeled: nil)]),
29
+ FunctionStructure("subscript", arguments: [.unlabeled]),
30
+ FunctionStructure("subscript", arguments: [.unlabeled, "default"]),
31
+ FunctionStructure("starts", arguments: ["with"]),
32
+ FunctionStructure("min", arguments: []),
33
+ FunctionStructure("max", arguments: []),
34
+ ]
35
+
36
+ private var knownSupportedFunctions: Set<FunctionStructure> {
37
+ var result = _knownSupportedFunctions
38
+ result.insert(FunctionStructure("localizedStandardContains", arguments: [.unlabeled]))
39
+ result.insert(FunctionStructure("localizedCompare", arguments: [.unlabeled]))
40
+ result.insert(FunctionStructure("caseInsensitiveCompare", arguments: [.unlabeled]))
41
+ return result
42
+ }
43
+
44
+ /// The functions whose `build_` SwiftData supplies (Sources/SwiftData/StringPredicates.swift).
45
+ private let swiftDataFunctions: Set<String> = ["localizedStandardContains", "localizedCompare", "caseInsensitiveCompare"]
46
+
47
+ private let _supportedFunctionSuggestions: [FunctionStructure : FunctionStructure] = [
48
+ FunctionStructure("hasPrefix", arguments: [.unlabeled]) : FunctionStructure("starts", arguments: ["with"]),
49
+ ]
50
+
51
+ private var supportedFunctionSuggestions: [FunctionStructure : FunctionStructure] {
52
+ var result = _supportedFunctionSuggestions
53
+ result[FunctionStructure("localizedCaseInsensitiveContains", arguments: [.unlabeled])] = FunctionStructure("localizedStandardContains", arguments: [.unlabeled])
54
+ result[FunctionStructure("localizedCaseInsensitiveCompare", arguments: [.unlabeled])] = FunctionStructure("localizedCompare", arguments: [.unlabeled])
55
+ result[FunctionStructure("localizedStandardCompare", arguments: [.unlabeled])] = FunctionStructure("localizedCompare", arguments: [.unlabeled])
56
+ return result
57
+ }
58
+
59
+ extension Array where Element == FunctionStructure.Argument {
60
+ fileprivate func argumentsEqual(_ other: Self) -> Bool {
61
+ let currentPackIndex = self.firstIndex { $0.kind == .pack }
62
+ let otherPackIndex = other.firstIndex { $0.kind == .pack }
63
+
64
+ var full: [FunctionStructure.Argument]
65
+ var prefix: ArraySlice<FunctionStructure.Argument>
66
+ var suffix: ArraySlice<FunctionStructure.Argument>
67
+ switch (currentPackIndex, otherPackIndex) {
68
+ // If neither contains a pack or both contain a pack, just compare arguments as-is
69
+ case (nil, nil), (.some(_), .some(_)):
70
+ return self == other
71
+
72
+ // If one of them contains a pack, compare the prefix and suffix to allow the pack to lazily consume multiple arguments
73
+ case (let .some(idx), nil):
74
+ full = other
75
+ prefix = self[..<idx]
76
+ suffix = self[self.index(after: idx)...]
77
+ case (nil, let .some(idx)):
78
+ full = self
79
+ prefix = other[..<idx]
80
+ suffix = other[other.index(after: idx)...]
81
+ }
82
+ return full.starts(with: prefix) && full.reversed().starts(with: suffix.reversed())
83
+ }
84
+
85
+ fileprivate func expandingPackToMatchCount(_ otherCount: Int) -> Self {
86
+ let countDifference = otherCount - self.count
87
+ guard countDifference >= 0, let packIdx = self.firstIndex(where: { $0.kind == .pack }) else {
88
+ return self
89
+ }
90
+
91
+ var copy = self
92
+ copy[packIdx] = .init(label: copy[packIdx].label, kind: .standard)
93
+ if countDifference > 0 {
94
+ copy.insert(contentsOf: Array(repeating: .unlabeled, count: countDifference), at: packIdx + 1)
95
+ }
96
+ return copy
97
+ }
98
+ }
99
+
100
+ private struct FunctionStructure: Hashable {
101
+ struct Argument : Hashable, ExpressibleByStringLiteral {
102
+ enum Kind : Hashable {
103
+ case standard
104
+ case closure
105
+ case pack
106
+ }
107
+
108
+ let label: String?
109
+ let kind: Kind
110
+
111
+ init(stringLiteral: String) {
112
+ label = stringLiteral
113
+ kind = .standard
114
+ }
115
+
116
+ init(label: String?, kind: Kind) {
117
+ self.label = label
118
+ self.kind = kind
119
+ }
120
+
121
+ static func closure(labeled label: String?) -> Self {
122
+ Self(label: label, kind: .closure)
123
+ }
124
+
125
+ static var unlabeled: Self {
126
+ Self(label: nil, kind: .standard)
127
+ }
128
+
129
+ static func pack(labeled label: String?) -> Self {
130
+ Self(label: label, kind: .pack)
131
+ }
132
+
133
+ static func ==(lhs: Self, rhs: Self) -> Bool {
134
+ lhs.label == rhs.label
135
+ }
136
+ }
137
+ let name: String
138
+ let arguments: [Argument]
139
+ let hasTrailingClosure: Bool
140
+
141
+ var supportsTrailingClosure: Bool {
142
+ hasTrailingClosure || arguments.last?.kind == .closure
143
+ }
144
+
145
+ var signature: String {
146
+ let args = arguments.map { ($0.label ?? "_") + ":" }.joined()
147
+ return "\(name)(\(args))"
148
+ }
149
+
150
+ init(_ name: String, arguments: [Argument], trailingClosure: Bool = false) {
151
+ self.name = name
152
+ self.arguments = arguments
153
+ self.hasTrailingClosure = trailingClosure
154
+ }
155
+
156
+ func matches(_ other: FunctionStructure) -> Bool {
157
+ guard self.name == other.name else { return false }
158
+
159
+ switch (self.hasTrailingClosure, other.hasTrailingClosure) {
160
+ case (true, true), (false, false):
161
+ return self.arguments.argumentsEqual(other.arguments)
162
+ case (true, false):
163
+ guard let otherLast = other.arguments.last else { return false }
164
+ return self.arguments.argumentsEqual(other.arguments.dropLast()) && otherLast.kind == .closure
165
+ case (false, true):
166
+ guard let last = self.arguments.last else { return false }
167
+ return self.arguments.dropLast().argumentsEqual(other.arguments) && last.kind == .closure
168
+ }
169
+ }
170
+
171
+ func fixItChanges(transformingFrom source: FunctionCallExprSyntax) -> [FixIt.Change]? {
172
+ let sourceHasTrailingClosure = source.trailingClosure != nil
173
+ if sourceHasTrailingClosure {
174
+ guard supportsTrailingClosure else { return nil }
175
+ }
176
+ let sourceArgumentTotalCount = source.arguments.count + (sourceHasTrailingClosure ? 1 : 0)
177
+ let argumentTotalCount = self.arguments.count + (hasTrailingClosure ? 1 : 0)
178
+ guard argumentTotalCount == sourceArgumentTotalCount,
179
+ let calledExpr = source.calledExpression.as(MemberAccessExprSyntax.self) else {
180
+ return nil
181
+ }
182
+ var newFunctionCall = source
183
+ newFunctionCall.calledExpression = ExprSyntax(calledExpr.with(\.declName, DeclReferenceExprSyntax(baseName: .identifier(name))))
184
+ newFunctionCall.arguments = LabeledExprListSyntax(zip(source.arguments, arguments).map {
185
+ if let newLabel = $1.label {
186
+ return $0.with(\.label, .identifier(newLabel)).with(\.colon, .colonToken()).with(\.expression, $0.expression.with(\.leadingTrivia, [.spaces(1)]))
187
+ } else {
188
+ return $0.with(\.label, nil).with(\.colon, nil).with(\.trailingTrivia, []).with(\.expression, $0.expression.with(\.leadingTrivia, []))
189
+ }
190
+ })
191
+ newFunctionCall.leadingTrivia = []
192
+ newFunctionCall.trailingTrivia = []
193
+ if self.hasTrailingClosure && source.trailingClosure == nil, let newTrailingClosure = source.arguments.last?.expression.as(ClosureExprSyntax.self) {
194
+ newFunctionCall.trailingClosure = newTrailingClosure
195
+ }
196
+ return [.replace(oldNode: Syntax(source), newNode: Syntax(newFunctionCall))]
197
+ }
198
+ }
199
+
200
+ private func _knownMatchingFunction(_ structure: FunctionStructure) -> FunctionStructure? {
201
+ knownSupportedFunctions.first {
202
+ $0.matches(structure)
203
+ }
204
+ }
205
+
206
+ private func _suggestionForUnknownFunction(_ structure: FunctionStructure) -> FunctionStructure? {
207
+ guard let key = supportedFunctionSuggestions.keys.first(where: { $0.matches(structure) }) else {
208
+ return nil
209
+ }
210
+ return supportedFunctionSuggestions[key]
211
+ }
212
+
213
+ private class ShorthandArgumentIdentifierDetector: SyntaxVisitor {
214
+ var found = false
215
+
216
+ override func visit(_ node: DeclReferenceExprSyntax) -> SyntaxVisitorContinueKind {
217
+ // Look for identifiers such as $0, $1, etc.
218
+ if case let .dollarIdentifier(identifier) = node.baseName.tokenKind, identifier.dropFirst().allSatisfy(\.isNumber) {
219
+ found = true
220
+ return .skipChildren
221
+ } else {
222
+ return .visitChildren
223
+ }
224
+ }
225
+ }
226
+
227
+ extension SyntaxProtocol {
228
+ var containsShorthandArgumentIdentifiers: Bool {
229
+ let visitor = ShorthandArgumentIdentifierDetector(viewMode: .all)
230
+ visitor.walk(self)
231
+ return visitor.found
232
+ }
233
+ }
234
+
235
+ private protocol PredicateSyntaxRewriter : SyntaxRewriter {
236
+ var success: Bool { get }
237
+ var ignorable: Bool { get }
238
+ var diagnostics: [Diagnostic] { get }
239
+ }
240
+
241
+ extension PredicateSyntaxRewriter {
242
+ var success: Bool { true }
243
+ var ignorable: Bool { false }
244
+ var diagnostics: [Diagnostic] { [] }
245
+ }
246
+
247
+ extension SyntaxProtocol {
248
+ fileprivate func rewrite(with rewriter: some PredicateSyntaxRewriter) throws -> Syntax {
249
+ let translated = rewriter.rewrite(self)
250
+ guard rewriter.success else {
251
+ throw DiagnosticsError(diagnostics: rewriter.diagnostics)
252
+ }
253
+ guard !rewriter.ignorable else {
254
+ return Syntax(self)
255
+ }
256
+ return translated
257
+ }
258
+ }
259
+
260
+ private class OptionalChainRewriter: SyntaxRewriter, PredicateSyntaxRewriter {
261
+ var withinValidChainingTreeStart = true
262
+ var withinChainingTree = false
263
+ var optionalInput: ExprSyntax? = nil
264
+ var ignorable = true
265
+
266
+ private func _prePossibleTopOfTree() -> Bool {
267
+ if !withinChainingTree && withinValidChainingTreeStart {
268
+ withinChainingTree = true
269
+ return true
270
+ }
271
+ return false
272
+ }
273
+
274
+ private func _postTopOfTree(_ node: ExprSyntax) -> ExprSyntax {
275
+ assert(withinChainingTree)
276
+ withinChainingTree = false
277
+ if let input = optionalInput {
278
+ optionalInput = nil
279
+ ignorable = false
280
+ let visited = self.visit(input)
281
+ let closure = ClosureExprSyntax(statements: [CodeBlockItemSyntax(item: CodeBlockItemSyntax.Item(node))])
282
+ let functionMember = MemberAccessExprSyntax(base: visited, name: "flatMap")
283
+ let functionCall = FunctionCallExprSyntax(calledExpression: functionMember, leftParen: .leftParenToken(), arguments: [], rightParen: .rightParenToken(), trailingClosure: closure)
284
+ return ExprSyntax(functionCall)
285
+ }
286
+ return node
287
+ }
288
+
289
+ override func visit(_ node: ClosureExprSyntax) -> ExprSyntax {
290
+ guard withinChainingTree else {
291
+ // If we're not already in a chaining tree, just keep progressing with our current rewriter
292
+ return super.visit(node)
293
+ }
294
+
295
+ // We're in the middle of a potential tree, so rewrite the closure with a fresh state
296
+ // This ensures potential chaining in the closure isn't rewritten outside of the closure
297
+ let nestedRewriter = OptionalChainRewriter()
298
+ guard let rewritten = (try? node.rewrite(with: nestedRewriter))?.as(ExprSyntax.self) else {
299
+ // If rewriting the closure failed, just leave the closure as-is
300
+ return ExprSyntax(node)
301
+ }
302
+ if ignorable {
303
+ ignorable = nestedRewriter.ignorable
304
+ }
305
+ return rewritten
306
+ }
307
+
308
+ override func visit(_ node: FunctionCallExprSyntax) -> ExprSyntax {
309
+ let priorValidTreeStart = withinValidChainingTreeStart
310
+ defer { withinValidChainingTreeStart = priorValidTreeStart }
311
+
312
+ if node.arguments.containsShorthandArgumentIdentifiers {
313
+ withinValidChainingTreeStart = false
314
+ }
315
+
316
+ let topOfTree = _prePossibleTopOfTree()
317
+ let visited = super.visit(node)
318
+ if topOfTree {
319
+ return _postTopOfTree(visited)
320
+ } else {
321
+ return visited
322
+ }
323
+ }
324
+
325
+ override func visit(_ node: MemberAccessExprSyntax) -> ExprSyntax {
326
+ let topOfTree = _prePossibleTopOfTree()
327
+ let visited = super.visit(node)
328
+ if topOfTree {
329
+ return _postTopOfTree(visited)
330
+ } else {
331
+ return visited
332
+ }
333
+ }
334
+
335
+ override func visit(_ node: OptionalChainingExprSyntax) -> ExprSyntax {
336
+ guard withinChainingTree else {
337
+ return super.visit(node)
338
+ }
339
+ // Capture the optional input, and replace it in the output expression with a "$0"
340
+ optionalInput = node.expression
341
+ return .init(DeclReferenceExprSyntax(baseName: .dollarIdentifier("$0")))
342
+ }
343
+ }
344
+
345
+ extension CodeBlockItemListSyntax.Element.Item {
346
+ fileprivate var _expression: ExprSyntax? {
347
+ switch self {
348
+ case .expr(let expr): return expr
349
+ case .stmt(let stmt): return stmt.as(ExpressionStmtSyntax.self)?.expression
350
+ default: return nil
351
+ }
352
+ }
353
+ }
354
+
355
+ extension ConditionElementListSyntax {
356
+ fileprivate var optionalBindings: [OptionalBindingConditionSyntax]? {
357
+ var result = [OptionalBindingConditionSyntax]()
358
+ for element in self {
359
+ switch element.condition {
360
+ case let .optionalBinding(binding):
361
+ result.append(binding)
362
+ default:
363
+ return nil
364
+ }
365
+ }
366
+ return result
367
+ }
368
+ }
369
+
370
+ extension ClosureParameterListSyntax {
371
+ fileprivate var withVariableWrappedTypes: Self {
372
+ return Self(self.map {
373
+ if let type = $0.type {
374
+ $0.with(\.type, "PredicateExpressions.\(raw: moduleName())::Variable<\(type)>")
375
+ } else {
376
+ $0
377
+ }
378
+ })
379
+ }
380
+ }
381
+
382
+ extension KeyPathExprSyntax {
383
+ private enum KeyPathDirectExpressionRewritingError : Error {
384
+ case unknownKeypathComponentType
385
+ }
386
+
387
+ fileprivate func asDirectExpression(on base: some ExprSyntaxProtocol) -> ExprSyntax? {
388
+ var result = ExprSyntax(base)
389
+ for item in components {
390
+ switch item.component {
391
+ case .property(let prop):
392
+ result = ExprSyntax(MemberAccessExprSyntax(base: result, declName: prop.declName))
393
+ case .optional(let opt):
394
+ if opt.questionOrExclamationMark.tokenKind == .exclamationMark {
395
+ result = ExprSyntax(ForceUnwrapExprSyntax(expression: result))
396
+ } else {
397
+ result = ExprSyntax(OptionalChainingExprSyntax(expression: result))
398
+ }
399
+ case .subscript(let sub):
400
+ result = ExprSyntax(SubscriptCallExprSyntax(calledExpression: result, arguments: sub.arguments))
401
+ @unknown default:
402
+ return nil
403
+ }
404
+ }
405
+ return result
406
+ }
407
+ }
408
+
409
+ private class PredicateQueryRewriter: SyntaxRewriter, PredicateSyntaxRewriter {
410
+ private let indentWidth: Trivia = .spaces(4)
411
+ private var indentLevel = 0
412
+ private var indent: Trivia {
413
+ Trivia(pieces: Array(repeating: .spaces(4), count: indentLevel))
414
+ }
415
+ var validOptionalChainingTree = true
416
+ var diagnostics: [Diagnostic] = []
417
+ var success: Bool { diagnostics.isEmpty }
418
+ let kind: ExpansionKind
419
+
420
+ init(kind: ExpansionKind) {
421
+ self.kind = kind
422
+ }
423
+
424
+ private func diagnose(node: SyntaxProtocol, message: PredicateExpansionDiagnostic, fixIts: [FixIt] = []) {
425
+ diagnostics.append(.init(node: Syntax(node), message: message, fixIts: fixIts))
426
+ }
427
+
428
+ private func makeArgument(label: String?, _ expression: ExprSyntax, shouldVisit: Bool = true, shouldIndent: Bool = true) -> LabeledExprSyntax {
429
+ if shouldIndent {
430
+ indentLevel += 1
431
+ }
432
+ defer {
433
+ if shouldIndent {
434
+ indentLevel -= 1
435
+ }
436
+ }
437
+
438
+ let labelSyntax = label.map {
439
+ TokenSyntax(.identifier($0), presence: .present)
440
+ }?.with(\.leadingTrivia, indent)
441
+
442
+ let colonSyntax = label.map { _ in
443
+ TokenSyntax(.colon, presence: .present)
444
+ }
445
+
446
+ var argument = shouldVisit ? visit(expression) : expression
447
+
448
+ if shouldVisit && argument == expression {
449
+ argument = "PredicateExpressions.\(raw: moduleName())::build_Arg(\(expression.with(\.leadingTrivia, []).with(\.trailingTrivia, [])))"
450
+ }
451
+
452
+ argument = argument.with(\.leadingTrivia, label == nil ? indent : .space)
453
+ return .init(label: labelSyntax,
454
+ colon: colonSyntax,
455
+ expression: argument,
456
+ trailingComma: nil)
457
+ }
458
+
459
+ override func visit(_ node: PrefixOperatorExprSyntax) -> ExprSyntax {
460
+ switch node.operator.text {
461
+ case "!":
462
+ let syntax: ExprSyntax =
463
+ """
464
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_Negation(
465
+ \(makeArgument(label: nil, node.expression))
466
+ \(raw: indent))
467
+ """
468
+
469
+ return syntax
470
+ case "-":
471
+ let syntax: ExprSyntax =
472
+ """
473
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_UnaryMinus(
474
+ \(makeArgument(label: nil, node.expression))
475
+ \(raw: indent))
476
+ """
477
+
478
+ return syntax
479
+ default:
480
+ diagnose(node: node.operator, message: "The '\(node.operator.text)' operator is not supported in this \(kind.keyword)")
481
+ return ExprSyntax(node)
482
+ }
483
+ }
484
+
485
+ override func visit(_ node: InfixOperatorExprSyntax) -> ExprSyntax {
486
+ let lhsOp = node.leftOperand
487
+ let rhsOp = node.rightOperand
488
+ let opExpr = node.operator
489
+
490
+ guard let opSyntax = opExpr.as(BinaryOperatorExprSyntax.self) else {
491
+ diagnose(node: opExpr, message: "The '\(opExpr.description)' operator is not supported in this \(kind.keyword)")
492
+ return ExprSyntax(node)
493
+ }
494
+
495
+ let (lhsLabel, rhsLabel) = switch opSyntax.operator.text {
496
+ case "...", "..<": ("lower", "upper")
497
+ default: ("lhs", "rhs")
498
+ }
499
+
500
+ let lhsArgument = makeArgument(label: lhsLabel, lhsOp).with(\.trailingTrivia, [])
501
+ let rhsArgument = makeArgument(label: rhsLabel, rhsOp).with(\.trailingTrivia, [])
502
+
503
+ switch (opSyntax.operator.text) {
504
+ case "==":
505
+ let syntax: ExprSyntax =
506
+ """
507
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_Equal(
508
+ \(lhsArgument),
509
+ \(rhsArgument)
510
+ \(raw: indent))
511
+ """
512
+
513
+ return syntax
514
+ case "!=":
515
+ let syntax: ExprSyntax =
516
+ """
517
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_NotEqual(
518
+ \(lhsArgument),
519
+ \(rhsArgument)
520
+ \(raw: indent))
521
+ """
522
+
523
+ return syntax
524
+ case "<":
525
+ let syntax: ExprSyntax =
526
+ """
527
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_Comparison(
528
+ \(lhsArgument),
529
+ \(rhsArgument),
530
+ \(raw: indent + indentWidth)op: .lessThan
531
+ \(raw: indent))
532
+ """
533
+
534
+ return syntax
535
+ case "<=":
536
+ let syntax: ExprSyntax =
537
+ """
538
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_Comparison(
539
+ \(lhsArgument),
540
+ \(rhsArgument),
541
+ \(raw: indent + indentWidth)op: .lessThanOrEqual
542
+ \(raw: indent))
543
+ """
544
+
545
+ return syntax
546
+ case ">":
547
+ let syntax: ExprSyntax =
548
+ """
549
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_Comparison(
550
+ \(lhsArgument),
551
+ \(rhsArgument),
552
+ \(raw: indent + indentWidth)op: .greaterThan
553
+ \(raw: indent))
554
+ """
555
+
556
+ return syntax
557
+ case ">=":
558
+ let syntax: ExprSyntax =
559
+ """
560
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_Comparison(
561
+ \(lhsArgument),
562
+ \(rhsArgument),
563
+ \(raw: indent + indentWidth)op: .greaterThanOrEqual
564
+ \(raw: indent))
565
+ """
566
+
567
+ return syntax
568
+ case "||":
569
+ let syntax: ExprSyntax =
570
+ """
571
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_Disjunction(
572
+ \(lhsArgument),
573
+ \(rhsArgument)
574
+ \(raw: indent))
575
+ """
576
+
577
+ return syntax
578
+ case "&&":
579
+ let syntax: ExprSyntax =
580
+ """
581
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_Conjunction(
582
+ \(lhsArgument),
583
+ \(rhsArgument)
584
+ \(raw: indent))
585
+ """
586
+
587
+ return syntax
588
+ case "+":
589
+ let syntax: ExprSyntax =
590
+ """
591
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_Arithmetic(
592
+ \(lhsArgument),
593
+ \(rhsArgument),
594
+ \(raw: indent + indentWidth)op: .add
595
+ \(raw: indent))
596
+ """
597
+
598
+ return syntax
599
+ case "-":
600
+ let syntax: ExprSyntax =
601
+ """
602
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_Arithmetic(
603
+ \(lhsArgument),
604
+ \(rhsArgument),
605
+ \(raw: indent + indentWidth)op: .subtract
606
+ \(raw: indent))
607
+ """
608
+
609
+ return syntax
610
+ case "*":
611
+ let syntax: ExprSyntax =
612
+ """
613
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_Arithmetic(
614
+ \(lhsArgument),
615
+ \(rhsArgument),
616
+ \(raw: indent + indentWidth)op: .multiply
617
+ \(raw: indent))
618
+ """
619
+
620
+ return syntax
621
+ case "/":
622
+ let syntax: ExprSyntax =
623
+ """
624
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_Division(
625
+ \(lhsArgument),
626
+ \(rhsArgument)
627
+ \(raw: indent))
628
+ """
629
+
630
+ return syntax
631
+ case "%":
632
+ let syntax: ExprSyntax =
633
+ """
634
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_Remainder(
635
+ \(lhsArgument),
636
+ \(rhsArgument)
637
+ \(raw: indent))
638
+ """
639
+
640
+ return syntax
641
+ case "??":
642
+ let syntax: ExprSyntax =
643
+ """
644
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_NilCoalesce(
645
+ \(lhsArgument),
646
+ \(rhsArgument)
647
+ \(raw: indent))
648
+ """
649
+
650
+ return syntax
651
+
652
+ case "...":
653
+ let syntax: ExprSyntax =
654
+ """
655
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_ClosedRange(
656
+ \(lhsArgument),
657
+ \(rhsArgument)
658
+ \(raw: indent))
659
+ """
660
+
661
+ return syntax
662
+
663
+ case "..<":
664
+ let syntax: ExprSyntax =
665
+ """
666
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_Range(
667
+ \(lhsArgument),
668
+ \(rhsArgument)
669
+ \(raw: indent))
670
+ """
671
+
672
+ return syntax
673
+ default:
674
+ diagnose(node: opSyntax, message: "The '\(opSyntax.operator.text)' operator is not supported in this \(kind.keyword)")
675
+ return ExprSyntax(node)
676
+ }
677
+ }
678
+
679
+ // We only hit this if our OptionalChainingRewriter was unable to rewrite them out of the expression tree
680
+ override func visit(_ node: OptionalChainingExprSyntax) -> ExprSyntax {
681
+ diagnose(node: node.questionMark, message: "Optional chaining is not supported here in this \(kind.keyword). Use the flatMap(_:) function explicitly instead.")
682
+ return .init(node)
683
+ }
684
+
685
+ override func visit(_ node: ForceUnwrapExprSyntax) -> ExprSyntax {
686
+ return """
687
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_ForcedUnwrap(
688
+ \(makeArgument(label: nil, node.expression))
689
+ \(raw: indent))
690
+ """
691
+ }
692
+
693
+ override func visit(_ node: NilLiteralExprSyntax) -> ExprSyntax {
694
+ "PredicateExpressions.\(raw: moduleName())::build_NilLiteral()"
695
+ }
696
+
697
+ override func visit(_ node: MemberAccessExprSyntax) -> ExprSyntax {
698
+ guard let base = node.base else {
699
+ diagnose(node: node, message: "Member access without an explicit base is not supported in this \(kind.keyword)")
700
+ return .init(node)
701
+ }
702
+
703
+ let newPropertyComponent = KeyPathPropertyComponentSyntax(declName: node.declName)
704
+ let keyPath = KeyPathExprSyntax(components: [.init(period: TokenSyntax.periodToken(), component: .property(newPropertyComponent))])
705
+ return """
706
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_KeyPath(
707
+ \(makeArgument(label: "root", base)),
708
+ \(makeArgument(label: "keyPath", .init(keyPath), shouldVisit: false).with(\.trailingTrivia, []))
709
+ \(raw: indent))
710
+ """
711
+ }
712
+
713
+ override func visit(_ node: FunctionCallExprSyntax) -> ExprSyntax {
714
+ let memberAccess = node.calledExpression.as(MemberAccessExprSyntax.self)
715
+ let base = memberAccess?.base
716
+ let funcName = memberAccess?.declName.baseName.with(\.leadingTrivia, []).with(\.trailingTrivia, []).text ?? node.calledExpression.as(DeclReferenceExprSyntax.self)!.baseName.text
717
+ return _processFunction(
718
+ base: base,
719
+ functionName: funcName,
720
+ argumentList: node.arguments,
721
+ trailingClosure: node.trailingClosure,
722
+ diagnosticPoint: .init(memberAccess?.declName) ?? .init(node),
723
+ functionCallExpr: node)
724
+ ?? .init(node)
725
+ }
726
+
727
+ override func visit(_ node: SubscriptCallExprSyntax) -> ExprSyntax {
728
+ return _processFunction(
729
+ base: node.calledExpression,
730
+ functionName: "subscript",
731
+ argumentList: node.arguments,
732
+ trailingClosure: node.trailingClosure,
733
+ diagnosticPoint: .init(node.leftSquare))
734
+ ?? .init(node)
735
+ }
736
+
737
+ private func _processFunction(base: ExprSyntax?, functionName: String, argumentList: LabeledExprListSyntax, trailingClosure: ClosureExprSyntax?, diagnosticPoint: Syntax, functionCallExpr: FunctionCallExprSyntax? = nil) -> ExprSyntax? {
738
+ // The provided base is nil when calling global functions functions
739
+ guard let base else {
740
+ diagnose(node: diagnosticPoint, message: "Global functions are not supported in this \(kind.keyword)")
741
+ return nil
742
+ }
743
+
744
+ // Check this function against our known list to provide rich diagnostics for functions we know we don't support
745
+ let name = TokenSyntax(.identifier(functionName), presence: .present).with(\.leadingTrivia, []).with(\.trailingTrivia, [])
746
+ let args = argumentList.map {
747
+ let isClosure = $0.expression.is(ClosureExprSyntax.self) || $0.expression.is(KeyPathExprSyntax.self)
748
+ return FunctionStructure.Argument(label: $0.label?.text, kind: isClosure ? .closure : .standard)
749
+ }
750
+ let structure = FunctionStructure(name.text, arguments: args, trailingClosure: trailingClosure != nil)
751
+ guard let knownFunc = _knownMatchingFunction(structure) else {
752
+ let diagnostic = PredicateExpansionDiagnostic("The \(structure.signature) function is not supported in this \(kind.keyword)")
753
+ var fixIts = [FixIt]()
754
+ if let functionCallExpr,
755
+ let suggestion = _suggestionForUnknownFunction(structure),
756
+ let changes = suggestion.fixItChanges(transformingFrom: functionCallExpr) {
757
+ fixIts.append(FixIt(message: PredicateExpansionDiagnostic("Use \(suggestion.signature)", severity: .note), changes: changes))
758
+ }
759
+ diagnose(node: diagnosticPoint, message: diagnostic, fixIts: fixIts)
760
+ return nil
761
+ }
762
+
763
+ var arguments: [LabeledExprSyntax] = []
764
+ func addArgument(_ argument: ExprSyntax, label: String?, withComma: Bool) {
765
+ arguments.append(
766
+ makeArgument(label: label, argument)
767
+ .with(\.trailingComma, withComma ? TokenSyntax(.comma, presence: .present) : nil)
768
+ .with(\.trailingTrivia, withComma ? .newline : [])
769
+ )
770
+ }
771
+
772
+ // Function arguments can contain dollar sign identifiers that can't be nested inside of a new closure
773
+ // Prevent this function call from being placed inside of a flatMap due to optionalChaining
774
+ let oldValidOptionalChainingTree = validOptionalChainingTree
775
+ validOptionalChainingTree = false
776
+ addArgument(base, label: nil, withComma: !argumentList.isEmpty)
777
+ validOptionalChainingTree = oldValidOptionalChainingTree
778
+
779
+ for (sourceArg, knownArgStructure) in zip(argumentList, knownFunc.arguments.expandingPackToMatchCount(argumentList.count)) {
780
+ var expression = sourceArg.expression
781
+ if knownArgStructure.kind == .closure, let kpExpr = sourceArg.expression.as(KeyPathExprSyntax.self) {
782
+ guard !kpExpr.containsShorthandArgumentIdentifiers,
783
+ let memberAccess = kpExpr.asDirectExpression(on: DeclReferenceExprSyntax(baseName: .dollarIdentifier("$0"))),
784
+ let preparedMemberAccess = try? memberAccess.rewrite(with: OptionalChainRewriter()) else {
785
+ diagnose(node: kpExpr, message: "This key path is not supported here in this \(kind.keyword). Use an explicit closure instead.")
786
+ return nil
787
+ }
788
+ expression = ExprSyntax(ClosureExprSyntax(statements: [CodeBlockItemSyntax(item: .expr(preparedMemberAccess.as(ExprSyntax.self)!))]))
789
+ }
790
+ addArgument(expression, label: sourceArg.label?.text, withComma: sourceArg.trailingComma != nil)
791
+ }
792
+
793
+ // SwiftData's builders are found without a module selector.
794
+ let buildModule = swiftDataFunctions.contains(name.text) ? "" : "\(moduleName())::"
795
+ if let closure = trailingClosure {
796
+ // Don't indent, because closures already get indented
797
+ let closureArg = makeArgument(label: nil, ExprSyntax(closure), shouldIndent: false)
798
+ return """
799
+ \(raw: indent)PredicateExpressions.\(raw: buildModule)build_\(name.with(\.leadingTrivia, []).with(\.trailingTrivia, []))(
800
+ \(LabeledExprListSyntax(arguments))
801
+ \(raw: indent))\(raw: Trivia.space)\(closureArg.with(\.leadingTrivia, []).with(\.trailingTrivia, []))
802
+ """
803
+ } else {
804
+ return """
805
+ \(raw: indent)PredicateExpressions.\(raw: buildModule)build_\(name.with(\.leadingTrivia, []).with(\.trailingTrivia, []))(
806
+ \(LabeledExprListSyntax(arguments))
807
+ \(raw: indent))
808
+ """
809
+ }
810
+ }
811
+
812
+ override func visit(_ node: TupleExprSyntax) -> ExprSyntax {
813
+ guard node.elements.count == 1, let element = node.elements.first else {
814
+ diagnose(node: node, message: "Tuples are not supported in this \(kind.keyword)")
815
+ return ExprSyntax(node)
816
+ }
817
+
818
+ // Support expressions like "(input as? Bool) == true" where parantheses used for grouping are treated like a single element tuple expression
819
+ return visit(element.expression)
820
+ }
821
+
822
+ // Processes a code block and guarantees that the returned code block only contains one item
823
+ func _processCodeBlock(_ statements: CodeBlockItemListSyntax, in node: Syntax, removeReturn: Bool = false) -> CodeBlockItemListSyntax? {
824
+ guard statements.count == 1 else {
825
+ diagnose(node: statements.isEmpty ? node : statements[statements.index(after: statements.startIndex)], message: "\(kind.capitalizedKeyword) body may only contain one expression")
826
+ return nil
827
+ }
828
+
829
+ indentLevel += 1
830
+ var body = visit(statements)
831
+ if success && body == statements {
832
+ let wrapped: ExprSyntax =
833
+ """
834
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_Arg(
835
+ \(raw: indent + indentWidth)\(body.with(\.leadingTrivia, []).with(\.trailingTrivia, []))
836
+ \(raw: indent))
837
+ """
838
+ body = [.init(item: .expr(wrapped))]
839
+ }
840
+ indentLevel -= 1
841
+
842
+ if removeReturn, let first = body.first, case .stmt(let statement) = first.item, let returnStmt = statement.as(ReturnStmtSyntax.self), let returnExpr = returnStmt.expression {
843
+ body = [.init(item: .expr(returnExpr.with(\.leadingTrivia, returnStmt.leadingTrivia)))]
844
+ }
845
+ return body
846
+ }
847
+
848
+ override func visit(_ node: CodeBlockSyntax) -> CodeBlockSyntax {
849
+ guard let body = _processCodeBlock(node.statements, in: .init(node)) else {
850
+ return node
851
+ }
852
+ return node.with(\.statements, body)
853
+ }
854
+
855
+ override func visit(_ node: ClosureExprSyntax) -> ExprSyntax {
856
+ guard let body = _processCodeBlock(node.statements, in: .init(node)) else {
857
+ return .init(node)
858
+ }
859
+
860
+ var resultingSignature = node.signature
861
+ if let signature = node.signature {
862
+ var visited = signature
863
+ visited.returnClause = nil
864
+ if case .parameterClause(let paramClause) = signature.parameterClause {
865
+ let newParamClause = paramClause.with(\.parameters, paramClause.parameters.withVariableWrappedTypes)
866
+ visited.parameterClause = .parameterClause(newParamClause)
867
+ }
868
+ resultingSignature = visited
869
+ }
870
+
871
+ return ExprSyntax(
872
+ node
873
+ .with(\.statements, body)
874
+ .with(\.leftBrace, node.leftBrace.with(\.trailingTrivia, node.signature == nil ? .newline : .space))
875
+ .with(\.signature, resultingSignature?.with(\.trailingTrivia, .newline))
876
+ .with(\.rightBrace, node.rightBrace.with(\.leadingTrivia, .newline + indent))
877
+ )
878
+ }
879
+
880
+ override func visit(_ node: TernaryExprSyntax) -> ExprSyntax {
881
+ let condition = node.condition
882
+ let firstChoice = node.thenExpression
883
+ let secondChoice = node.elseExpression
884
+
885
+ return """
886
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_Conditional(
887
+ \(makeArgument(label: nil, condition).with(\.trailingTrivia, [])),
888
+ \(makeArgument(label: nil, firstChoice).with(\.trailingTrivia, [])),
889
+ \(makeArgument(label: nil, secondChoice).with(\.trailingTrivia, []))
890
+ \(raw: indent))
891
+ """
892
+ }
893
+
894
+ override func visit(_ node: IsExprSyntax) -> ExprSyntax {
895
+ return """
896
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::TypeCheck<_, \(node.type)>(
897
+ \(makeArgument(label: nil, node.expression).with(\.trailingTrivia, []))
898
+ \(raw: indent))
899
+ """
900
+ }
901
+
902
+ override func visit(_ node: AsExprSyntax) -> ExprSyntax {
903
+ let castType: String
904
+ switch node.questionOrExclamationMark?.tokenKind {
905
+ case .none: fallthrough
906
+ case .some(.exclamationMark):
907
+ castType = "Force"
908
+ case .some(.postfixQuestionMark):
909
+ castType = "Conditional"
910
+ default:
911
+ fatalError("Unexpected question/exclamation mark token kind")
912
+ }
913
+
914
+ return """
915
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::\(raw: castType)Cast<_, \(node.type)>(
916
+ \(makeArgument(label: nil, node.expression).with(\.trailingTrivia, []))
917
+ \(raw: indent))
918
+ """
919
+ }
920
+
921
+ override func visit(_ node: ReturnStmtSyntax) -> StmtSyntax {
922
+ guard let expression = node.expression else {
923
+ // No expansion needed when returning Void
924
+ return StmtSyntax(node)
925
+ }
926
+
927
+ let visited = visit(expression)
928
+ guard visited == expression else {
929
+ // No expansion needed when returning transformed expression
930
+ return StmtSyntax(node.with(\.expression, visited.with(\.leadingTrivia, [])).with(\.leadingTrivia, indent))
931
+ }
932
+
933
+ // Wrap constant return expressions in a build_Arg call
934
+ let wrapped: ExprSyntax =
935
+ """
936
+ PredicateExpressions.\(raw: moduleName())::build_Arg(
937
+ \(visited.with(\.leadingTrivia, indent + indentWidth))
938
+ \(raw: indent))
939
+ """
940
+ return StmtSyntax(node.with(\.expression, wrapped).with(\.leadingTrivia, indent))
941
+ }
942
+
943
+ override func visit(_ node: SwitchExprSyntax) -> ExprSyntax {
944
+ self.diagnose(node: node, message: "Switch expressions are not supported in this \(kind.keyword)")
945
+ return .init(node)
946
+ }
947
+
948
+ private func _rewriteConditionsAsExpression<C: BidirectionalCollection<ConditionElementListSyntax.Element>>(_ collection: C, in expr: IfExprSyntax) -> ExprSyntax? {
949
+ guard let last = collection.last else {
950
+ self.diagnose(node: expr, message: "This list of conditionals is unsupported in this \(kind.keyword)")
951
+ return nil
952
+ }
953
+ guard case .expression(let lastExpr) = last.condition else {
954
+ let type: String
955
+ switch last.condition {
956
+ case .availability(_):
957
+ type = "Availability conditions"
958
+ case .matchingPattern(_):
959
+ type = "Matching pattern conditions"
960
+ case .optionalBinding(_):
961
+ self.diagnose(node: last, message: "Mixing optional bindings with other conditions is not supported in this \(kind.keyword)")
962
+ return nil
963
+ default:
964
+ type = "These types of conditions"
965
+ }
966
+ self.diagnose(node: last, message: "\(type) are not supported in this \(kind.keyword)")
967
+ return nil
968
+ }
969
+ let rest = collection.dropLast()
970
+ if rest.isEmpty {
971
+ return lastExpr
972
+ } else {
973
+ guard let restRewritten = _rewriteConditionsAsExpression(rest, in: expr) else {
974
+ return nil
975
+ }
976
+ return .init(InfixOperatorExprSyntax(leftOperand: restRewritten, operator: BinaryOperatorExprSyntax(operator: .binaryOperator("&&")), rightOperand: lastExpr))
977
+ }
978
+ }
979
+
980
+ private func _rewriteIfAsFlatMap(bindings: [OptionalBindingConditionSyntax], body: ExprSyntax, else: ExprSyntax) -> ExprSyntax? {
981
+ indentLevel += bindings.count
982
+
983
+ var prior: ExprSyntax = body
984
+ for binding in bindings.reversed() {
985
+ guard let identifier = binding.pattern.as(IdentifierPatternSyntax.self)?.identifier else {
986
+ self.diagnose(node: binding.pattern, message: "This optional binding condition is not supported in this \(kind.keyword)")
987
+ return nil
988
+ }
989
+ let initializer = binding.initializer?.value ?? ExprSyntax(DeclReferenceExprSyntax(baseName: identifier))
990
+
991
+ prior = """
992
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_flatMap(
993
+ \(makeArgument(label: nil, initializer).with(\.trailingTrivia, []))
994
+ \(raw: indent)) { \(identifier.with(\.trailingTrivia, []).with(\.leadingTrivia, [])) in
995
+ \(makeArgument(label: nil, prior, shouldVisit: false).with(\.trailingTrivia, []))
996
+ \(raw: indent)}
997
+ """
998
+ indentLevel -= 1
999
+ }
1000
+
1001
+ return """
1002
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_NilCoalesce(
1003
+ \(makeArgument(label: "lhs", prior, shouldVisit: false)),
1004
+ \(makeArgument(label: "rhs", `else`, shouldVisit: false))
1005
+ \(raw: indent))
1006
+ """
1007
+ }
1008
+
1009
+ private func _processIfBody(_ node: IfExprSyntax) -> ExprSyntax? {
1010
+ guard let visitedBody = _processCodeBlock(node.body.statements, in: .init(node.body), removeReturn: true) else {
1011
+ return nil
1012
+ }
1013
+
1014
+ guard let bodyExpression = visitedBody.first?.item._expression else {
1015
+ self.diagnose(node: node.body, message: "This if expression body is not supported in this \(kind.keyword)")
1016
+ return nil
1017
+ }
1018
+
1019
+ return bodyExpression
1020
+ }
1021
+
1022
+ private func _processElseBody(_ node: IfExprSyntax) -> ExprSyntax? {
1023
+ guard let elseBody = node.elseBody else {
1024
+ self.diagnose(node: node, message: "If expressions without an else expression are not supported in this \(kind.keyword)")
1025
+ return nil
1026
+ }
1027
+
1028
+ let elseExpression: ExprSyntax
1029
+ switch elseBody {
1030
+ case .codeBlock(let codeBlock):
1031
+ guard let visitedElseBody = _processCodeBlock(codeBlock.statements, in: .init(codeBlock), removeReturn: true) else {
1032
+ return nil
1033
+ }
1034
+ guard let expr = visitedElseBody.first?.item._expression else {
1035
+ self.diagnose(node: node.body, message: "This if expression else body is not supported in this \(kind.keyword)")
1036
+ return nil
1037
+ }
1038
+ elseExpression = expr
1039
+ case .ifExpr(let ifExpr):
1040
+ elseExpression = visit(ifExpr)
1041
+ #if FOUNDATION_FRAMEWORK
1042
+ @unknown default:
1043
+ self.diagnose(node: elseBody, message: "This if expression else body is not supported in this \(kind.keyword)")
1044
+ return nil
1045
+ #endif
1046
+ }
1047
+
1048
+ return elseExpression
1049
+ }
1050
+
1051
+ override func visit(_ node: IfExprSyntax) -> ExprSyntax {
1052
+ if let bindings = node.conditions.optionalBindings {
1053
+ indentLevel += bindings.count
1054
+ guard let bodyExpression = _processIfBody(node) else {
1055
+ return .init(node)
1056
+ }
1057
+ indentLevel -= bindings.count
1058
+ guard let elseExpression = _processElseBody(node) else {
1059
+ return .init(node)
1060
+ }
1061
+ return _rewriteIfAsFlatMap(bindings: bindings, body: bodyExpression, else: elseExpression) ?? .init(node)
1062
+ }
1063
+
1064
+ guard let ifExpression = _rewriteConditionsAsExpression(node.conditions, in: node),
1065
+ let bodyExpression = _processIfBody(node),
1066
+ let elseExpression = _processElseBody(node) else {
1067
+ return .init(node)
1068
+ }
1069
+
1070
+ return """
1071
+ \(raw: indent)PredicateExpressions.\(raw: moduleName())::build_Conditional(
1072
+ \(makeArgument(label: nil, ifExpression).with(\.trailingTrivia, [])),
1073
+ \(makeArgument(label: nil, bodyExpression, shouldVisit: false).with(\.trailingTrivia, [])),
1074
+ \(makeArgument(label: nil, elseExpression, shouldVisit: false).with(\.trailingTrivia, []))
1075
+ \(raw: indent))
1076
+ """
1077
+ }
1078
+
1079
+ override func visit(_ node: WhileStmtSyntax) -> StmtSyntax {
1080
+ self.diagnose(node: node, message: "While loops are not supported in this \(kind.keyword)")
1081
+ return .init(node)
1082
+ }
1083
+
1084
+ override func visit(_ node: ForStmtSyntax) -> StmtSyntax {
1085
+ self.diagnose(node: node, message: "For-in loops are not supported in this \(kind.keyword)")
1086
+ return .init(node)
1087
+ }
1088
+
1089
+ override func visit(_ node: DoStmtSyntax) -> StmtSyntax {
1090
+ self.diagnose(node: node, message: "Do statements are not supported in this \(kind.keyword)")
1091
+ return .init(node)
1092
+ }
1093
+
1094
+ override func visit(_ node: CatchClauseSyntax) -> CatchClauseSyntax {
1095
+ self.diagnose(node: node, message: "Catch clauses are not supported in this \(kind.keyword)")
1096
+ return node
1097
+ }
1098
+
1099
+ override func visit(_ node: RepeatStmtSyntax) -> StmtSyntax {
1100
+ self.diagnose(node: node, message: "Repeat-while loops are not supported in this \(kind.keyword)")
1101
+ return .init(node)
1102
+ }
1103
+
1104
+ override func visit(_ node: CodeBlockItemSyntax) -> CodeBlockItemSyntax {
1105
+ // At this point, we know we're the only item in the code block because predicates only support single-expression code blocks
1106
+
1107
+ // Diagnose any declarations
1108
+ if case .decl(_) = node.item {
1109
+ diagnose(node: node.item, message: "Declarations are not supported in this \(kind.keyword)")
1110
+ return node
1111
+ }
1112
+
1113
+ if case let .stmt(statement) = node.item {
1114
+ // Unwrap a do statement with valid expression bodies
1115
+ if let doStatement = statement.as(DoStmtSyntax.self) {
1116
+ if let catchClause = doStatement.catchClauses.first {
1117
+ diagnose(node: catchClause, message: "Catch clauses are not supported in this \(kind.keyword)")
1118
+ return node
1119
+ }
1120
+ indentLevel -= 1
1121
+ let visitedBody = self.visit(doStatement.body)
1122
+ indentLevel += 1
1123
+ guard success else {
1124
+ return node
1125
+ }
1126
+ guard let innerExpr = visitedBody.statements.first else {
1127
+ diagnose(node: doStatement, message: "Do statement is not supported here in this \(kind.keyword)")
1128
+ return node
1129
+ }
1130
+ return innerExpr
1131
+ }
1132
+ }
1133
+
1134
+ return super.visit(node)
1135
+ }
1136
+ }
1137
+
1138
+ private struct PredicateExpansionDiagnostic: DiagnosticMessage, FixItMessage, ExpressibleByStringLiteral, ExpressibleByStringInterpolation {
1139
+ let message: String
1140
+ let severity: DiagnosticSeverity
1141
+ let diagnosticID: MessageID = .init(domain: "FoundationMacros", id: "PredicateDiagnostic")
1142
+ var fixItID: MessageID { diagnosticID }
1143
+
1144
+ init(_ message: String, severity: DiagnosticSeverity = .error) {
1145
+ self.message = message
1146
+ self.severity = severity
1147
+ }
1148
+
1149
+ init(stringLiteral value: String) {
1150
+ self.init(value)
1151
+ }
1152
+ }
1153
+
1154
+ private func moduleName(internationalization: Bool = false) -> String {
1155
+ #if FOUNDATION_FRAMEWORK
1156
+ "Foundation"
1157
+ #else
1158
+ internationalization ? "FoundationInternationalization" : "FoundationEssentials"
1159
+ #endif
1160
+ }
1161
+
1162
+ private enum ExpansionKind {
1163
+ case predicate
1164
+ case expression
1165
+
1166
+ var keyword: String {
1167
+ switch self {
1168
+ case .predicate:
1169
+ "predicate"
1170
+ case .expression:
1171
+ "expression"
1172
+ }
1173
+ }
1174
+
1175
+ var capitalizedKeyword: String {
1176
+ let keyword = self.keyword
1177
+ let first = keyword.first!.uppercased()
1178
+ return "\(first)\(keyword.dropFirst())"
1179
+ }
1180
+
1181
+ var macroKeyword: String {
1182
+ "#\(capitalizedKeyword)"
1183
+ }
1184
+
1185
+ var qualifiedExpansionType: String {
1186
+ "\(moduleName()).\(capitalizedKeyword)"
1187
+ }
1188
+ }
1189
+
1190
+ private func predicateExpansion(of node: some FreestandingMacroExpansionSyntax, in context: some MacroExpansionContext, kind: ExpansionKind) throws -> ExprSyntax {
1191
+ guard let closure = node.trailingClosure else {
1192
+ let fixIts: [FixIt]
1193
+ if let argument = node.arguments.first?.expression.as(ClosureExprSyntax.self) {
1194
+ var newNode = node.with(\.leftParen, nil)
1195
+ .with(\.rightParen, nil)
1196
+ .with(\.trailingClosure, argument.with(\.leadingTrivia, [.spaces(1)]).with(\.trailingTrivia, []))
1197
+ newNode.arguments = []
1198
+ fixIts = [
1199
+ FixIt(message: PredicateExpansionDiagnostic("Use a trailing closure instead of a function parameter", severity: .note), changes: [
1200
+ .replace(oldNode: Syntax(node), newNode: Syntax(newNode))
1201
+ ])
1202
+ ]
1203
+ } else {
1204
+ fixIts = []
1205
+ }
1206
+ throw DiagnosticsError(diagnostics: [.init(
1207
+ node: Syntax(node),
1208
+ message: PredicateExpansionDiagnostic("\(kind.macroKeyword) macro expansion requires a trailing closure"),
1209
+ fixIts: fixIts
1210
+ )])
1211
+ }
1212
+
1213
+ let translatedClosure = try closure
1214
+ .rewrite(with: OptionalChainRewriter())
1215
+ .rewrite(with: PredicateQueryRewriter(kind: kind))
1216
+ .with(\.leadingTrivia, [])
1217
+ .with(\.trailingTrivia, [])
1218
+
1219
+ if let genericArgs = node.genericArgumentClause {
1220
+ let strippedGenericArgs = genericArgs
1221
+ .with(\.leadingTrivia, [])
1222
+ .with(\.trailingTrivia, [])
1223
+ return "\(raw: kind.qualifiedExpansionType)\(strippedGenericArgs)(\(translatedClosure))"
1224
+ } else {
1225
+ // When the macro is specified without generic args (ex. "#Predicate { ... }") initialize a Predicate without generic args so they can be inferred from context
1226
+ return "\(raw: kind.qualifiedExpansionType)(\(translatedClosure))"
1227
+ }
1228
+ }
1229
+
1230
+ public struct PredicateMacro: SwiftSyntaxMacros.ExpressionMacro, Sendable {
1231
+ public static var formatMode: FormatMode { .disabled }
1232
+
1233
+ public static func expansion(of node: some FreestandingMacroExpansionSyntax, in context: some MacroExpansionContext) throws -> ExprSyntax {
1234
+ try predicateExpansion(of: node, in: context, kind: .predicate)
1235
+ }
1236
+ }
1237
+
1238
+ public struct ExpressionMacro: SwiftSyntaxMacros.ExpressionMacro, Sendable {
1239
+ public static var formatMode: FormatMode { .disabled }
1240
+
1241
+ public static func expansion(of node: some FreestandingMacroExpansionSyntax, in context: some MacroExpansionContext) throws -> ExprSyntax {
1242
+ try predicateExpansion(of: node, in: context, kind: .expression)
1243
+ }
1244
+ }