Skip to content

Commit

Permalink
Make identifier matching more resilient.
Browse files Browse the repository at this point in the history
  • Loading branch information
Matyáš Kříž committed Jun 23, 2024
1 parent c55ab47 commit 616e65d
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 106 deletions.
6 changes: 0 additions & 6 deletions Generator/Generator.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@
48205DE8188B258737270530 /* ModifierListSyntax+common.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4E1D009F8E0D6988EA56E9 /* ModifierListSyntax+common.swift */; };
483BE5542BFD109F00B202E0 /* Typealias.swift in Sources */ = {isa = PBXBuildFile; fileRef = 483BE5532BFD109F00B202E0 /* Typealias.swift */; };
483BE5552BFD109F00B202E0 /* Typealias.swift in Sources */ = {isa = PBXBuildFile; fileRef = 483BE5532BFD109F00B202E0 /* Typealias.swift */; };
483BE55D2C256C9F00B202E0 /* GeneralError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 483BE55C2C256C9F00B202E0 /* GeneralError.swift */; };
483BE55E2C256C9F00B202E0 /* GeneralError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 483BE55C2C256C9F00B202E0 /* GeneralError.swift */; };
4871C1D4211262913FE7E23A /* TOMLKit in Frameworks */ = {isa = PBXBuildFile; productRef = CF01AE9B482B793213C15803 /* TOMLKit */; };
4A04C8DABB34967D6D2EDB49 /* OrderedSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F1F3CD491EFD856B4C96AC7 /* OrderedSet.swift */; };
4A2BFBD3DA28E395A3D05946 /* Attribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B8A800560013CEEAC82BDD3 /* Attribute.swift */; };
Expand Down Expand Up @@ -184,7 +182,6 @@
32D7CD1899844A58C727A50D /* GeneratorHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneratorHelper.swift; sourceTree = "<group>"; };
41C5C09640B2E1C7C8FB4CD7 /* HasName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HasName.swift; sourceTree = "<group>"; };
483BE5532BFD109F00B202E0 /* Typealias.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Typealias.swift; sourceTree = "<group>"; };
483BE55C2C256C9F00B202E0 /* GeneralError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralError.swift; sourceTree = "<group>"; };
4F1F3CD491EFD856B4C96AC7 /* OrderedSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderedSet.swift; sourceTree = "<group>"; };
50316F84EA0A5C89C1ED8932 /* cuckoonator */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = text; path = cuckoonator; sourceTree = BUILT_PRODUCTS_DIR; };
50E0C10D6BFAE96A0A700D06 /* FileRepresentation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileRepresentation.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -399,7 +396,6 @@
61D4E2D59CBA725E92818DF5 /* String+convenience.swift */,
DD008EFA376A4341CD91C7C3 /* SwiftSyntax+convenience.swift */,
5A484A998FE2183BF6ADAA94 /* Utils.swift */,
483BE55C2C256C9F00B202E0 /* GeneralError.swift */,
);
path = Helpers;
sourceTree = "<group>";
Expand Down Expand Up @@ -586,7 +582,6 @@
89D8E6E0BB802AAC86092BD6 /* ContainerTemplate.swift in Sources */,
5CA71A4AF5B2FEDD41396FCA /* MockTemplate.swift in Sources */,
0590D5E1059A7678C601109F /* NopImplStubTemplate.swift in Sources */,
483BE55E2C256C9F00B202E0 /* GeneralError.swift in Sources */,
FE1CA1D2D68ECCD53D48698E /* StubbingProxyTemplate.swift in Sources */,
CA3FB4772D2F62F20750E9AC /* Templates.swift in Sources */,
95A6440D0CAFC15C1B956397 /* TypeErasureTemplate.swift in Sources */,
Expand Down Expand Up @@ -676,7 +671,6 @@
2AE7D1FED2533686F9BCA0AE /* Inheritable.swift in Sources */,
88DC61F066E5D5A5C0BB3317 /* Initializer.swift in Sources */,
17A2954EF62AC448248369BC /* Method.swift in Sources */,
483BE55D2C256C9F00B202E0 /* GeneralError.swift in Sources */,
A863F7D5DA2F1E539178451B /* MethodParameter.swift in Sources */,
6B9EA70876BE120C8290ED7E /* MethodSignature.swift in Sources */,
CB65B046EAB308A744FFF63F /* NamespaceDeclaration.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1010"
version = "1.3">
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
Expand Down Expand Up @@ -86,7 +86,7 @@
</CommandLineArgument>
<CommandLineArgument
argument = "--verbose"
isEnabled = "YES">
isEnabled = "NO">
</CommandLineArgument>
</CommandLineArguments>
<EnvironmentVariables>
Expand Down
92 changes: 37 additions & 55 deletions Generator/Sources/Internal/Crawlers/Crawler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ final class Crawler: SyntaxVisitor {
parent: container,
attributes: attributes(from: node.attributes),
accessibility: accessibility(from: node.modifiers) ?? (container as? HasAccessibility)?.accessibility ?? .internal,
name: node.name.trimmed.description,
name: node.name.filteredDescription,
genericParameters: genericParameters(from: node.genericParameterClause?.parameters),
genericRequirements: genericRequirements(from: node.genericWhereClause?.requirements),
inheritedTypes: inheritedTypes(from: node.inheritanceClause?.inheritedTypes),
Expand All @@ -75,7 +75,7 @@ final class Crawler: SyntaxVisitor {
parent: container,
attributes: attributes(from: node.attributes),
accessibility: accessibility(from: node.modifiers) ?? (container as? HasAccessibility)?.accessibility ?? .internal,
name: node.name.trimmed.description,
name: node.name.filteredDescription,
genericParameters: (genericParameters(from: node.primaryAssociatedTypeClause?.primaryAssociatedTypes) + associatedTypes(from: node.memberBlock.members)).merged(),
genericRequirements: genericRequirements(from: node.genericWhereClause?.requirements),
inheritedTypes: inheritedTypes,
Expand All @@ -98,7 +98,7 @@ final class Crawler: SyntaxVisitor {
parent: container,
attributes: attributes(from: node.attributes),
accessibility: accessibility(from: node.modifiers) ?? (container as? HasAccessibility)?.accessibility ?? .internal,
name: node.name.trimmed.description,
name: node.name.filteredDescription,
members: []
)

Expand All @@ -118,7 +118,7 @@ final class Crawler: SyntaxVisitor {
parent: container,
attributes: attributes(from: node.attributes),
accessibility: accessibility(from: node.modifiers) ?? (container as? HasAccessibility)?.accessibility ?? .internal,
name: node.extendedType.trimmed.description,
name: node.extendedType.filteredDescription,
members: []
)

Expand All @@ -138,7 +138,7 @@ final class Crawler: SyntaxVisitor {
parent: container,
attributes: attributes(from: node.attributes),
accessibility: accessibility(from: node.modifiers) ?? (container as? HasAccessibility)?.accessibility ?? .internal,
name: node.name.trimmed.description,
name: node.name.filteredDescription,
members: []
)

Expand Down Expand Up @@ -182,11 +182,7 @@ final class Crawler: SyntaxVisitor {
}

override func visit(_ node: TypeAliasDeclSyntax) -> SyntaxVisitorContinueKind {
do {
try tokens.append(Typealias(syntax: node))
} catch {
log(.error, message: "Error \(url.path):\n\tCan't parse typealias '\(node.trimmedDescription)'.")
}
tokens.append(Typealias(syntax: node))
return .skipChildren
}

Expand All @@ -200,17 +196,17 @@ final class Crawler: SyntaxVisitor {
let description: String
switch node {
case let node as ClassDeclSyntax:
description = "class \(node.name.trimmed.description)"
description = "class \(node.name.filteredDescription)"
case let node as ProtocolDeclSyntax:
description = "protocol \(node.name.trimmed.description)"
description = "protocol \(node.name.filteredDescription)"
case let node as StructDeclSyntax:
description = "struct \(node.name.trimmed.description)"
description = "struct \(node.name.filteredDescription)"
case let node as ExtensionDeclSyntax:
description = "extension \(node.extendedType.trimmed.description)"
description = "extension \(node.extendedType.filteredDescription)"
case let node as EnumDeclSyntax:
description = "enum \(node.name.trimmed.description)"
description = "enum \(node.name.filteredDescription)"
default:
description = "Unknown declaration \(node.trimmed.description)"
description = "Unknown declaration \(node.filteredDescription)"
}

log(
Expand Down Expand Up @@ -273,13 +269,8 @@ extension Crawler {

let type: ComplexType
if let explicitType = binding.typeAnnotation?.type {
do {
type = try ComplexType(syntax: explicitType)
} catch {
log(.error, message: "Error \(url.path):\n\tCan't parse explicit type '\(explicitType.trimmedDescription)'.")
return nil
}
} else if let initializer = binding.initializer?.value.trimmed.description, let guessedType = TypeGuesser.guessType(from: initializer) {
type = ComplexType(syntax: explicitType)
} else if let initializer = binding.initializer?.value.filteredDescription, let guessedType = TypeGuesser.guessType(from: initializer) {
type = .type(guessedType)
} else {
fatalError("Can't infer type of property '\(identifier)' in file \(url)")
Expand Down Expand Up @@ -327,13 +318,7 @@ extension Crawler {

guard accessibility.isAccessible else { return nil }

let parameters: [MethodParameter]
do {
parameters = try self.parameters(from: initializer.signature.parameterClause.parameters)
} catch {
log(.error, message: "Error \(url.path):\n\tCan't parse method parameters '\(initializer.signature.parameterClause.parameters.trimmedDescription)'.")
return nil
}
let parameters = self.parameters(from: initializer.signature.parameterClause.parameters)

return Initializer(
parent: container,
Expand All @@ -344,7 +329,7 @@ extension Crawler {
genericParameters: genericParameters(from: initializer.genericParameterClause?.parameters),
parameters: parameters,
asyncType: nil,
throwType: initializer.signature.effectSpecifiers?.throwsSpecifier.flatMap { ThrowType(rawValue: $0.trimmed.description) },
throwType: initializer.signature.effectSpecifiers?.throwsSpecifier.flatMap { ThrowType(rawValue: $0.filteredDescription) },
returnType: nil,
whereConstraints: genericRequirements(from: initializer.genericWhereClause?.requirements)
),
Expand All @@ -366,21 +351,8 @@ extension Crawler {

guard accessibility.isAccessible else { return nil }

let parameters: [MethodParameter]
do {
parameters = try self.parameters(from: method.signature.parameterClause.parameters)
} catch {
log(.error, message: "Error \(url.path):\n\tCan't parse method parameters '\(method.signature.parameterClause.parameters.trimmedDescription)'.")
return nil
}

let returnType: ComplexType?
do {
returnType = try method.signature.returnClause.flatMap { try ComplexType(syntax: $0.type) }
} catch {
log(.error, message: "Error \(url.path):\n\tCan't parse return type '\(method.signature.returnClause?.type.trimmedDescription ?? "")'.")
return nil
}
let parameters = self.parameters(from: method.signature.parameterClause.parameters)
let returnType = method.signature.returnClause.flatMap { ComplexType(syntax: $0.type) }

return Method(
parent: container,
Expand All @@ -391,8 +363,8 @@ extension Crawler {
signature: Method.Signature(
genericParameters: genericParameters(from: method.genericParameterClause?.parameters),
parameters: parameters,
asyncType: method.signature.effectSpecifiers?.asyncSpecifier.flatMap { AsyncType(rawValue: $0.trimmed.description) },
throwType: method.signature.effectSpecifiers?.throwsSpecifier.flatMap { ThrowType(rawValue: $0.trimmed.description) },
asyncType: method.signature.effectSpecifiers?.asyncSpecifier.flatMap { AsyncType(rawValue: $0.filteredDescription) },
throwType: method.signature.effectSpecifiers?.throwsSpecifier.flatMap { ThrowType(rawValue: $0.filteredDescription) },
returnType: returnType ?? ComplexType.type("Void"),
whereConstraints: genericRequirements(from: method.genericWhereClause?.requirements)
),
Expand All @@ -402,12 +374,12 @@ extension Crawler {
}

extension Crawler {
private func parameters(from parameterList: FunctionParameterListSyntax) throws -> [MethodParameter] {
try parameterList.map { parameter in
private func parameters(from parameterList: FunctionParameterListSyntax) -> [MethodParameter] {
parameterList.map { parameter in
MethodParameter(
name: parameter.firstName.trimmed.description,
name: parameter.firstName.filteredDescription,
innerName: nil,
type: try ComplexType(syntax: parameter.type)
type: ComplexType(syntax: parameter.type)
)
}
}
Expand Down Expand Up @@ -473,7 +445,7 @@ extension Crawler {
private func genericParameters(from genericParameterList: GenericParameterListSyntax?) -> [GenericParameter] {
genericParameterList?.map { genericParameter in
GenericParameter(
name: try! genericParameter.name.identifier,
name: genericParameter.name.filteredDescription,
inheritedTypes: inheritedTypes(from: genericParameter.inheritedType?.trimmed)
)
} ?? []
Expand Down Expand Up @@ -501,7 +473,7 @@ extension Crawler {
}

private func genericRequirements(from genericRequirementList: GenericRequirementListSyntax?) -> [String] {
genericRequirementList?.map { $0.requirement.trimmed.description } ?? []
genericRequirementList?.map { $0.requirement.filteredDescription } ?? []
}

private func inheritedTypes(from inheritedTypesList: InheritedTypeListSyntax?) -> [String] {
Expand All @@ -524,6 +496,14 @@ extension Crawler {
extension Crawler {
private static let testString =
"""
public struct Prefs {}
public extension Prefs {
enum Key: String {
case blabla
}
}
// DUDE
@objcMembers
class Multi {
Expand All @@ -543,7 +523,9 @@ class Multi {
var gg: Dictionary<Int, String>
var ggwp: Array<String>
func generico<G: APIManager.GraphQLSomething>(plek: inout Gaga) {}
func gg(_ value: Any?, forKey: Prefs.Key) -> Jedna.Dva {}
func generico<G: APIManager.GraphQLSomething>(plek: inout Enum.Gaga) {}
func compositionalParameters(param1: any Equatable & Numeric, param2: OnlyLabelProtocol & Codable)
Expand Down
5 changes: 0 additions & 5 deletions Generator/Sources/Internal/Helpers/GeneralError.swift

This file was deleted.

28 changes: 3 additions & 25 deletions Generator/Sources/Internal/Helpers/SwiftSyntax+convenience.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,30 +24,8 @@ extension ExprSyntaxProtocol {
}
}

extension TokenSyntax {
var identifier: String {
get throws {
try tokenKind.identifier
}
}
}

extension IdentifierTypeSyntax {
var identifier: String {
get throws {
try name.tokenKind.identifier
}
}
}

extension TokenKind {
var identifier: String {
get throws {
if case .identifier(let identifier) = self {
return identifier
} else {
throw GeneralError.identifierParseFailed
}
}
extension SyntaxProtocol {
var filteredDescription: String {
trimmedDescription.replacingOccurrences(of: "\n", with: " ")
}
}
22 changes: 11 additions & 11 deletions Generator/Sources/Internal/Tokens/ComplexType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,49 +9,49 @@ enum ComplexType {
case closure(Closure)
case type(String)

init(syntax: TypeSyntax) throws {
init(syntax: TypeSyntax) {
if let implicitOptionalType = syntax.as(ImplicitlyUnwrappedOptionalTypeSyntax.self) {
self = .optional(wrappedType: try ComplexType(syntax: implicitOptionalType.wrappedType), isImplicit: true)
self = .optional(wrappedType: ComplexType(syntax: implicitOptionalType.wrappedType), isImplicit: true)
} else if let optionalType = syntax.as(OptionalTypeSyntax.self) {
self = .optional(wrappedType: try ComplexType(syntax: optionalType.wrappedType), isImplicit: false)
self = .optional(wrappedType: ComplexType(syntax: optionalType.wrappedType), isImplicit: false)
} else if let attributedType = syntax.as(AttributedTypeSyntax.self) {
self = .attributed(
attributes: [
attributedType.attributes.map { $0.trimmedDescription },
attributedType.specifier.map { [$0.trimmedDescription] } ?? [],
].flatMap { $0 },
baseType: try ComplexType(syntax: attributedType.baseType)
baseType: ComplexType(syntax: attributedType.baseType)
)
} else if let functionType = syntax.as(FunctionTypeSyntax.self) {
self = .closure(
Closure(
parameters: try functionType.parameters.map {
parameters: functionType.parameters.map {
Closure.Parameter(
label: $0.secondName?.trimmedDescription,
type: try ComplexType(syntax: $0.type)
type: ComplexType(syntax: $0.type)
)
},
effects: Closure.Effects(effectSpecifiers: functionType.effectSpecifiers),
returnType: try ComplexType(syntax: functionType.returnClause.type)
returnType: ComplexType(syntax: functionType.returnClause.type)
)
)
} else if let identifierType = syntax.as(IdentifierTypeSyntax.self) {
switch try identifierType.identifier {
switch identifierType.filteredDescription {
case "Dictionary":
let arguments = identifierType.genericArgumentClause?.arguments
guard let keyType = arguments?.first?.argument, let valueType = arguments?.last?.argument else {
fatalError("Cuckoo error: Failed to get Dictionary type, please open an issue.")
}
self = .dictionary(
keyType: try ComplexType(syntax: keyType),
valueType: try ComplexType(syntax: valueType)
keyType: ComplexType(syntax: keyType),
valueType: ComplexType(syntax: valueType)
)
case "Array":
let arguments = identifierType.genericArgumentClause?.arguments
guard let elementType = arguments?.first?.argument else {
fatalError("Cuckoo error: Failed to get Array type, please open an issue.")
}
self = .array(elementType: try ComplexType(syntax: elementType))
self = .array(elementType: ComplexType(syntax: elementType))
default:
self = .type(syntax.trimmedDescription)
}
Expand Down
4 changes: 2 additions & 2 deletions Generator/Sources/Internal/Tokens/Typealias.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ struct Typealias: Token, CustomStringConvertible {
}

extension Typealias {
init(syntax: TypeAliasDeclSyntax) throws {
init(syntax: TypeAliasDeclSyntax) {
self.init(
alias: [
try syntax.name.identifier,
syntax.name.filteredDescription,
syntax.genericParameterClause?.trimmedDescription
]
.compactMap { $0 }
Expand Down
2 changes: 2 additions & 0 deletions Tests/Swift/Source/TestedClass.swift
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ class TestedClass {
}

func genericTypealiasMethod(typealias: GenericTypealias<String>) {}

func keywordTypeParameters(any: Any) {}
}

private class ThisClassShouldNotBeMocked1 {
Expand Down

0 comments on commit 616e65d

Please sign in to comment.