Skip to content

Commit

Permalink
Convert namespacedPrefixes into regex
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexey Naumov committed Dec 25, 2022
1 parent 63bd28b commit 22a48ce
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 32 deletions.
34 changes: 26 additions & 8 deletions Sources/ViewInspector/BaseTypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public protocol KnownViewType {
public extension KnownViewType {
static var namespacedPrefixes: [String] {
guard !typePrefix.isEmpty else { return [] }
return ["SwiftUI." + typePrefix]
return [.swiftUINamespaceRegex + typePrefix]
}
static var isTransitive: Bool { false }
static func inspectionCall(typeName: String) -> String {
Expand All @@ -68,15 +68,33 @@ internal extension String {
prefix(1).lowercased() + dropFirst()
}

func hasPrefix(regex: String) -> Bool {
guard let ex = try? NSRegularExpression(pattern: regex) else { return false }
let range = NSRange(location: 0, length: utf16.count)
return ex.firstMatch(in: self, range: range)?.range.lowerBound == 0
}
static var swiftUINamespaceRegex: String { "SwiftUI(|[a-zA-Z0-9]{0,2}\\))\\." }

func removingSwiftUINamespace() -> String {
guard hasPrefix("SwiftUI.") else { return self }
return String(suffix(count - 8))
return removing(prefix: .swiftUINamespaceRegex)
.removing(prefix: "SwiftUI.")
}

func removing(prefix: String) -> String {
guard hasPrefix(prefix) else { return self }
return String(suffix(count - prefix.count))
}

fileprivate func hasPrefix(regex: String, wholeMatch: Bool) -> Bool {
let range = NSRange(location: 0, length: utf16.count)
guard let ex = try? NSRegularExpression(pattern: regex),
let match = ex.firstMatch(in: self, range: range)
else { return false }
if wholeMatch {
return match.range == range
}
return match.range.lowerBound == 0
}
}

internal extension Array where Element == String {
func containsPrefixRegex(matching name: String, wholeMatch: Bool = true) -> Bool {
return contains(where: { name.hasPrefix(regex: $0, wholeMatch: wholeMatch) })
}
}

Expand Down
13 changes: 7 additions & 6 deletions Sources/ViewInspector/Inspector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ internal extension Inspector {

private static func isSystemType(name: String) -> Bool {
return [
"SwiftUI[a-zA-Z0-9]{0,2}\\)?",
"_CoreLocationUI_SwiftUI", "_MapKit_SwiftUI",
"_AuthenticationServices_SwiftUI", "_AVKit_SwiftUI",
].contains(where: { name.hasPrefix(regex: $0 + "\\.") })
String.swiftUINamespaceRegex,
"_CoreLocationUI_SwiftUI\\.", "_MapKit_SwiftUI\\.",
"_AuthenticationServices_SwiftUI\\.", "_AVKit_SwiftUI\\.",
].containsPrefixRegex(matching: name, wholeMatch: false)
}

static func typeName(type: Any.Type,
Expand Down Expand Up @@ -284,10 +284,11 @@ internal extension Inspector {
""")
}
}
if namespacedPrefixes.contains(typePrefix) {
if namespacedPrefixes.containsPrefixRegex(matching: typePrefix) {
return
}
if let prefix = namespacedPrefixes.first {
if var prefix = namespacedPrefixes.first {
prefix = prefix.replacingOccurrences(of: String.swiftUINamespaceRegex, with: "SwiftUI.")
let typePrefix = typeName(type: type(of: value), namespaced: true)
throw InspectionError.typeMismatch(factual: typePrefix, expected: prefix)
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/ViewInspector/SwiftUI/Alert.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public extension ViewType {
public static var typePrefix: String = ViewType.PopupContainer<Alert>.typePrefix
static var typePrefixIOS15: String = "AlertModifier"
public static var namespacedPrefixes: [String] {
[typePrefix, "SwiftUI." + typePrefixIOS15]
[typePrefix, .swiftUINamespaceRegex + typePrefixIOS15]
}
public static func inspectionCall(typeName: String) -> String {
return "alert(\(ViewType.indexPlaceholder))"
Expand Down
18 changes: 9 additions & 9 deletions Sources/ViewInspector/SwiftUI/Gesture.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ public extension ViewType {

public static var namespacedPrefixes: [String] {
var prefixes = [
"SwiftUI.AddGestureModifier",
"SwiftUI.HighPriorityGestureModifier",
"SwiftUI.SimultaneousGestureModifier",
"SwiftUI._ChangedGesture",
"SwiftUI._EndedGesture",
"SwiftUI._MapGesture",
"SwiftUI._ModifiersGesture",
"SwiftUI.GestureStateGesture"
]
"AddGestureModifier",
"HighPriorityGestureModifier",
"SimultaneousGestureModifier",
"_ChangedGesture",
"_EndedGesture",
"_MapGesture",
"_ModifiersGesture",
"GestureStateGesture"
].map { String.swiftUINamespaceRegex + $0 }
prefixes.append(Inspector.typeName(type: T.self, namespaced: true, generics: .remove))
return prefixes
}
Expand Down
7 changes: 0 additions & 7 deletions Sources/ViewInspector/SwiftUI/Toolbar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,6 @@ public extension ViewType {
return "_ToolbarItemGroupModifier"
}
}()
public static var namespacedPrefixes: [String] {
#if os(tvOS)
return ["SwiftUI." + typePrefix, "SwiftUI1c)." + typePrefix]
#else
return ["SwiftUI." + typePrefix]
#endif
}
public static func inspectionCall(typeName: String) -> String {
return "toolbar(\(ViewType.indexPlaceholder))"
}
Expand Down
4 changes: 3 additions & 1 deletion Sources/ViewInspector/ViewSearchIndex.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ internal extension ViewSearch {
let fullName = Inspector.typeName(value: content.view, namespaced: true, generics: .remove)
if shortName.count > 0,
let identity = index[String(shortName.prefix(1))]?
.first(where: { $0.viewType.namespacedPrefixes.contains(fullName) }) {
.first(where: {
$0.viewType.namespacedPrefixes.containsPrefixRegex(matching: fullName)
}) {
return identity
}
if (try? content.extractCustomView()) != nil {
Expand Down

1 comment on commit 22a48ce

@Tyler-Keith-Thompson
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure this commit is responsible for a series of breaking changes for me. I'm working on creating a minimally reproducible example for you, I'll create an issue if I can.

I've had problems when views are nested in functions (used to work)

func testThing() {
    struct Screen1: View {
        var body: some View { Text("") }
    }
}

And I've had lots of problems with find. It seems to just completely ignore generic parameters, meaning all of the find calls are finding the first view that matches a type name ignoring the generic specialization entirely. So It keeps giving me the wrong view.

Please sign in to comment.