diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 8a6d1ba63b..c1b68f040c 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -44,6 +44,7 @@ jobs: -scheme "DuckDuckGo" \ -destination "platform=iOS Simulator,name=iPhone 14,OS=16.4" -skipPackagePluginValidation \ + -skipMacroValidation \ - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/end-to-end.yml b/.github/workflows/end-to-end.yml index 5cef39c0a7..68abd594b3 100644 --- a/.github/workflows/end-to-end.yml +++ b/.github/workflows/end-to-end.yml @@ -44,6 +44,7 @@ jobs: -destination "platform=iOS Simulator,name=iPhone 15,OS=17.2" \ -derivedDataPath "DerivedData" \ -skipPackagePluginValidation \ + -skipMacroValidation \ ONLY_ACTIVE_ARCH=NO \ | tee xcodebuild.log diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index ae31bc6122..a53560b741 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -47,6 +47,7 @@ jobs: -destination "platform=iOS Simulator,name=iPhone 15,OS=17.2" \ -derivedDataPath "DerivedData" \ -skipPackagePluginValidation \ + -skipMacroValidation \ | tee xcodebuild.log \ | xcbeautify --report junit --report-path . --junit-report-filename unittests.xml @@ -89,6 +90,7 @@ jobs: -destination "platform=iOS Simulator,name=iPhone 15,OS=17.2" \ -derivedDataPath "DerivedData" \ -skipPackagePluginValidation \ + -skipMacroValidation \ | xcbeautify --report junit --report-path . --junit-report-filename unittests.xml - name: Publish unit tests report diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index bdbdb037cc..462a3fc004 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -82,6 +82,7 @@ jobs: -destination "platform=iOS Simulator,name=iPhone 15,OS=17.2" \ -derivedDataPath "DerivedData" \ -skipPackagePluginValidation \ + -skipMacroValidation \ DDG_SLOW_COMPILE_CHECK_THRESHOLD=250 \ | tee xcodebuild.log \ | xcbeautify --report junit --report-path . --junit-report-filename unittests.xml @@ -188,6 +189,7 @@ jobs: -derivedDataPath "DerivedData" \ -configuration "Release" \ -skipPackagePluginValidation \ + -skipMacroValidation \ | xcbeautify create-asana-task: diff --git a/.github/workflows/sync-end-to-end.yml b/.github/workflows/sync-end-to-end.yml index 78d7e2ad1e..af560b1dd5 100644 --- a/.github/workflows/sync-end-to-end.yml +++ b/.github/workflows/sync-end-to-end.yml @@ -44,6 +44,7 @@ jobs: -destination "platform=iOS Simulator,name=iPhone 15" \ -derivedDataPath "DerivedData" \ -skipPackagePluginValidation \ + -skipMacroValidation \ ONLY_ACTIVE_ARCH=NO \ | tee xcodebuild.log diff --git a/Core/AppURLs.swift b/Core/AppURLs.swift index e2250c3744..eff05031d3 100644 --- a/Core/AppURLs.swift +++ b/Core/AppURLs.swift @@ -17,8 +17,9 @@ // limitations under the License. // -import Foundation import BrowserServicesKit +import Foundation +import Macros public extension URL { @@ -48,7 +49,7 @@ public extension URL { static let exti = URL(string: "\(base)/exti/\(devMode)")! static let feedback = URL(string: "\(base)/feedback.js?type=app-feedback")! - static let appStore = URL(string: "https://apps.apple.com/app/duckduckgo-privacy-browser/id663592361")! + static let appStore = #URL("https://apps.apple.com/app/duckduckgo-privacy-browser/id663592361") static let mac = URL(string: "\(base)/mac")! static let windows = URL(string: "\(base)/windows")! diff --git a/Core/BookmarksImporter.swift b/Core/BookmarksImporter.swift index 177dcf2955..4615e47689 100644 --- a/Core/BookmarksImporter.swift +++ b/Core/BookmarksImporter.swift @@ -17,11 +17,12 @@ // limitations under the License. // +import Bookmarks import Common import Foundation -import SwiftSoup -import Bookmarks +import Macros import Persistence +import SwiftSoup public enum BookmarksImportError: Error { case invalidHtmlNoDLTag @@ -217,7 +218,7 @@ final public class BookmarksImporter { static let FavoritesFolder = "DuckDuckGo Favorites" static let BookmarksFolder = "DuckDuckGo Bookmarks" static let bookmarkURLString = "https://duckduckgo.com" - static let bookmarkURL = URL(string: "https://duckduckgo.com")! + static let bookmarkURL = #URL("https://duckduckgo.com") static let favoriteAttribute = "duckduckgo:favorite" static let isFavorite = "true" static let idAttribute = "id" diff --git a/Core/DataStoreWarmup.swift b/Core/DataStoreWarmup.swift index 79087b9fc2..6554f0ca8c 100644 --- a/Core/DataStoreWarmup.swift +++ b/Core/DataStoreWarmup.swift @@ -18,6 +18,7 @@ // import Combine +import Macros import WebKit /// WKWebsiteDataStore is basically non-functional until a web view has been instanciated and a page is successfully loaded. @@ -27,7 +28,7 @@ public class DataStoreWarmup { @MainActor public func ensureReady() async { - await BlockingNavigationDelegate().loadInBackgroundWebView(url: URL(string: "about:blank")!) + await BlockingNavigationDelegate().loadInBackgroundWebView(url: #URL("about:blank")) } } diff --git a/Core/UserAgentManager.swift b/Core/UserAgentManager.swift index 80db1e64a0..32f90094d2 100644 --- a/Core/UserAgentManager.swift +++ b/Core/UserAgentManager.swift @@ -19,10 +19,11 @@ // swiftlint:disable file_length -import Foundation -import WebKit import BrowserServicesKit import Common +import Foundation +import Macros +import WebKit public protocol UserAgentManager { @@ -46,7 +47,7 @@ public class DefaultUserAgentManager: UserAgentManager { private func prepareUserAgent() { let webview = WKWebView() - webview.load(URLRequest.developerInitiated(URL(string: "about:blank")!)) + webview.load(URLRequest.developerInitiated(#URL("about:blank"))) getDefaultAgent(webView: webview) { [weak self] agent in // Reference webview instance to keep it in scope and allow UA to be returned diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index ff266ce02e..2295ddf9f0 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -687,6 +687,14 @@ B652DF10287C2C1600C12A9C /* ContentBlocking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9847BFFD27A2DDB400DB07AA /* ContentBlocking.swift */; }; B652DF12287C336E00C12A9C /* ContentBlockingUpdating.swift in Sources */ = {isa = PBXBuildFile; fileRef = B652DF11287C336E00C12A9C /* ContentBlockingUpdating.swift */; }; B652DF13287C373A00C12A9C /* ScriptSourceProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = B652DEFE287BF1FE00C12A9C /* ScriptSourceProviding.swift */; }; + B6A26C042B98358B00DF9EAD /* Macros in Frameworks */ = {isa = PBXBuildFile; productRef = B6A26C032B98358B00DF9EAD /* Macros */; }; + B6A26C062B98359A00DF9EAD /* Macros in Frameworks */ = {isa = PBXBuildFile; productRef = B6A26C052B98359A00DF9EAD /* Macros */; }; + B6A26C082B9835A000DF9EAD /* Macros in Frameworks */ = {isa = PBXBuildFile; productRef = B6A26C072B9835A000DF9EAD /* Macros */; }; + B6A26C0A2B9835A800DF9EAD /* Macros in Frameworks */ = {isa = PBXBuildFile; productRef = B6A26C092B9835A800DF9EAD /* Macros */; }; + B6A26C0C2B9835AD00DF9EAD /* Macros in Frameworks */ = {isa = PBXBuildFile; productRef = B6A26C0B2B9835AD00DF9EAD /* Macros */; }; + B6A26C0E2B9835B100DF9EAD /* Macros in Frameworks */ = {isa = PBXBuildFile; productRef = B6A26C0D2B9835B100DF9EAD /* Macros */; }; + B6A26C102B9835B400DF9EAD /* Macros in Frameworks */ = {isa = PBXBuildFile; productRef = B6A26C0F2B9835B400DF9EAD /* Macros */; }; + B6A26C122B9835B800DF9EAD /* Macros in Frameworks */ = {isa = PBXBuildFile; productRef = B6A26C112B9835B800DF9EAD /* Macros */; }; B6AD9E3628D4510A0019CDE9 /* ContentBlockerRulesManagerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6AD9E3428D4510A0019CDE9 /* ContentBlockerRulesManagerMock.swift */; }; B6AD9E3728D4510A0019CDE9 /* ContentBlockingUpdatingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6AD9E3528D4510A0019CDE9 /* ContentBlockingUpdatingTests.swift */; }; B6AD9E3828D4512E0019CDE9 /* EmbeddedTrackerDataTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9801F08927E4B21100191874 /* EmbeddedTrackerDataTests.swift */; }; @@ -2697,6 +2705,7 @@ 0202569029881ECA00E694E7 /* CocoaAsyncSocket in Frameworks */, 02025664298818B200E694E7 /* NetworkExtension.framework in Frameworks */, 4B470EE4299C6DFB0086EBDC /* Core.framework in Frameworks */, + B6A26C062B98359A00DF9EAD /* Macros in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2704,6 +2713,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + B6A26C0E2B9835B100DF9EAD /* Macros in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2722,6 +2732,7 @@ 853273B624FFE0BB00E3C778 /* WidgetKit.framework in Frameworks */, 0238E44F29C0FAA100615E30 /* FindInPageIOSJSSupport in Frameworks */, 3760DFED299315EF0045A446 /* Waitlist in Frameworks */, + B6A26C042B98358B00DF9EAD /* Macros in Frameworks */, F143C2EB1E4A4CD400CFDE3A /* Core.framework in Frameworks */, 4B2754EC29E8C7DF00394032 /* Lottie in Frameworks */, 31E69A63280F4CB600478327 /* DuckUI in Frameworks */, @@ -2737,6 +2748,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + B6A26C0A2B9835A800DF9EAD /* Macros in Frameworks */, F486D3362506A037002D07D7 /* OHHTTPStubs in Frameworks */, F486D3382506A225002D07D7 /* OHHTTPStubsSwift in Frameworks */, F115ED9C2B4EFC8E001A0453 /* TestUtils in Frameworks */, @@ -2767,6 +2779,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + B6A26C102B9835B400DF9EAD /* Macros in Frameworks */, 1E1D8B632995143200C96994 /* OHHTTPStubs in Frameworks */, 1E1D8B652995143200C96994 /* OHHTTPStubsSwift in Frameworks */, ); @@ -2776,6 +2789,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + B6A26C0C2B9835AD00DF9EAD /* Macros in Frameworks */, F486D31D2506980E002D07D7 /* Swifter in Frameworks */, 85F21DC021123B03002631A6 /* Core.framework in Frameworks */, ); @@ -2786,6 +2800,7 @@ buildActionMask = 2147483647; files = ( 98D4B7DF2944DDBD0068814D /* Core.framework in Frameworks */, + B6A26C122B9835B800DF9EAD /* Macros in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2794,6 +2809,7 @@ buildActionMask = 2147483647; files = ( 4B948E2629DCCDB9002531FA /* Persistence in Frameworks */, + B6A26C082B9835A000DF9EAD /* Macros in Frameworks */, 98A50962294B48A400D10880 /* Bookmarks in Frameworks */, 1E60989B290009C700A508F9 /* Common in Frameworks */, 1E60989D290011E600A508F9 /* ContentBlocking in Frameworks */, @@ -5692,6 +5708,7 @@ name = PacketTunnelProvider; packageProductDependencies = ( 0202568F29881ECA00E694E7 /* CocoaAsyncSocket */, + B6A26C052B98359A00DF9EAD /* Macros */, ); productName = PacketTunnelProvider; productReference = 02025662298818B100E694E7 /* PacketTunnelProvider.appex */; @@ -5712,6 +5729,9 @@ 025CCFE82582601C001CD5BB /* PBXTargetDependency */, ); name = FingerprintingUITests; + packageProductDependencies = ( + B6A26C0D2B9835B100DF9EAD /* Macros */, + ); productName = FingerprintingUITests; productReference = 025CCFE22582601C001CD5BB /* FingerprintingUITests.xctest */; productType = "com.apple.product-type.bundle.ui-testing"; @@ -5771,6 +5791,7 @@ F42D541C29DCA40B004C4FF1 /* DesignResourcesKit */, 0238E44E29C0FAA100615E30 /* FindInPageIOSJSSupport */, 4B2754EB29E8C7DF00394032 /* Lottie */, + B6A26C032B98358B00DF9EAD /* Macros */, ); productName = DuckDuckGo; productReference = 84E341921E2F7EFB00BDBA6F /* DuckDuckGo.app */; @@ -5796,6 +5817,7 @@ F486D3372506A225002D07D7 /* OHHTTPStubsSwift */, EEFAB4662A73C230008A38E4 /* NetworkProtectionTestUtils */, F115ED9B2B4EFC8E001A0453 /* TestUtils */, + B6A26C092B9835A800DF9EAD /* Macros */, ); productName = DuckDuckGoTests; productReference = 84E341A61E2F7EFB00BDBA6F /* UnitTests.xctest */; @@ -5859,6 +5881,7 @@ packageProductDependencies = ( 1E1D8B622995143200C96994 /* OHHTTPStubs */, 1E1D8B642995143200C96994 /* OHHTTPStubsSwift */, + B6A26C0F2B9835B400DF9EAD /* Macros */, ); productName = IntegrationTests; productReference = 85D33FCB25C97B6E002B91A6 /* IntegrationTests.xctest */; @@ -5881,6 +5904,7 @@ name = AtbUITests; packageProductDependencies = ( F486D31C2506980E002D07D7 /* Swifter */, + B6A26C0B2B9835AD00DF9EAD /* Macros */, ); productName = AtbIntegrationTests; productReference = 85F21DAD210F5E32002631A6 /* AtbUITests.xctest */; @@ -5902,6 +5926,7 @@ ); name = PerformanceTests; packageProductDependencies = ( + B6A26C112B9835B800DF9EAD /* Macros */, ); productName = IntegrationTests; productReference = 9825F9D7293F2DE900F220F2 /* PerformanceTests.xctest */; @@ -5954,6 +5979,7 @@ EE8E56892A56BCE400F11DCA /* NetworkProtection */, D61CDA152B7CF77300A0FBB9 /* Subscription */, D61CDA172B7CF78300A0FBB9 /* ZIPFoundation */, + B6A26C072B9835A000DF9EAD /* Macros */, ); productName = Core; productReference = F143C2E41E4A4CD400CFDE3A /* Core.framework */; @@ -10019,7 +10045,7 @@ repositoryURL = "https://github.com/DuckDuckGo/BrowserServicesKit"; requirement = { kind = exactVersion; - version = 116.1.0; + version = 117.0.0; }; }; B6F997C22B8F374300476735 /* XCRemoteSwiftPackageReference "apple-toolbox" */ = { @@ -10027,7 +10053,7 @@ repositoryURL = "https://github.com/duckduckgo/apple-toolbox.git"; requirement = { kind = exactVersion; - version = 1.0.0; + version = 2.0.0; }; }; C14882EB27F211A000D59F0C /* XCRemoteSwiftPackageReference "SwiftSoup" */ = { @@ -10178,6 +10204,46 @@ package = 98A16C2928A11BDE00A6C003 /* XCRemoteSwiftPackageReference "BrowserServicesKit" */; productName = Bookmarks; }; + B6A26C032B98358B00DF9EAD /* Macros */ = { + isa = XCSwiftPackageProductDependency; + package = B6F997C22B8F374300476735 /* XCRemoteSwiftPackageReference "apple-toolbox" */; + productName = Macros; + }; + B6A26C052B98359A00DF9EAD /* Macros */ = { + isa = XCSwiftPackageProductDependency; + package = B6F997C22B8F374300476735 /* XCRemoteSwiftPackageReference "apple-toolbox" */; + productName = Macros; + }; + B6A26C072B9835A000DF9EAD /* Macros */ = { + isa = XCSwiftPackageProductDependency; + package = B6F997C22B8F374300476735 /* XCRemoteSwiftPackageReference "apple-toolbox" */; + productName = Macros; + }; + B6A26C092B9835A800DF9EAD /* Macros */ = { + isa = XCSwiftPackageProductDependency; + package = B6F997C22B8F374300476735 /* XCRemoteSwiftPackageReference "apple-toolbox" */; + productName = Macros; + }; + B6A26C0B2B9835AD00DF9EAD /* Macros */ = { + isa = XCSwiftPackageProductDependency; + package = B6F997C22B8F374300476735 /* XCRemoteSwiftPackageReference "apple-toolbox" */; + productName = Macros; + }; + B6A26C0D2B9835B100DF9EAD /* Macros */ = { + isa = XCSwiftPackageProductDependency; + package = B6F997C22B8F374300476735 /* XCRemoteSwiftPackageReference "apple-toolbox" */; + productName = Macros; + }; + B6A26C0F2B9835B400DF9EAD /* Macros */ = { + isa = XCSwiftPackageProductDependency; + package = B6F997C22B8F374300476735 /* XCRemoteSwiftPackageReference "apple-toolbox" */; + productName = Macros; + }; + B6A26C112B9835B800DF9EAD /* Macros */ = { + isa = XCSwiftPackageProductDependency; + package = B6F997C22B8F374300476735 /* XCRemoteSwiftPackageReference "apple-toolbox" */; + productName = Macros; + }; B6F997CB2B8F380A00476735 /* SwiftLintPlugin */ = { isa = XCSwiftPackageProductDependency; package = B6F997C22B8F374300476735 /* XCRemoteSwiftPackageReference "apple-toolbox" */; diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index d017bc495e..a17cb5bc7a 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -5,8 +5,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/apple-toolbox.git", "state" : { - "revision" : "e3dc4faf70ca09718a2d20d5c47b449389e8c153", - "version" : "1.0.0" + "revision" : "d51beaf1736013b530576ace13a16d6d1a63742c", + "version" : "2.0.0" } }, { @@ -23,8 +23,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/DuckDuckGo/BrowserServicesKit", "state" : { - "revision" : "9bafa0271688bae67ab9c1ba97d5e69f80fe71df", - "version" : "116.1.0" + "revision" : "dbe75fa0ee9e3b740d520d5be7967e2c5239dfb5", + "version" : "117.0.0" } }, { @@ -135,6 +135,15 @@ "version" : "1.3.0" } }, + { + "identity" : "swift-syntax", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-syntax.git", + "state" : { + "revision" : "64889f0c732f210a935a0ad7cda38f77f876262d", + "version" : "509.1.1" + } + }, { "identity" : "swifter", "kind" : "remoteSourceControl", diff --git a/DuckDuckGo/AdAttribution/AdAttributionFetcher.swift b/DuckDuckGo/AdAttribution/AdAttributionFetcher.swift index a9d3d31a80..6193491b4f 100644 --- a/DuckDuckGo/AdAttribution/AdAttributionFetcher.swift +++ b/DuckDuckGo/AdAttribution/AdAttributionFetcher.swift @@ -19,6 +19,7 @@ import AdServices import Common +import Macros protocol AdAttributionFetcher { func fetch() async -> AdServicesAttributionResponse? @@ -116,7 +117,7 @@ struct DefaultAdAttributionFetcher: AdAttributionFetcher { } private struct Constant { - static let attributionServiceURL = URL(string: "https://api-adservices.apple.com/api/v1/")! + static let attributionServiceURL = #URL("https://api-adservices.apple.com/api/v1/") static let maxRetries = 3 } } diff --git a/DuckDuckGo/AutofillLoginDetailsViewModel.swift b/DuckDuckGo/AutofillLoginDetailsViewModel.swift index 2c7ec10da8..5aacbeea91 100644 --- a/DuckDuckGo/AutofillLoginDetailsViewModel.swift +++ b/DuckDuckGo/AutofillLoginDetailsViewModel.swift @@ -19,14 +19,15 @@ // swiftlint:disable file_length -import Foundation import BrowserServicesKit import Common -import SwiftUI import Core +import DDGSync import DesignResourcesKit +import Foundation +import Macros import SecureStorage -import DDGSync +import SwiftUI protocol AutofillLoginDetailsViewModelDelegate: AnyObject { func autofillLoginDetailsViewModelDidSave() @@ -58,7 +59,7 @@ final class AutofillLoginDetailsViewModel: ObservableObject { } enum Constants { - static let privateEmailURL = URL(string: "https://duckduckgo.com/email")! + static let privateEmailURL = #URL("https://duckduckgo.com/email") } weak var delegate: AutofillLoginDetailsViewModelDelegate? diff --git a/DuckDuckGo/DesktopDownloadViewModel.swift b/DuckDuckGo/DesktopDownloadViewModel.swift index 6d52883345..9a14e3b360 100644 --- a/DuckDuckGo/DesktopDownloadViewModel.swift +++ b/DuckDuckGo/DesktopDownloadViewModel.swift @@ -18,11 +18,12 @@ // import Foundation +import Macros import UIKit final class DesktopDownloadViewModel: ObservableObject { - static let defaultURL = URL(string: "https://duckduckgo.com/")! + static let defaultURL = #URL("https://duckduckgo.com/") static let prefix = "https://" private var platform: DesktopDownloadPlatform diff --git a/DuckDuckGo/FirewallManager.swift b/DuckDuckGo/FirewallManager.swift index 6fb8e0a029..0035b6161c 100644 --- a/DuckDuckGo/FirewallManager.swift +++ b/DuckDuckGo/FirewallManager.swift @@ -23,6 +23,7 @@ import Foundation import NetworkExtension import BrowserServicesKit import Common +import Macros public protocol FirewallDelegate: AnyObject { func statusDidChange(newStatus: NEVPNStatus) @@ -80,10 +81,10 @@ public class FirewallManager: FirewallManaging { config.requestCachePolicy = .reloadIgnoringLocalCacheData config.urlCache = nil let session = URLSession(configuration: config) - let url = URL(string: "https://bad_url") - + let url = #URL("https://bad_url") + os_log("[INFO] Calling dummy URL to force VPN", log: FirewallManager.apptpLog, type: .debug) - _ = try? await session.data(from: url!) + _ = try? await session.data(from: url) os_log("[INFO] Response from dummy URL while activating VPN", log: FirewallManager.apptpLog, type: .debug) } diff --git a/DuckDuckGo/RemoteMessageRequest.swift b/DuckDuckGo/RemoteMessageRequest.swift index 2bfcd698fa..2aa0192467 100644 --- a/DuckDuckGo/RemoteMessageRequest.swift +++ b/DuckDuckGo/RemoteMessageRequest.swift @@ -17,20 +17,20 @@ // limitations under the License. // - -import Foundation import BrowserServicesKit -import RemoteMessaging import Core +import Foundation +import Macros import Networking +import RemoteMessaging public struct RemoteMessageRequest { private var endpoint: URL { #if DEBUG - return URL(string: "https://raw.githubusercontent.com/duckduckgo/remote-messaging-config/main/samples/ios/sample1.json")! + return #URL("https://raw.githubusercontent.com/duckduckgo/remote-messaging-config/main/samples/ios/sample1.json") #else - return URL(string: "https://staticcdn.duckduckgo.com/remotemessaging/config/v1/ios-config.json")! + return #URL("https://staticcdn.duckduckgo.com/remotemessaging/config/v1/ios-config.json") #endif } diff --git a/DuckDuckGoTests/AddressDisplayHelperTests.swift b/DuckDuckGoTests/AddressDisplayHelperTests.swift index c4122c4f20..e9fae0c49e 100644 --- a/DuckDuckGoTests/AddressDisplayHelperTests.swift +++ b/DuckDuckGoTests/AddressDisplayHelperTests.swift @@ -16,7 +16,10 @@ // See the License for the specific language governing permissions and // limitations under the License. // + +import Macros import XCTest + @testable import DuckDuckGo class AddressDisplayHelperTests: XCTestCase { @@ -25,36 +28,36 @@ class AddressDisplayHelperTests: XCTestCase { func testShortURL() { - XCTAssertEqual(AddressHelper.shortURLString(URL(string: "https://www.duckduckgo.com")!), "duckduckgo.com") - XCTAssertEqual(AddressHelper.shortURLString(URL(string: "https://www.duckduckgo.com/some/path")!), "duckduckgo.com") - XCTAssertEqual(AddressHelper.shortURLString(URL(string: "https://www.subdomain.duckduckgo.com/some/path")!), "subdomain.duckduckgo.com") - XCTAssertEqual(AddressHelper.shortURLString(URL(string: "https://m.duckduckgo.com/some/path")!), "m.duckduckgo.com") - XCTAssertEqual(AddressHelper.shortURLString(URL(string: "http://some-other.sub.domain.duck.eu/with/path")!), "some-other.sub.domain.duck.eu") - XCTAssertEqual(AddressHelper.shortURLString(URL(string: "http://duckduckgo.com:1234")!), "duckduckgo.com") - XCTAssertEqual(AddressHelper.shortURLString(URL(string: "https://192.168.0.1:1234")!), "192.168.0.1") + XCTAssertEqual(AddressHelper.shortURLString(#URL("https://www.duckduckgo.com")), "duckduckgo.com") + XCTAssertEqual(AddressHelper.shortURLString(#URL("https://www.duckduckgo.com/some/path")), "duckduckgo.com") + XCTAssertEqual(AddressHelper.shortURLString(#URL("https://www.subdomain.duckduckgo.com/some/path")), "subdomain.duckduckgo.com") + XCTAssertEqual(AddressHelper.shortURLString(#URL("https://m.duckduckgo.com/some/path")), "m.duckduckgo.com") + XCTAssertEqual(AddressHelper.shortURLString(#URL("http://some-other.sub.domain.duck.eu/with/path")), "some-other.sub.domain.duck.eu") + XCTAssertEqual(AddressHelper.shortURLString(#URL("http://duckduckgo.com:1234")), "duckduckgo.com") + XCTAssertEqual(AddressHelper.shortURLString(#URL("https://192.168.0.1:1234")), "192.168.0.1") - XCTAssertEqual(AddressHelper.shortURLString(URL(string: "https://www.com")!), "com") // This is an exception we are ok with) + XCTAssertEqual(AddressHelper.shortURLString(#URL("https://www.com")), "com") // This is an exception we are ok with) - XCTAssertNil(AddressHelper.shortURLString(URL(string: "file:///some/path")!)) - XCTAssertNil(AddressHelper.shortURLString(URL(string: "somescheme:///some/path")!)) - XCTAssertNil(AddressHelper.shortURLString(URL(string: "blob:https://www.my.com/111-222-333-444")!)) - XCTAssertNil(AddressHelper.shortURLString(URL(string: "data:text/plain;charset=UTF-8;page=21,the%20data:12345")!)) + XCTAssertNil(AddressHelper.shortURLString(#URL("file:///some/path"))) + XCTAssertNil(AddressHelper.shortURLString(#URL("somescheme:///some/path"))) + XCTAssertNil(AddressHelper.shortURLString(#URL("blob:https://www.my.com/111-222-333-444"))) + XCTAssertNil(AddressHelper.shortURLString(#URL("data:text/plain;charset=UTF-8;page=21,the%20data:12345"))) } func testShortensURLWhenShortVersionExpected() { - let addressForDisplay = AddressHelper.addressForDisplay(url: URL(string: "http://some.domain.eu/with/path")!, showsFullURL: false) + let addressForDisplay = AddressHelper.addressForDisplay(url: #URL("http://some.domain.eu/with/path"), showsFullURL: false) XCTAssertEqual(addressForDisplay, "some.domain.eu") } func testDoesNotShortenURLWhenFullVersionExpected() { - let addressForDisplay = AddressHelper.addressForDisplay(url: URL(string: "http://some.domain.eu/with/path")!, showsFullURL: true) + let addressForDisplay = AddressHelper.addressForDisplay(url: #URL("http://some.domain.eu/with/path"), showsFullURL: true) XCTAssertEqual(addressForDisplay, "http://some.domain.eu/with/path") } func testFallsBackToLongURLWhenCannotProduceShortURL() { - let addressForDisplay = AddressHelper.addressForDisplay(url: URL(string: "file:///some/path")!, showsFullURL: false) + let addressForDisplay = AddressHelper.addressForDisplay(url: #URL("file:///some/path"), showsFullURL: false) XCTAssertEqual(addressForDisplay, "file:///some/path") } diff --git a/DuckDuckGoTests/AppURLsTests.swift b/DuckDuckGoTests/AppURLsTests.swift index 280e855dcc..830fa92b30 100644 --- a/DuckDuckGoTests/AppURLsTests.swift +++ b/DuckDuckGoTests/AppURLsTests.swift @@ -17,7 +17,9 @@ // limitations under the License. // +import Macros import XCTest + @testable import BrowserServicesKit @testable import Core @@ -60,7 +62,7 @@ final class AppURLsTests: XCTestCase { } func testWhenRemoveInternalSearchParametersFromNonSearchUrlThenUrlIsUnchanged() { - let example = URL(string: "https://duckduckgo.com?atb=x&t=y&ko=z")! + let example = #URL("https://duckduckgo.com?atb=x&t=y&ko=z") let result = example.removingInternalSearchParameters() XCTAssertEqual(example.absoluteString, result.absoluteString) } @@ -76,13 +78,13 @@ final class AppURLsTests: XCTestCase { } func testBaseUrlDoesNotHaveSubDomain() { - XCTAssertEqual(URL.ddg, URL(string: "https://duckduckgo.com")) + XCTAssertEqual(URL.ddg, #URL("https://duckduckgo.com")) } func testWhenMobileStatsParamsAreAppliedThenTheyReturnAnUpdatedUrl() throws { mockStatisticsStore.atb = "x" let actual = StatisticsDependentURLFactory(statisticsStore: mockStatisticsStore) - .applyingStatsParams(to: URL(string: "http://duckduckgo.com?atb=wrong&t=wrong")!) + .applyingStatsParams(to: #URL("http://duckduckgo.com?atb=wrong&t=wrong")) XCTAssertEqual(actual.getParameter(named: "atb"), "x") XCTAssertEqual(actual.getParameter(named: "t"), "ddg_ios") } @@ -90,70 +92,70 @@ final class AppURLsTests: XCTestCase { func testWhenAtbMatchesThenHasMobileStatsParamsIsTrue() { mockStatisticsStore.atb = "x" let result = StatisticsDependentURLFactory(statisticsStore: mockStatisticsStore) - .hasCorrectMobileStatsParams(url: URL(string: "http://duckduckgo.com?atb=x&t=ddg_ios")!) + .hasCorrectMobileStatsParams(url: #URL("http://duckduckgo.com?atb=x&t=ddg_ios")) XCTAssertTrue(result) } func testWhenAtbIsMismatchedThenHasMobileStatsParamsIsFalse() { mockStatisticsStore.atb = "y" let result = StatisticsDependentURLFactory(statisticsStore: mockStatisticsStore) - .hasCorrectMobileStatsParams(url: URL(string: "http://duckduckgo.com?atb=x&t=ddg_ios")!) + .hasCorrectMobileStatsParams(url: #URL("http://duckduckgo.com?atb=x&t=ddg_ios")) XCTAssertFalse(result) } func testWhenAtbIsMissingThenHasMobileStatsParamsIsFalse() { mockStatisticsStore.atb = "x" let result = StatisticsDependentURLFactory(statisticsStore: mockStatisticsStore) - .hasCorrectMobileStatsParams(url: URL(string: "http://duckduckgo.com?t=ddg_ios")!) + .hasCorrectMobileStatsParams(url: #URL("http://duckduckgo.com?t=ddg_ios")) XCTAssertFalse(result) } func testWhenSourceIsMismatchedThenHasMobileStatsParamsIsFalse() { mockStatisticsStore.atb = "x" let result = StatisticsDependentURLFactory(statisticsStore: mockStatisticsStore) - .hasCorrectMobileStatsParams(url: URL(string: "http://duckduckgo.com?atb=x&t=ddg_desktop")!) + .hasCorrectMobileStatsParams(url: #URL("http://duckduckgo.com?atb=x&t=ddg_desktop")) XCTAssertFalse(result) } func testWhenSourceIsMissingThenHasMobileStatsParamsIsFalse() { mockStatisticsStore.atb = "x" let result = StatisticsDependentURLFactory(statisticsStore: mockStatisticsStore) - .hasCorrectMobileStatsParams(url: URL(string: "http://duckduckgo.com?atb=y")!) + .hasCorrectMobileStatsParams(url: #URL("http://duckduckgo.com?atb=y")) XCTAssertFalse(result) } func testWhenUrlIsDdgWithASearchParamThenIsSearchIsTrue() { - let result = URL(string: "http://duckduckgo.com?q=hello")!.isDuckDuckGoSearch + let result = #URL("http://duckduckgo.com?q=hello").isDuckDuckGoSearch XCTAssertTrue(result) } func testWhenUrlHasNoSearchParamsThenIsSearchIsFalse() { - let result = URL(string: "http://duckduckgo.com?test=hello")!.isDuckDuckGoSearch + let result = #URL("http://duckduckgo.com?test=hello").isDuckDuckGoSearch XCTAssertFalse(result) } func testWhenUrlIsNonDdgThenIsSearchIsFalse() { - let result = URL(string: "http://www.example.com?q=hello")!.isDuckDuckGoSearch + let result = #URL("http://www.example.com?q=hello").isDuckDuckGoSearch XCTAssertFalse(result) } func testWhenNonDdgUrlHasDdgParamThenIsDdgIsFalse() { - let result = URL(string: "http://www.example.com?x=duckduckgo.com")!.isDuckDuckGo + let result = #URL("http://www.example.com?x=duckduckgo.com").isDuckDuckGo XCTAssertFalse(result) } func testWhenDdgUrlIsHttpThenIsDddgIsTrue() { - let result = URL(string: "http://duckduckgo.com")!.isDuckDuckGo + let result = #URL("http://duckduckgo.com").isDuckDuckGo XCTAssertTrue(result) } func testWhenDdgUrlIsHttpsThenIsDddgIsTrue() { - let result = URL(string: "https://duckduckgo.com")!.isDuckDuckGo + let result = #URL("https://duckduckgo.com").isDuckDuckGo XCTAssertTrue(result) } func testWhenDdgUrlHasSubdomainThenIsDddgIsTrue() { - let result = URL(string: "http://www.duckduckgo.com")!.isDuckDuckGo + let result = #URL("http://www.duckduckgo.com").isDuckDuckGo XCTAssertTrue(result) } @@ -233,7 +235,7 @@ final class AppURLsTests: XCTestCase { } func testWhenExistingQueryUsesVerticalThenItIsAppliedToNewOne() throws { - let contextURL = URL(string: "https://duckduckgo.com/?q=query&iar=images&ko=-1&ia=images")! + let contextURL = #URL("https://duckduckgo.com/?q=query&iar=images&ko=-1&ia=images") let url = StatisticsDependentURLFactory(statisticsStore: mockStatisticsStore) .makeSearchURL(query: "query", queryContext: contextURL)! @@ -242,7 +244,7 @@ final class AppURLsTests: XCTestCase { } func testWhenExistingQueryUsesVerticalWithMapsThenTheseAreIgnored() throws { - let contextURL = URL(string: "https://duckduckgo.com/?q=query&iar=images&ko=-1&ia=images&iaxm=maps")! + let contextURL = #URL("https://duckduckgo.com/?q=query&iar=images&ko=-1&ia=images&iaxm=maps") let url = StatisticsDependentURLFactory(statisticsStore: mockStatisticsStore) .makeSearchURL(query: "query", queryContext: contextURL)! @@ -253,7 +255,7 @@ final class AppURLsTests: XCTestCase { } func testWhenExistingQueryHasNoVerticalThenItIsAbsentInNewOne() throws { - let contextURL = URL(string: "https://example.com")! + let contextURL = #URL("https://example.com") let url = StatisticsDependentURLFactory(statisticsStore: mockStatisticsStore) .makeSearchURL(query: "query", queryContext: contextURL)! @@ -273,20 +275,20 @@ final class AppURLsTests: XCTestCase { } func testWhenDdgUrlWithSearchParamThenSearchQueryReturned() { - let url = URL(string: "https://www.duckduckgo.com/?ko=-1&kl=wt-wt&q=some%20search")! + let url = #URL("https://www.duckduckgo.com/?ko=-1&kl=wt-wt&q=some%20search") let expected = "some search" let actual = url.searchQuery XCTAssertEqual(actual, expected) } func testWhenNoSearchParamInDdgUrlThenSearchQueryReturnsNil() { - let url = URL(string: "https://www.duckduckgo.com/?ko=-1&kl=wt-wt")! + let url = #URL("https://www.duckduckgo.com/?ko=-1&kl=wt-wt") let result = url.searchQuery XCTAssertNil(result) } func testWhenNotDdgUrlThenSearchQueryReturnsNil() { - let url = URL(string: "https://www.test.com/?ko=-1&kl=wt-wt&q=some%20search")! + let url = #URL("https://www.test.com/?ko=-1&kl=wt-wt&q=some%20search") let result = url.searchQuery XCTAssertNil(result) } diff --git a/DuckDuckGoTests/BookmarksCachingSearchTests.swift b/DuckDuckGoTests/BookmarksCachingSearchTests.swift index 7885ce8e8e..0efb242a11 100644 --- a/DuckDuckGoTests/BookmarksCachingSearchTests.swift +++ b/DuckDuckGoTests/BookmarksCachingSearchTests.swift @@ -17,10 +17,11 @@ // limitations under the License. // -import XCTest -import CoreData -import Combine import Bookmarks +import Combine +import CoreData +import Macros +import XCTest @testable import Core @@ -42,7 +43,7 @@ public class MockBookmarksSearchStore: BookmarksSearchStore { class BookmarksCachingSearchTests: XCTestCase { - let url = URL(string: "http://duckduckgo.com")! + let url = #URL("http://duckduckgo.com") let simpleStore = MockBookmarksSearchStore() let urlStore = MockBookmarksSearchStore() @@ -85,9 +86,9 @@ class BookmarksCachingSearchTests: XCTestCase { BookmarksCachingSearch.ScoredBookmark(objectID: mockObjectID, title: Entry.f12a.rawValue, url: url, isFavorite: true)] urlStore.dataSet = [ - BookmarksCachingSearch.ScoredBookmark(objectID: mockObjectID, title: Entry.urlExample1.rawValue, url: URL(string: "https://example.com")!, isFavorite: true), - BookmarksCachingSearch.ScoredBookmark(objectID: mockObjectID, title: Entry.urlExample2.rawValue, url: URL(string: "https://example.com")!, isFavorite: true), - BookmarksCachingSearch.ScoredBookmark(objectID: mockObjectID, title: Entry.urlNasa.rawValue, url: URL(string: "https://www.nasa.gov")!, isFavorite: true), + BookmarksCachingSearch.ScoredBookmark(objectID: mockObjectID, title: Entry.urlExample1.rawValue, url: #URL("https://example.com"), isFavorite: true), + BookmarksCachingSearch.ScoredBookmark(objectID: mockObjectID, title: Entry.urlExample2.rawValue, url: #URL("https://example.com"), isFavorite: true), + BookmarksCachingSearch.ScoredBookmark(objectID: mockObjectID, title: Entry.urlNasa.rawValue, url: #URL("https://www.nasa.gov"), isFavorite: true), BookmarksCachingSearch.ScoredBookmark(objectID: mockObjectID, title: Entry.urlDDG.rawValue, url: url, isFavorite: true)] } @@ -238,6 +239,6 @@ class BookmarksCachingSearchTests: XCTestCase { private extension BookmarksCachingSearchTests { enum Constants { static let bookmarkTitle = "my bookmark" - static let bookmarkURL = URL(string: "https://www.apple.com")! + static let bookmarkURL = #URL("https://www.apple.com") } } diff --git a/DuckDuckGoTests/BookmarksImporterTests.swift b/DuckDuckGoTests/BookmarksImporterTests.swift index e8a4dc44ee..94d2375de5 100644 --- a/DuckDuckGoTests/BookmarksImporterTests.swift +++ b/DuckDuckGoTests/BookmarksImporterTests.swift @@ -17,10 +17,12 @@ // limitations under the License. // -import XCTest +import Bookmarks +import Macros import SwiftSoup +import XCTest + @testable import Core -import Bookmarks @MainActor class BookmarksImporterTests: XCTestCase { @@ -195,6 +197,6 @@ private extension BookmarksImporterTests { enum Constants { static let bookmarkTitle = "my bookmark" static let bookmarkURLString = "https://duckduckgo.com" - static let bookmarkURL = URL(string: "https://duckduckgo.com")! + static let bookmarkURL = #URL("https://duckduckgo.com") } } diff --git a/DuckDuckGoTests/DaxDialogTests.swift b/DuckDuckGoTests/DaxDialogTests.swift index 727f21a99d..1d0072f0b5 100644 --- a/DuckDuckGoTests/DaxDialogTests.swift +++ b/DuckDuckGoTests/DaxDialogTests.swift @@ -17,13 +17,15 @@ // limitations under the License. // -import XCTest -@testable import DuckDuckGo -@testable import Core import BrowserServicesKit -import TrackerRadarKit import ContentBlocking +import Macros import PrivacyDashboard +import TrackerRadarKit +import XCTest + +@testable import Core +@testable import DuckDuckGo private struct MockEntityProvider: EntityProviding { @@ -46,13 +48,13 @@ final class DaxDialog: XCTestCase { struct URLs { - static let example = URL(string: "https://www.example.com")! - static let ddg = URL(string: "https://duckduckgo.com?q=test")! - static let facebook = URL(string: "https://www.facebook.com")! - static let google = URL(string: "https://www.google.com")! - static let ownedByFacebook = URL(string: "https://www.instagram.com")! - static let amazon = URL(string: "https://www.amazon.com")! - static let tracker = URL(string: "https://www.1dmp.io")! + static let example = #URL("https://www.example.com") + static let ddg = #URL("https://duckduckgo.com?q=test") + static let facebook = #URL("https://www.facebook.com") + static let google = #URL("https://www.google.com") + static let ownedByFacebook = #URL("https://www.instagram.com") + static let amazon = #URL("https://www.amazon.com") + static let tracker = #URL("https://www.1dmp.io") } diff --git a/DuckDuckGoTests/DownloadMocks.swift b/DuckDuckGoTests/DownloadMocks.swift index 1601392430..4ff1c9bd4a 100644 --- a/DuckDuckGoTests/DownloadMocks.swift +++ b/DuckDuckGoTests/DownloadMocks.swift @@ -18,6 +18,7 @@ // import Foundation +import Macros import WebKit @testable import DuckDuckGo @@ -55,7 +56,7 @@ class MockNavigationResponse: WKNavigationResponse { var mimeType: String? override var response: URLResponse { - let response = MockURLResponse(url: URL(string: "https://www.duck.com")!, + let response = MockURLResponse(url: #URL("https://www.duck.com"), mimeType: mimeType!, expectedContentLength: 1234, textEncodingName: "") diff --git a/DuckDuckGoTests/DownloadTestsHelper.swift b/DuckDuckGoTests/DownloadTestsHelper.swift index e9810b6c21..073e463402 100644 --- a/DuckDuckGoTests/DownloadTestsHelper.swift +++ b/DuckDuckGoTests/DownloadTestsHelper.swift @@ -18,10 +18,12 @@ // import Foundation +import Macros + @testable import DuckDuckGo struct DownloadTestsHelper { - let mockURL = URL(string: "https://duck.com")! + let mockURL = #URL("https://duck.com") let tmpDirectory = FileManager.default.temporaryDirectory let downloadsDirectory: URL diff --git a/DuckDuckGoTests/FaviconRequestModifierTests.swift b/DuckDuckGoTests/FaviconRequestModifierTests.swift index 0058e7a5c9..b3431cd777 100644 --- a/DuckDuckGoTests/FaviconRequestModifierTests.swift +++ b/DuckDuckGoTests/FaviconRequestModifierTests.swift @@ -17,8 +17,10 @@ // limitations under the License. // -import XCTest import BrowserServicesKit +import Macros +import XCTest + @testable import Core class MockEmbeddedDataProvider: EmbeddedDataProvider { @@ -74,7 +76,7 @@ class FaviconRequestModifierTests: XCTestCase { } func test() { - let request = URLRequest(url: URL(string: "https://www.example.com")!) + let request = URLRequest(url: #URL("https://www.example.com")) let result = FaviconRequestModifier(userAgentManager: userAgentManager).modified(for: request) XCTAssertTrue(result?.allHTTPHeaderFields?["User-Agent"]?.contains("DuckDuckGo") ?? false) } diff --git a/DuckDuckGoTests/FaviconsTests.swift b/DuckDuckGoTests/FaviconsTests.swift index efe00fe4d4..12d4bb494a 100644 --- a/DuckDuckGoTests/FaviconsTests.swift +++ b/DuckDuckGoTests/FaviconsTests.swift @@ -17,11 +17,13 @@ // limitations under the License. // +import Bookmarks +import CoreData +import Kingfisher +import Macros import XCTest + @testable import Core -import Kingfisher -import CoreData -import Bookmarks class FaviconsTests: XCTestCase { @@ -97,8 +99,8 @@ class FaviconsTests: XCTestCase { switch options?[4] { case .alternativeSources(let sources): XCTAssertEqual(2, sources.count) - XCTAssertEqual(sources[0].url, URL(string: "https://example.com/favicon.ico")) - XCTAssertEqual(sources[1].url, URL(string: "http://example.com/favicon.ico")) + XCTAssertEqual(sources[0].url, #URL("https://example.com/favicon.ico")) + XCTAssertEqual(sources[1].url, #URL("http://example.com/favicon.ico")) default: XCTFail("Unexpected option") diff --git a/DuckDuckGoTests/FireproofFaviconUpdaterTests.swift b/DuckDuckGoTests/FireproofFaviconUpdaterTests.swift index f8713a7307..2dfacdc021 100644 --- a/DuckDuckGoTests/FireproofFaviconUpdaterTests.swift +++ b/DuckDuckGoTests/FireproofFaviconUpdaterTests.swift @@ -17,12 +17,14 @@ // limitations under the License. // +import Bookmarks +import Core import Foundation +import Macros +import Persistence import XCTest + @testable import DuckDuckGo -import Persistence -import Core -import Bookmarks class FireproofFaviconUpdaterTests: XCTestCase, TabNotifying, FaviconProviding { @@ -85,7 +87,7 @@ class FireproofFaviconUpdaterTests: XCTestCase, TabNotifying, FaviconProviding { try createBookmark() image = UIImage() - let url = URL(string: "https://example.com/favicon.ico")! + let url = #URL("https://example.com/favicon.ico") let updater = FireproofFaviconUpdater(bookmarksDatabase: db, tab: self, favicons: self) updater.faviconUserScript(FaviconUserScript(), didRequestUpdateFaviconForHost: "example.com", withUrl: url) @@ -102,7 +104,7 @@ class FireproofFaviconUpdaterTests: XCTestCase, TabNotifying, FaviconProviding { try createBookmark() image = UIImage() - let url = URL(string: "https://example.com/favicon.ico")! + let url = #URL("https://example.com/favicon.ico") let updater = FireproofFaviconUpdater(bookmarksDatabase: db, tab: self, favicons: self) updater.faviconUserScript(FaviconUserScript(), didRequestUpdateFaviconForHost: "www.example.com", withUrl: url) diff --git a/DuckDuckGoTests/HTTPSUpgradeTests.swift b/DuckDuckGoTests/HTTPSUpgradeTests.swift index cc649cb09b..c32252598a 100644 --- a/DuckDuckGoTests/HTTPSUpgradeTests.swift +++ b/DuckDuckGoTests/HTTPSUpgradeTests.swift @@ -17,10 +17,11 @@ // limitations under the License. // -import XCTest +import BrowserServicesKit +import Macros import OHHTTPStubs import OHHTTPStubsSwift -import BrowserServicesKit +import XCTest @testable import Core @@ -34,7 +35,7 @@ class HTTPSUpgradeTests: XCTestCase { func testWhenURLIsHttpsThenShouldUpgradeResultIsFalse() { let expect = expectation(description: "Https url should not be upgraded") - let url = URL(string: "https://upgradable.url")! + let url = #URL("https://upgradable.url") let testee = HTTPSUpgrade(store: MockHTTPSUpgradeStore(bloomFilter: bloomFilter())) testee.loadData() @@ -49,7 +50,7 @@ class HTTPSUpgradeTests: XCTestCase { func testWhenURLIsExcludedThenShouldUpgradeResultIsFalse() { let expect = expectation(description: "Excluded http:// urls should not be upgraded") - let url = URL(string: "http://excluded.url")! + let url = #URL("http://excluded.url") let testee = HTTPSUpgrade(store: MockHTTPSUpgradeStore(bloomFilter: bloomFilter())) testee.loadData() @@ -63,7 +64,7 @@ class HTTPSUpgradeTests: XCTestCase { func testWhenURLIsHttpAndCanBeUpgradedThenShouldUpgradeIsTrue() { let expect = expectation(description: "Http url in list and should be upgraded") - let url = URL(string: "http://upgradable.url")! + let url = #URL("http://upgradable.url") let testee = HTTPSUpgrade(store: MockHTTPSUpgradeStore(bloomFilter: bloomFilter()), privacyConfig: WebKitTestHelper.preparePrivacyConfig( @@ -84,7 +85,7 @@ class HTTPSUpgradeTests: XCTestCase { func testWhenURLIsHttpAndHttpsUpgradesDisabledThenShouldUpgradeIsFalse() { let expect = expectation(description: "Http url in list and should not be upgraded") - let url = URL(string: "http://upgradable.url")! + let url = #URL("http://upgradable.url") let testee = HTTPSUpgrade(store: MockHTTPSUpgradeStore(bloomFilter: bloomFilter()), privacyConfig: WebKitTestHelper.preparePrivacyConfig( @@ -105,7 +106,7 @@ class HTTPSUpgradeTests: XCTestCase { func testWhenURLIsHttpAndCannotBeUpgradedThenShouldUpgradeIsFalse() { let expect = expectation(description: "Http url not in list should not be upgraded") - let url = URL(string: "http://unknown.url")! + let url = #URL("http://unknown.url") let testee = HTTPSUpgrade(store: MockHTTPSUpgradeStore(bloomFilter: bloomFilter())) testee.loadData() diff --git a/DuckDuckGoTests/MenuBookmarksViewModelTests.swift b/DuckDuckGoTests/MenuBookmarksViewModelTests.swift index d2bce8cb21..e4f310fbb4 100644 --- a/DuckDuckGoTests/MenuBookmarksViewModelTests.swift +++ b/DuckDuckGoTests/MenuBookmarksViewModelTests.swift @@ -17,11 +17,12 @@ // limitations under the License. // -import Foundation -import XCTest import Bookmarks -import Persistence import DuckDuckGo +import Foundation +import Macros +import Persistence +import XCTest private extension MenuBookmarksViewModel { @@ -35,7 +36,7 @@ private extension MenuBookmarksViewModel { class MenuBookmarksViewModelTests: XCTestCase { - let url = URL(string: "https://test.com")! + let url = #URL("https://test.com") var db: CoreDataDatabase! override func setUpWithError() throws { diff --git a/DuckDuckGoTests/MockSecureVault.swift b/DuckDuckGoTests/MockSecureVault.swift index 8545c641fa..ca0aea4c51 100644 --- a/DuckDuckGoTests/MockSecureVault.swift +++ b/DuckDuckGoTests/MockSecureVault.swift @@ -17,10 +17,11 @@ // limitations under the License. // -import Foundation import BrowserServicesKit -import SecureStorage +import Foundation import GRDB +import Macros +import SecureStorage // swiftlint:disable file_length typealias MockVaultFactory = SecureVaultFactory> @@ -222,6 +223,10 @@ final class MockSecureVault: AutofillSecureVault { // MARK: - Mock Providers +private extension URL { + static let duckduckgo = #URL("https://duckduckgo.com/") +} + class MockDatabaseProvider: AutofillDatabaseProvider { // swiftlint:disable identifier_name @@ -237,13 +242,13 @@ class MockDatabaseProvider: AutofillDatabaseProvider { var db: GRDB.DatabaseWriter // swiftlint:enable identifier_name - required init(file: URL = URL(string: "https://duckduckgo.com/")!, key: Data = Data()) throws { + required init(file: URL = .duckduckgo, key: Data = Data()) throws { db = (try? DatabaseQueue(named: "Test"))! } static func recreateDatabase(withKey key: Data) throws -> Self { // swiftlint:disable:next force_cast - return try MockDatabaseProvider(file: URL(string: "https://duck.com")!, key: Data()) as! Self + return try MockDatabaseProvider(file: #URL("https://duck.com"), key: Data()) as! Self } func storeWebsiteCredentials(_ credentials: SecureVaultModels.WebsiteCredentials) throws -> Int64 { diff --git a/DuckDuckGoTests/MockUserAgent.swift b/DuckDuckGoTests/MockUserAgent.swift index d9bb55ff33..49c9897345 100644 --- a/DuckDuckGoTests/MockUserAgent.swift +++ b/DuckDuckGoTests/MockUserAgent.swift @@ -17,9 +17,10 @@ // limitations under the License. // +import BrowserServicesKit import Foundation +import Macros import WebKit -import BrowserServicesKit class MockUserAgentManager: UserAgentManager { @@ -33,7 +34,7 @@ class MockUserAgentManager: UserAgentManager { private func prepareUserAgent() { let webview = WKWebView() - webview.load(URLRequest.developerInitiated(URL(string: "about:blank")!)) + webview.load(URLRequest.developerInitiated(#URL("about:blank"))) getDefaultAgent(webView: webview) { [weak self] agent in // Reference webview instance to keep it in scope and allow UA to be returned diff --git a/DuckDuckGoTests/NotFoundCachingDownloaderTests.swift b/DuckDuckGoTests/NotFoundCachingDownloaderTests.swift index 3bb8ed65c4..bb8f666020 100644 --- a/DuckDuckGoTests/NotFoundCachingDownloaderTests.swift +++ b/DuckDuckGoTests/NotFoundCachingDownloaderTests.swift @@ -17,7 +17,9 @@ // limitations under the License. // +import Macros import XCTest + @testable import Core class NotFoundCachingDownloaderTests: XCTestCase { @@ -57,7 +59,7 @@ class NotFoundCachingDownloaderTests: XCTestCase { downloader.noFaviconsFound(forDomain: "example.com") let moreThanAWeekFromNow = Date().addingTimeInterval(60 * 60 * 24 * 8) - XCTAssertTrue(downloader.shouldDownload(URL(string: "https://example.com/path/to/image.png")!, referenceDate: moreThanAWeekFromNow)) + XCTAssertTrue(downloader.shouldDownload(#URL("https://example.com/path/to/image.png"), referenceDate: moreThanAWeekFromNow)) guard let domains: [String: TimeInterval] = UserDefaults.app.object(forKey: UserDefaultsWrapper.Key.notFoundCache.rawValue) as? [String: TimeInterval] else { @@ -70,11 +72,11 @@ class NotFoundCachingDownloaderTests: XCTestCase { func testWhenMarkingDomainAsNotFoundThenShouldNotDownload() { downloader.noFaviconsFound(forDomain: "example.com") - XCTAssertFalse(downloader.shouldDownload(URL(string: "https://example.com/path/to/image.png")!)) + XCTAssertFalse(downloader.shouldDownload(#URL("https://example.com/path/to/image.png"))) } func testWhenDomainNotMarkedAsNotFoundThenShouldNotDownload() { - XCTAssertTrue(downloader.shouldDownload(URL(string: "https://example.com/path/to/image.png")!)) + XCTAssertTrue(downloader.shouldDownload(#URL("https://example.com/path/to/image.png"))) } } diff --git a/DuckDuckGoTests/PrivacyIconLogicTests.swift b/DuckDuckGoTests/PrivacyIconLogicTests.swift index a14220bdc8..7ff6ad326f 100644 --- a/DuckDuckGoTests/PrivacyIconLogicTests.swift +++ b/DuckDuckGoTests/PrivacyIconLogicTests.swift @@ -17,21 +17,23 @@ // limitations under the License. // -import Foundation -import XCTest -import TrackerRadarKit import BrowserServicesKit +import Foundation +import Macros import PrivacyDashboard +import TrackerRadarKit +import XCTest + @testable import Core @testable import DuckDuckGo class PrivacyIconLogicTests: XCTestCase { - static let pageURL = URL(string: "https://example.com")! - static let insecurePageURL = URL(string: "http://example.com")! - static let ddgSearchURL = URL(string: "https://duckduckgo.com/?q=catfood&t=h_&ia=web")! - static let ddgMainURL = URL(string: "https://duckduckgo.com")! - static let ddgSupportURL = URL(string: "https://duckduckgo.com/email/settings/support")! + static let pageURL = #URL("https://example.com") + static let insecurePageURL = #URL("http://example.com") + static let ddgSearchURL = #URL("https://duckduckgo.com/?q=catfood&t=h_&ia=web") + static let ddgMainURL = #URL("https://duckduckgo.com") + static let ddgSupportURL = #URL("https://duckduckgo.com/email/settings/support") func testPrivacyIconIsShieldForPageURL() { let url = PrivacyIconLogicTests.insecurePageURL diff --git a/DuckDuckGoTests/TabTests.swift b/DuckDuckGoTests/TabTests.swift index c5092a92d8..e8eaa73ba4 100644 --- a/DuckDuckGoTests/TabTests.swift +++ b/DuckDuckGoTests/TabTests.swift @@ -17,16 +17,18 @@ // limitations under the License. // +import Macros import XCTest -@testable import DuckDuckGo + @testable import Core +@testable import DuckDuckGo class TabTests: XCTestCase { struct Constants { static let title = "A title" - static let url = URL(string: "https://example.com")! - static let differentUrl = URL(string: "https://aDifferentUrl.com")! + static let url = #URL("https://example.com") + static let differentUrl = #URL("https://aDifferentUrl.com") } func testWhenDesktopPropertyChangesThenObserversNotified() { @@ -145,7 +147,7 @@ class TabTests: XCTestCase { } private func link() -> Link { - return Link(title: "title", url: URL(string: "http://example.com")!) + return Link(title: "title", url: #URL("http://example.com")) } } diff --git a/DuckDuckGoTests/TabsModelTests.swift b/DuckDuckGoTests/TabsModelTests.swift index f81545afa2..405e4922ea 100644 --- a/DuckDuckGoTests/TabsModelTests.swift +++ b/DuckDuckGoTests/TabsModelTests.swift @@ -17,13 +17,15 @@ // limitations under the License. // +import Macros import XCTest + @testable import DuckDuckGo @testable import Core class TabsModelTests: XCTestCase { - private let exampleLink = Link(title: nil, url: URL(string: "https://example.com")!) + private let exampleLink = Link(title: nil, url: #URL("https://example.com")) private var emptyModel: TabsModel { return TabsModel(desktop: false) @@ -38,9 +40,9 @@ class TabsModelTests: XCTestCase { private var filledModel: TabsModel { let model = TabsModel(tabs: [ - Tab(link: Link(title: "url1", url: URL(string: "https://ur1l.com")!)), - Tab(link: Link(title: "url2", url: URL(string: "https://ur12.com")!)), - Tab(link: Link(title: "url3", url: URL(string: "https://ur13.com")!)) + Tab(link: Link(title: "url1", url: #URL("https://ur1l.com"))), + Tab(link: Link(title: "url2", url: #URL("https://ur12.com"))), + Tab(link: Link(title: "url3", url: #URL("https://ur13.com"))) ], desktop: false) return model } @@ -102,7 +104,7 @@ class TabsModelTests: XCTestCase { } func testWhenTabExistsThenIndexReturned() { - let tab = Tab(link: Link(title: nil, url: URL(string: "https://www.example.com")!)) + let tab = Tab(link: Link(title: nil, url: #URL("https://www.example.com"))) let testee = filledModel testee.add(tab: tab) XCTAssertEqual(testee.indexOf(tab: tab), 3) diff --git a/DuckDuckGoTests/TrackerAnimationLogicTests.swift b/DuckDuckGoTests/TrackerAnimationLogicTests.swift index 07302fc11f..b3088d01d7 100644 --- a/DuckDuckGoTests/TrackerAnimationLogicTests.swift +++ b/DuckDuckGoTests/TrackerAnimationLogicTests.swift @@ -17,18 +17,20 @@ // limitations under the License. // -import Foundation -import XCTest -import TrackerRadarKit import BrowserServicesKit import ContentBlocking +import Foundation +import Macros import PrivacyDashboard +import TrackerRadarKit +import XCTest + @testable import Core @testable import DuckDuckGo class TrackerAnimationLogicTests: XCTestCase { - static let pageURL = URL(string: "https://example.com")! + static let pageURL = #URL("https://example.com") func testAnimationLogicToAnimateTrackersIfAnyBlocked() { let trackerInfo = makeBlockedTrackerInfo(pageURL: Self.pageURL) diff --git a/DuckDuckGoTests/UserAgentTests.swift b/DuckDuckGoTests/UserAgentTests.swift index 7055db968e..22b6e6e509 100644 --- a/DuckDuckGoTests/UserAgentTests.swift +++ b/DuckDuckGoTests/UserAgentTests.swift @@ -17,9 +17,11 @@ // limitations under the License. // +import BrowserServicesKit +import Macros import WebKit import XCTest -import BrowserServicesKit + @testable import Core // swiftlint:disable file_length type_body_length @@ -64,11 +66,11 @@ final class UserAgentTests: XCTestCase { } private struct Constants { - static let url = URL(string: "http://example.com/index.html") - static let noAppUrl = URL(string: "http://cvs.com/index.html") - static let noAppSubdomainUrl = URL(string: "http://subdomain.cvs.com/index.html") - static let ddgFixedUrl = URL(string: "http://test2.com/index.html") - static let ddgDefaultUrl = URL(string: "http://test3.com/index.html") + static let url = #URL("http://example.com/index.html") + static let noAppUrl = #URL("http://cvs.com/index.html") + static let noAppSubdomainUrl = #URL("http://subdomain.cvs.com/index.html") + static let ddgFixedUrl = #URL("http://test2.com/index.html") + static let ddgDefaultUrl = #URL("http://test3.com/index.html") } let testConfig = """ diff --git a/LocalPackages/DuckUI/Package.swift b/LocalPackages/DuckUI/Package.swift index 79df959eeb..693478114c 100644 --- a/LocalPackages/DuckUI/Package.swift +++ b/LocalPackages/DuckUI/Package.swift @@ -31,7 +31,7 @@ let package = Package( targets: ["DuckUI"]) ], dependencies: [ - .package(url: "https://github.com/duckduckgo/apple-toolbox.git", exact: "1.0.0"), + .package(url: "https://github.com/duckduckgo/apple-toolbox.git", exact: "2.0.0"), ], targets: [ .target( diff --git a/LocalPackages/SyncUI/Package.swift b/LocalPackages/SyncUI/Package.swift index 51c9b26b91..ebbe099b43 100644 --- a/LocalPackages/SyncUI/Package.swift +++ b/LocalPackages/SyncUI/Package.swift @@ -34,7 +34,7 @@ let package = Package( dependencies: [ .package(path: "../DuckUI"), .package(url: "https://github.com/duckduckgo/DesignResourcesKit", exact: "2.0.0"), - .package(url: "https://github.com/duckduckgo/apple-toolbox.git", exact: "1.0.0"), + .package(url: "https://github.com/duckduckgo/apple-toolbox.git", exact: "2.0.0"), ], targets: [ .target( diff --git a/LocalPackages/Waitlist/Package.swift b/LocalPackages/Waitlist/Package.swift index f3a3951ba5..b89a136609 100644 --- a/LocalPackages/Waitlist/Package.swift +++ b/LocalPackages/Waitlist/Package.swift @@ -16,12 +16,15 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/duckduckgo/DesignResourcesKit", exact: "2.0.0"), - .package(url: "https://github.com/duckduckgo/apple-toolbox.git", exact: "1.0.0"), + .package(url: "https://github.com/duckduckgo/apple-toolbox.git", exact: "2.0.0"), ], targets: [ .target( name: "Waitlist", - dependencies: ["DesignResourcesKit"], + dependencies: [ + "DesignResourcesKit", + .product(name: "Macros", package: "apple-toolbox"), + ], swiftSettings: [ .define("DEBUG", .when(configuration: .debug)) ], diff --git a/LocalPackages/Waitlist/Sources/Waitlist/Network/ProductWaitlistRequest.swift b/LocalPackages/Waitlist/Sources/Waitlist/Network/ProductWaitlistRequest.swift index 63dab2041f..1058a46a3f 100644 --- a/LocalPackages/Waitlist/Sources/Waitlist/Network/ProductWaitlistRequest.swift +++ b/LocalPackages/Waitlist/Sources/Waitlist/Network/ProductWaitlistRequest.swift @@ -18,6 +18,7 @@ // import Foundation +import Macros public typealias ProductWaitlistMakeHTTPRequest = (URL, _ method: String, _ body: Data?, @escaping ProductWaitlistHTTPRequestCompletion) -> Void public typealias ProductWaitlistHTTPRequestCompletion = (Data?, Error?) -> Void @@ -133,9 +134,9 @@ public class ProductWaitlistRequest: WaitlistRequest { private var endpoint: URL { #if DEBUG - return URL(string: "https://quack.duckduckgo.com/api/auth/waitlist/")! + return #URL("https://quack.duckduckgo.com/api/auth/waitlist/") #else - return URL(string: "https://quack.duckduckgo.com/api/auth/waitlist/")! + return #URL("https://quack.duckduckgo.com/api/auth/waitlist/") #endif } diff --git a/LocalPackages/Waitlist/Sources/WaitlistMocks/TestWaitlist.swift b/LocalPackages/Waitlist/Sources/WaitlistMocks/TestWaitlist.swift index 51236cdf43..0dd29425fd 100644 --- a/LocalPackages/Waitlist/Sources/WaitlistMocks/TestWaitlist.swift +++ b/LocalPackages/Waitlist/Sources/WaitlistMocks/TestWaitlist.swift @@ -18,6 +18,7 @@ // import Foundation +import Macros import Waitlist public struct TestWaitlist: Waitlist { @@ -38,7 +39,7 @@ public struct TestWaitlist: Waitlist { public static var identifier: String = "mockIdentifier" public static var apiProductName: String = "mockApiProductName" - public static var downloadURL: URL = URL(string: "https://duckduckgo.com")! + public static var downloadURL: URL = #URL("https://duckduckgo.com") public static var backgroundTaskName: String = "BG Task" public static var backgroundRefreshTaskIdentifier: String = "bgtask" diff --git a/LocalPackages/Waitlist/Tests/WaitlistTests/WaitlistViewModelTests.swift b/LocalPackages/Waitlist/Tests/WaitlistTests/WaitlistViewModelTests.swift index fffb48ee09..3fc237560b 100644 --- a/LocalPackages/Waitlist/Tests/WaitlistTests/WaitlistViewModelTests.swift +++ b/LocalPackages/Waitlist/Tests/WaitlistTests/WaitlistViewModelTests.swift @@ -17,10 +17,12 @@ // limitations under the License. // -import XCTest import Combine +import Macros import UserNotifications import WaitlistMocks +import XCTest + @testable import Waitlist class WaitlistViewModelTests: XCTestCase { @@ -261,7 +263,7 @@ extension WaitlistViewModel { waitlistRequest: waitlistRequest, waitlistStorage: waitlistStorage, notificationService: notificationService, - downloadURL: URL(string: "https://duckduckgo.com")! + downloadURL: #URL("https://duckduckgo.com") ) } } diff --git a/Widgets/WidgetViews.swift b/Widgets/WidgetViews.swift index 60e6902090..81f71f056e 100644 --- a/Widgets/WidgetViews.swift +++ b/Widgets/WidgetViews.swift @@ -17,8 +17,9 @@ // limitations under the License. // -import WidgetKit +import Macros import SwiftUI +import WidgetKit struct FavoriteView: View { @@ -306,7 +307,7 @@ extension Image { struct WidgetViews_Previews: PreviewProvider { static let mockFavorites: [Favorite] = { - let duckDuckGoFavorite = Favorite(url: URL(string: "https://duckduckgo.com/")!, + let duckDuckGoFavorite = Favorite(url: #URL("https://duckduckgo.com/"), domain: "duckduckgo.com", title: "title", favicon: nil) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 751b5b0df9..0b02e8896e 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -78,7 +78,7 @@ lane :adhoc do |options| scheme: "DuckDuckGo", export_options: "adhocExportOptions.plist", derived_data_path: "DerivedData", - xcargs: "-skipPackagePluginValidation" + xcargs: "-skipPackagePluginValidation -skipMacroValidation" ) if is_ci @@ -184,7 +184,7 @@ private_lane :build_release do |options| scheme: "DuckDuckGo", export_options: "appStoreExportOptions.plist", derived_data_path: "DerivedData", - xcargs: "-skipPackagePluginValidation" + xcargs: "-skipPackagePluginValidation -skipMacroValidation" ) end @@ -197,7 +197,7 @@ private_lane :build_alpha do |options| scheme: "DuckDuckGo-Alpha", export_options: "alphaExportOptions.plist", derived_data_path: "DerivedData", - xcargs: "-skipPackagePluginValidation" + xcargs: "-skipPackagePluginValidation -skipMacroValidation" ) end