From 65f72bcf5531bb62c94ce2298cacfbb8e69c4eab Mon Sep 17 00:00:00 2001 From: uabyss Date: Mon, 15 Jul 2024 21:41:53 +0900 Subject: [PATCH 01/19] fix: void_function_in_ternary incorrectly triggered with if statement --- .../VoidFunctionInTernaryConditionRule.swift | 49 ++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift index 8d6cc648c5..d9e3e232f8 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift @@ -60,6 +60,28 @@ struct VoidFunctionInTernaryConditionRule: Rule { subscript(index: Int) -> Int { index == 0 ? defaultValue() : compute(index) """), + Example(""" + func example() -> String { + if true { + isTrue ? defaultValue() : defaultValue() + } else { + "Default" + } + } + """).focused(), + Example(""" + func exampleNestedIfExpr() -> String { + if true { + if true { + if true { + isTrue ? defaultValue() : defaultValue() + } + } + } else { + "Default" + } + } + """).focused(), ], triggeringExamples: [ Example("success ↓? askQuestion() : exit()"), @@ -152,7 +174,7 @@ private extension CodeBlockItemSyntax { var isImplicitReturn: Bool { isClosureImplictReturn || isFunctionImplicitReturn || isVariableImplicitReturn || isSubscriptImplicitReturn || - isAcessorImplicitReturn + isAcessorImplicitReturn || isIfExprImplicitReturn } var isClosureImplictReturn: Bool { @@ -199,6 +221,17 @@ private extension CodeBlockItemSyntax { return parent.children(viewMode: .sourceAccurate).count == 1 } + + var isIfExprImplicitReturn: Bool { + guard let parent = parent?.as(CodeBlockItemListSyntax.self), + let ifExprSytax = parent.parent?.parent?.as(IfExprSyntax.self) else { + return false + } + guard let funcDecl = ifExprSytax.parent?.findParent(ofType: FunctionDeclSyntax.self) else { + return false + } + return parent.children(viewMode: .sourceAccurate).count == 1 && funcDecl.signature.allowsImplicitReturns + } } private extension FunctionSignatureSyntax { @@ -224,3 +257,17 @@ private extension ReturnClauseSyntax { return true } } + +// Helper method that traces back the parent until a particular node reaches FunctionDeclSyntax. +extension Syntax { + func findParent(ofType type: T.Type) -> T? { + var current: Syntax? = self + while let parent = current?.parent { + if let parentNode = parent.as(T.self) { + return parentNode + } + current = parent + } + return nil + } +} From 0ca536ba261f8817e8dfcf8a6e3845547d1b238b Mon Sep 17 00:00:00 2001 From: uabyss Date: Mon, 15 Jul 2024 21:45:46 +0900 Subject: [PATCH 02/19] fix: test cases --- .../VoidFunctionInTernaryConditionRule.swift | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift index d9e3e232f8..c759fa9645 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift @@ -68,7 +68,7 @@ struct VoidFunctionInTernaryConditionRule: Rule { "Default" } } - """).focused(), + """), Example(""" func exampleNestedIfExpr() -> String { if true { @@ -81,7 +81,7 @@ struct VoidFunctionInTernaryConditionRule: Rule { "Default" } } - """).focused(), + """), ], triggeringExamples: [ Example("success ↓? askQuestion() : exit()"), @@ -126,6 +126,15 @@ struct VoidFunctionInTernaryConditionRule: Rule { return index } """), + Example(""" + func example() -> Void { + if true { + isTrue ↓? defaultValue() : defaultValue() + } else { + print("false") + } + } + """), ] ) } From f439ad2040ed3825d25864c5ccf7acdd4a3c715d Mon Sep 17 00:00:00 2001 From: uabyss Date: Mon, 15 Jul 2024 22:03:34 +0900 Subject: [PATCH 03/19] fix: IntegrationTests --- .../Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift index c759fa9645..fdc76a0087 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift @@ -268,8 +268,8 @@ private extension ReturnClauseSyntax { } // Helper method that traces back the parent until a particular node reaches FunctionDeclSyntax. -extension Syntax { - func findParent(ofType type: T.Type) -> T? { +private extension Syntax { + func findParent(ofType _: T.Type) -> T? { var current: Syntax? = self while let parent = current?.parent { if let parentNode = parent.as(T.self) { From 65d7eac80c81ee19e70d5146d46f1c3448e97338 Mon Sep 17 00:00:00 2001 From: uabyss Date: Thu, 18 Jul 2024 17:04:21 +0900 Subject: [PATCH 04/19] update --- .../VoidFunctionInTernaryConditionRule.swift | 64 ++++++++++++------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift index fdc76a0087..c4997c57f3 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift @@ -72,16 +72,20 @@ struct VoidFunctionInTernaryConditionRule: Rule { Example(""" func exampleNestedIfExpr() -> String { if true { - if true { - if true { - isTrue ? defaultValue() : defaultValue() - } - } + isTrue ? defaultValue() : defaultValue() } else { "Default" } } """), + Example(""" + func collectionView() -> CGSize { + switch indexPath.section { + case 0: isEditing ? CGSize(width: 150, height: 20) : CGSize(width: 100, height: 20) + default: .zero + } + } + """), ], triggeringExamples: [ Example("success ↓? askQuestion() : exit()"), @@ -135,6 +139,25 @@ struct VoidFunctionInTernaryConditionRule: Rule { } } """), + Example(""" + func exampleNestedIfExpr() -> String { + if true { + isTrue ↓? defaultValue() : defaultValue() + } else { + "Default" + } + return hoge + } + """), + Example(""" + func collectionView() -> CGSize { + switch indexPath.section { + case 0: isEditing ↓? CGSize(width: 150, height: 20) : CGSize(width: 100, height: 20) + default: .zero + } + return hoge + } + """), ] ) } @@ -183,7 +206,7 @@ private extension CodeBlockItemSyntax { var isImplicitReturn: Bool { isClosureImplictReturn || isFunctionImplicitReturn || isVariableImplicitReturn || isSubscriptImplicitReturn || - isAcessorImplicitReturn || isIfExprImplicitReturn + isAcessorImplicitReturn || isIfExprImplicitReturn || isSwitchExprImplicitReturn } var isClosureImplictReturn: Bool { @@ -236,10 +259,21 @@ private extension CodeBlockItemSyntax { let ifExprSytax = parent.parent?.parent?.as(IfExprSyntax.self) else { return false } - guard let funcDecl = ifExprSytax.parent?.findParent(ofType: FunctionDeclSyntax.self) else { + guard let funcDecl = ifExprSytax.parent?.parent?.parent?.parent?.parent?.as(FunctionDeclSyntax.self) else { + return false + } + return parent.children(viewMode: .sourceAccurate).count == 1 && funcDecl.signature.allowsImplicitReturns && ifExprSytax.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self)?.count == 1 + } + + var isSwitchExprImplicitReturn: Bool { + guard let parent = parent?.as(CodeBlockItemListSyntax.self), + let switchExprSytax = parent.parent?.parent?.parent?.as(SwitchExprSyntax.self) else { + return false + } + guard let funcDecl = switchExprSytax.parent?.parent?.parent?.parent?.parent?.as(FunctionDeclSyntax.self) else { return false } - return parent.children(viewMode: .sourceAccurate).count == 1 && funcDecl.signature.allowsImplicitReturns + return parent.children(viewMode: .sourceAccurate).count == 1 && funcDecl.signature.allowsImplicitReturns && switchExprSytax.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self)?.count == 1 } } @@ -266,17 +300,3 @@ private extension ReturnClauseSyntax { return true } } - -// Helper method that traces back the parent until a particular node reaches FunctionDeclSyntax. -private extension Syntax { - func findParent(ofType _: T.Type) -> T? { - var current: Syntax? = self - while let parent = current?.parent { - if let parentNode = parent.as(T.self) { - return parentNode - } - current = parent - } - return nil - } -} From 29b49ceb7f32932a0a802fc938c72d29d0cc833d Mon Sep 17 00:00:00 2001 From: uabyss Date: Sun, 28 Jul 2024 22:02:16 +0900 Subject: [PATCH 05/19] fix: isIfExprImplicitReturn --- .../VoidFunctionInTernaryConditionRule.swift | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift index c4997c57f3..fd0b2b9bd5 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift @@ -79,6 +79,16 @@ struct VoidFunctionInTernaryConditionRule: Rule { } """), Example(""" + func exampleNestedIfExpr() -> String { + test() + if true { + isTrue ? defaultValue() : defaultValue() + } else { + "Default" + } + } + """), + Example(""" func collectionView() -> CGSize { switch indexPath.section { case 0: isEditing ? CGSize(width: 150, height: 20) : CGSize(width: 100, height: 20) @@ -262,7 +272,12 @@ private extension CodeBlockItemSyntax { guard let funcDecl = ifExprSytax.parent?.parent?.parent?.parent?.parent?.as(FunctionDeclSyntax.self) else { return false } - return parent.children(viewMode: .sourceAccurate).count == 1 && funcDecl.signature.allowsImplicitReturns && ifExprSytax.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self)?.count == 1 + if let codeBlockItemListSyntax = ifExprSytax.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self), + let expressionStmtSyntax = codeBlockItemListSyntax.last?.item.as(ExpressionStmtSyntax.self) + { + return parent.children(viewMode: .sourceAccurate).count == 1 && ( codeBlockItemListSyntax.count == 1 || expressionStmtSyntax.expression.is(IfExprSyntax.self)) && funcDecl.signature.allowsImplicitReturns + } + return false } var isSwitchExprImplicitReturn: Bool { From e810d7074f8e48aa51d413daa117ac26a79f665e Mon Sep 17 00:00:00 2001 From: uabyss Date: Sun, 28 Jul 2024 23:25:03 +0900 Subject: [PATCH 06/19] fix: test --- .../VoidFunctionInTernaryConditionRule.swift | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift index fd0b2b9bd5..5d5beef0b9 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift @@ -273,9 +273,10 @@ private extension CodeBlockItemSyntax { return false } if let codeBlockItemListSyntax = ifExprSytax.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self), - let expressionStmtSyntax = codeBlockItemListSyntax.last?.item.as(ExpressionStmtSyntax.self) - { - return parent.children(viewMode: .sourceAccurate).count == 1 && ( codeBlockItemListSyntax.count == 1 || expressionStmtSyntax.expression.is(IfExprSyntax.self)) && funcDecl.signature.allowsImplicitReturns + let expressionStmtSyntax = codeBlockItemListSyntax.last?.item.as(ExpressionStmtSyntax.self) { + return parent.children(viewMode: .sourceAccurate).count == 1 && + ( codeBlockItemListSyntax.count == 1 || expressionStmtSyntax.expression.is(IfExprSyntax.self)) && + funcDecl.signature.allowsImplicitReturns } return false } @@ -288,7 +289,9 @@ private extension CodeBlockItemSyntax { guard let funcDecl = switchExprSytax.parent?.parent?.parent?.parent?.parent?.as(FunctionDeclSyntax.self) else { return false } - return parent.children(viewMode: .sourceAccurate).count == 1 && funcDecl.signature.allowsImplicitReturns && switchExprSytax.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self)?.count == 1 + return parent.children(viewMode: .sourceAccurate).count == 1 && + funcDecl.signature.allowsImplicitReturns && + switchExprSytax.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self)?.count == 1 } } From cbf755c87343e145ed9b98c4caf8b85dc2a5b397 Mon Sep 17 00:00:00 2001 From: uabyss Date: Thu, 12 Sep 2024 17:06:07 +0900 Subject: [PATCH 07/19] add: recursive function to find FunctionDeclSyntax --- .../VoidFunctionInTernaryConditionRule.swift | 47 +++++++++++++++---- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift index 5d5beef0b9..1bbac469a7 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift @@ -168,6 +168,20 @@ struct VoidFunctionInTernaryConditionRule: Rule { return hoge } """), + Example(""" + func exampleNestedIfExpr() -> String { + if true { + if true { + isTrue ↓? defaultValue() : defaultValue() + } else { + return "False" + } + } else { + return "Default" + } + return hoge + } + """), ] ) } @@ -263,20 +277,35 @@ private extension CodeBlockItemSyntax { return parent.children(viewMode: .sourceAccurate).count == 1 } - - var isIfExprImplicitReturn: Bool { - guard let parent = parent?.as(CodeBlockItemListSyntax.self), - let ifExprSytax = parent.parent?.parent?.as(IfExprSyntax.self) else { - return false + + func getFunctionDeclSyntax(parent: CodeBlockItemListSyntax) -> FunctionDeclSyntax? { + let targetSyntax = parent.parent?.parent + if let targetSyntax = targetSyntax?.as(FunctionDeclSyntax.self) { + return targetSyntax + } + if let ifExprSyntax = targetSyntax?.as(IfExprSyntax.self) { + guard let codeBlockItemListSyntax = ifExprSyntax.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self) else { + return nil } - guard let funcDecl = ifExprSytax.parent?.parent?.parent?.parent?.parent?.as(FunctionDeclSyntax.self) else { - return false + return getFunctionDeclSyntax(parent: codeBlockItemListSyntax) + } + if let swichExprSyntax = targetSyntax?.parent?.as(SwitchExprSyntax.self) { + guard let codeBlockItemListSyntax = swichExprSyntax.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self) else { + return nil } - if let codeBlockItemListSyntax = ifExprSytax.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self), + return getFunctionDeclSyntax(parent: codeBlockItemListSyntax) + } + return nil + } + + var isIfExprImplicitReturn: Bool { + guard let parent = parent?.as(CodeBlockItemListSyntax.self) else { return false } + guard let result = getFunctionDeclSyntax(parent: parent) else { return false } + if let codeBlockItemListSyntax = result.body?.statements, let expressionStmtSyntax = codeBlockItemListSyntax.last?.item.as(ExpressionStmtSyntax.self) { return parent.children(viewMode: .sourceAccurate).count == 1 && ( codeBlockItemListSyntax.count == 1 || expressionStmtSyntax.expression.is(IfExprSyntax.self)) && - funcDecl.signature.allowsImplicitReturns + result.signature.allowsImplicitReturns } return false } From c16a7c0cdd8c40ad9f49f933875906326af1b340 Mon Sep 17 00:00:00 2001 From: uabyss Date: Thu, 12 Sep 2024 17:48:05 +0900 Subject: [PATCH 08/19] fix: test error --- .../VoidFunctionInTernaryConditionRule.swift | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift index 1bbac469a7..cff58af583 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift @@ -277,26 +277,26 @@ private extension CodeBlockItemSyntax { return parent.children(viewMode: .sourceAccurate).count == 1 } - - func getFunctionDeclSyntax(parent: CodeBlockItemListSyntax) -> FunctionDeclSyntax? { - let targetSyntax = parent.parent?.parent - if let targetSyntax = targetSyntax?.as(FunctionDeclSyntax.self) { - return targetSyntax - } - if let ifExprSyntax = targetSyntax?.as(IfExprSyntax.self) { - guard let codeBlockItemListSyntax = ifExprSyntax.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self) else { - return nil + + func getFunctionDeclSyntax(parent: CodeBlockItemListSyntax) -> FunctionDeclSyntax? { + let targetSyntax = parent.parent?.parent + if let targetSyntax = targetSyntax?.as(FunctionDeclSyntax.self) { + return targetSyntax } - return getFunctionDeclSyntax(parent: codeBlockItemListSyntax) - } - if let swichExprSyntax = targetSyntax?.parent?.as(SwitchExprSyntax.self) { - guard let codeBlockItemListSyntax = swichExprSyntax.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self) else { - return nil + if let ifExprSyntax = targetSyntax?.as(IfExprSyntax.self) { + guard let codeBlockItemListSyntax = ifExprSyntax.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self) else { + return nil + } + return getFunctionDeclSyntax(parent: codeBlockItemListSyntax) + } + if let switchExpr = targetSyntax?.parent?.as(SwitchExprSyntax.self) { + guard let codeBlockItemListSyntax = switchExpr.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self) else { + return nil + } + return getFunctionDeclSyntax(parent: codeBlockItemListSyntax) } - return getFunctionDeclSyntax(parent: codeBlockItemListSyntax) + return nil } - return nil - } var isIfExprImplicitReturn: Bool { guard let parent = parent?.as(CodeBlockItemListSyntax.self) else { return false } From cc6fc9db7fdf583f0c9f38025ac8d76550c68cd0 Mon Sep 17 00:00:00 2001 From: uabyss Date: Thu, 19 Sep 2024 22:25:02 +0900 Subject: [PATCH 09/19] refactor --- .../VoidFunctionInTernaryConditionRule.swift | 111 ++++++++++++------ 1 file changed, 73 insertions(+), 38 deletions(-) diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift index cff58af583..f256f1bf5d 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift @@ -63,18 +63,18 @@ struct VoidFunctionInTernaryConditionRule: Rule { Example(""" func example() -> String { if true { - isTrue ? defaultValue() : defaultValue() + return isTrue ? defaultValue() : defaultValue() } else { - "Default" + return "Default" } } """), Example(""" func exampleNestedIfExpr() -> String { if true { - isTrue ? defaultValue() : defaultValue() + return isTrue ? defaultValue() : defaultValue() } else { - "Default" + return "Default" } } """), @@ -82,20 +82,44 @@ struct VoidFunctionInTernaryConditionRule: Rule { func exampleNestedIfExpr() -> String { test() if true { - isTrue ? defaultValue() : defaultValue() + return isTrue ? defaultValue() : defaultValue() } else { - "Default" + return "Default" } } """), Example(""" func collectionView() -> CGSize { switch indexPath.section { - case 0: isEditing ? CGSize(width: 150, height: 20) : CGSize(width: 100, height: 20) + case 0: return isEditing ? CGSize(width: 150, height: 20) : CGSize(width: 100, height: 20) default: .zero } } """), + Example(""" + func exampleFunction() -> String { + if true { + switch value { + case 1: + if flag { + return isTrue ? "1" : "2" + } else { + return "3" + } + case 2: + if true { + return "4" + } else { + return "5" + } + default: + return "6" + } + } else { + return "7" + } + } + """) ], triggeringExamples: [ Example("success ↓? askQuestion() : exit()"), @@ -154,7 +178,7 @@ struct VoidFunctionInTernaryConditionRule: Rule { if true { isTrue ↓? defaultValue() : defaultValue() } else { - "Default" + "Default" } return hoge } @@ -182,6 +206,31 @@ struct VoidFunctionInTernaryConditionRule: Rule { return hoge } """), + Example(""" + func exampleFunction() -> String { + if true { + switch value { + case 1: + if flag { + isTrue ↓? print("hoge") : print("hoge") + return "3" + } else { + return "3" + } + case 2: + if true { + return "4" + } else { + return "5" + } + default: + return "6" + } + } else { + return "7" + } + } + """) ] ) } @@ -230,7 +279,7 @@ private extension CodeBlockItemSyntax { var isImplicitReturn: Bool { isClosureImplictReturn || isFunctionImplicitReturn || isVariableImplicitReturn || isSubscriptImplicitReturn || - isAcessorImplicitReturn || isIfExprImplicitReturn || isSwitchExprImplicitReturn + isAcessorImplicitReturn || isIfOrSwitchExprImplicitReturn } var isClosureImplictReturn: Bool { @@ -278,49 +327,35 @@ private extension CodeBlockItemSyntax { return parent.children(viewMode: .sourceAccurate).count == 1 } - func getFunctionDeclSyntax(parent: CodeBlockItemListSyntax) -> FunctionDeclSyntax? { - let targetSyntax = parent.parent?.parent + // Recursively traverse the codeBlockItem to determine if it is a FunctionDeclSyntax + func getFunctionDeclSyntax(codeBlockItem: CodeBlockItemSyntax) -> FunctionDeclSyntax? { + let targetSyntax = codeBlockItem.parent?.parent?.parent?.parent if let targetSyntax = targetSyntax?.as(FunctionDeclSyntax.self) { return targetSyntax } if let ifExprSyntax = targetSyntax?.as(IfExprSyntax.self) { - guard let codeBlockItemListSyntax = ifExprSyntax.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self) else { + if ifExprSyntax.body.statements.last != codeBlockItem { + return nil + } + guard let codeBlockItemSyntax = ifExprSyntax.parent?.parent?.as(CodeBlockItemSyntax.self) else { return nil } - return getFunctionDeclSyntax(parent: codeBlockItemListSyntax) + return getFunctionDeclSyntax(codeBlockItem: codeBlockItemSyntax) } + if let switchExpr = targetSyntax?.parent?.as(SwitchExprSyntax.self) { - guard let codeBlockItemListSyntax = switchExpr.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self) else { + guard let codeBlockItemSyntax = switchExpr.parent?.parent?.as(CodeBlockItemSyntax.self) else { return nil } - return getFunctionDeclSyntax(parent: codeBlockItemListSyntax) + return getFunctionDeclSyntax(codeBlockItem: codeBlockItemSyntax) } - return nil - } - var isIfExprImplicitReturn: Bool { - guard let parent = parent?.as(CodeBlockItemListSyntax.self) else { return false } - guard let result = getFunctionDeclSyntax(parent: parent) else { return false } - if let codeBlockItemListSyntax = result.body?.statements, - let expressionStmtSyntax = codeBlockItemListSyntax.last?.item.as(ExpressionStmtSyntax.self) { - return parent.children(viewMode: .sourceAccurate).count == 1 && - ( codeBlockItemListSyntax.count == 1 || expressionStmtSyntax.expression.is(IfExprSyntax.self)) && - result.signature.allowsImplicitReturns - } - return false + return nil } - var isSwitchExprImplicitReturn: Bool { - guard let parent = parent?.as(CodeBlockItemListSyntax.self), - let switchExprSytax = parent.parent?.parent?.parent?.as(SwitchExprSyntax.self) else { - return false - } - guard let funcDecl = switchExprSytax.parent?.parent?.parent?.parent?.parent?.as(FunctionDeclSyntax.self) else { - return false - } - return parent.children(viewMode: .sourceAccurate).count == 1 && - funcDecl.signature.allowsImplicitReturns && - switchExprSytax.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self)?.count == 1 + var isIfOrSwitchExprImplicitReturn: Bool { + guard let functionDeclSyntax = getFunctionDeclSyntax(codeBlockItem: self) else { return false } + return functionDeclSyntax.signature.allowsImplicitReturns } } From 0e9e428d51a2519823e0f914037111275dbf3ed4 Mon Sep 17 00:00:00 2001 From: uabyss Date: Sat, 12 Oct 2024 16:16:37 +0900 Subject: [PATCH 10/19] fix: test --- .../Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift index f256f1bf5d..2e29202c0a 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift @@ -119,7 +119,7 @@ struct VoidFunctionInTernaryConditionRule: Rule { return "7" } } - """) + """), ], triggeringExamples: [ Example("success ↓? askQuestion() : exit()"), @@ -230,7 +230,7 @@ struct VoidFunctionInTernaryConditionRule: Rule { return "7" } } - """) + """), ] ) } From a33917abcbf9388351c047b93cfd9b48e7a0e00e Mon Sep 17 00:00:00 2001 From: uabyss Date: Mon, 15 Jul 2024 21:41:53 +0900 Subject: [PATCH 11/19] fix: void_function_in_ternary incorrectly triggered with if statement --- .../VoidFunctionInTernaryConditionRule.swift | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift index 2e29202c0a..d0aab3a4b8 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift @@ -382,3 +382,17 @@ private extension ReturnClauseSyntax { return true } } + +// Helper method that traces back the parent until a particular node reaches FunctionDeclSyntax. +extension Syntax { + func findParent(ofType type: T.Type) -> T? { + var current: Syntax? = self + while let parent = current?.parent { + if let parentNode = parent.as(T.self) { + return parentNode + } + current = parent + } + return nil + } +} From 8d5b9f8960b247d746dfba96c0961653caa3ca3c Mon Sep 17 00:00:00 2001 From: uabyss Date: Mon, 15 Jul 2024 22:03:34 +0900 Subject: [PATCH 12/19] fix: IntegrationTests --- .../Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift index d0aab3a4b8..aab1b593f6 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift @@ -384,8 +384,8 @@ private extension ReturnClauseSyntax { } // Helper method that traces back the parent until a particular node reaches FunctionDeclSyntax. -extension Syntax { - func findParent(ofType type: T.Type) -> T? { +private extension Syntax { + func findParent(ofType _: T.Type) -> T? { var current: Syntax? = self while let parent = current?.parent { if let parentNode = parent.as(T.self) { From be1efd1ce1499b9c383fcf06950a81924f1047e1 Mon Sep 17 00:00:00 2001 From: uabyss Date: Thu, 18 Jul 2024 17:04:21 +0900 Subject: [PATCH 13/19] update --- .../VoidFunctionInTernaryConditionRule.swift | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift index aab1b593f6..b610c0c948 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift @@ -120,6 +120,14 @@ struct VoidFunctionInTernaryConditionRule: Rule { } } """), + Example(""" + func collectionView() -> CGSize { + switch indexPath.section { + case 0: isEditing ? CGSize(width: 150, height: 20) : CGSize(width: 100, height: 20) + default: .zero + } + } + """), ], triggeringExamples: [ Example("success ↓? askQuestion() : exit()"), @@ -382,17 +390,3 @@ private extension ReturnClauseSyntax { return true } } - -// Helper method that traces back the parent until a particular node reaches FunctionDeclSyntax. -private extension Syntax { - func findParent(ofType _: T.Type) -> T? { - var current: Syntax? = self - while let parent = current?.parent { - if let parentNode = parent.as(T.self) { - return parentNode - } - current = parent - } - return nil - } -} From dbeef12852f91423a3c0015d10641a0e6f53cc43 Mon Sep 17 00:00:00 2001 From: uabyss Date: Sun, 28 Jul 2024 22:02:16 +0900 Subject: [PATCH 14/19] fix: isIfExprImplicitReturn --- .../Idiomatic/VoidFunctionInTernaryConditionRule.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift index b610c0c948..a70ba9244a 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift @@ -121,6 +121,16 @@ struct VoidFunctionInTernaryConditionRule: Rule { } """), Example(""" + func exampleNestedIfExpr() -> String { + test() + if true { + isTrue ? defaultValue() : defaultValue() + } else { + "Default" + } + } + """), + Example(""" func collectionView() -> CGSize { switch indexPath.section { case 0: isEditing ? CGSize(width: 150, height: 20) : CGSize(width: 100, height: 20) From ae1cf7e346f6c5ae7f5a331057e835b22a4fb012 Mon Sep 17 00:00:00 2001 From: uabyss Date: Thu, 12 Sep 2024 17:06:07 +0900 Subject: [PATCH 15/19] add: recursive function to find FunctionDeclSyntax --- .../VoidFunctionInTernaryConditionRule.swift | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift index a70ba9244a..6fe4abc034 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift @@ -344,6 +344,26 @@ private extension CodeBlockItemSyntax { return parent.children(viewMode: .sourceAccurate).count == 1 } + + func getFunctionDeclSyntax(parent: CodeBlockItemListSyntax) -> FunctionDeclSyntax? { + let targetSyntax = parent.parent?.parent + if let targetSyntax = targetSyntax?.as(FunctionDeclSyntax.self) { + return targetSyntax + } + if let ifExprSyntax = targetSyntax?.as(IfExprSyntax.self) { + guard let codeBlockItemListSyntax = ifExprSyntax.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self) else { + return nil + } + return getFunctionDeclSyntax(parent: codeBlockItemListSyntax) + } + if let swichExprSyntax = targetSyntax?.parent?.as(SwitchExprSyntax.self) { + guard let codeBlockItemListSyntax = swichExprSyntax.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self) else { + return nil + } + return getFunctionDeclSyntax(parent: codeBlockItemListSyntax) + } + return nil + } // Recursively traverse the codeBlockItem to determine if it is a FunctionDeclSyntax func getFunctionDeclSyntax(codeBlockItem: CodeBlockItemSyntax) -> FunctionDeclSyntax? { From df72a0075d54e5334fb8d985dacf1150f0e4a997 Mon Sep 17 00:00:00 2001 From: uabyss Date: Thu, 12 Sep 2024 17:48:05 +0900 Subject: [PATCH 16/19] fix: test error --- .../VoidFunctionInTernaryConditionRule.swift | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift index 6fe4abc034..978725d827 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift @@ -344,26 +344,26 @@ private extension CodeBlockItemSyntax { return parent.children(viewMode: .sourceAccurate).count == 1 } - - func getFunctionDeclSyntax(parent: CodeBlockItemListSyntax) -> FunctionDeclSyntax? { - let targetSyntax = parent.parent?.parent - if let targetSyntax = targetSyntax?.as(FunctionDeclSyntax.self) { - return targetSyntax - } - if let ifExprSyntax = targetSyntax?.as(IfExprSyntax.self) { - guard let codeBlockItemListSyntax = ifExprSyntax.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self) else { - return nil + + func getFunctionDeclSyntax(parent: CodeBlockItemListSyntax) -> FunctionDeclSyntax? { + let targetSyntax = parent.parent?.parent + if let targetSyntax = targetSyntax?.as(FunctionDeclSyntax.self) { + return targetSyntax } - return getFunctionDeclSyntax(parent: codeBlockItemListSyntax) - } - if let swichExprSyntax = targetSyntax?.parent?.as(SwitchExprSyntax.self) { - guard let codeBlockItemListSyntax = swichExprSyntax.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self) else { - return nil + if let ifExprSyntax = targetSyntax?.as(IfExprSyntax.self) { + guard let codeBlockItemListSyntax = ifExprSyntax.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self) else { + return nil + } + return getFunctionDeclSyntax(parent: codeBlockItemListSyntax) + } + if let switchExpr = targetSyntax?.parent?.as(SwitchExprSyntax.self) { + guard let codeBlockItemListSyntax = switchExpr.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self) else { + return nil + } + return getFunctionDeclSyntax(parent: codeBlockItemListSyntax) } - return getFunctionDeclSyntax(parent: codeBlockItemListSyntax) + return nil } - return nil - } // Recursively traverse the codeBlockItem to determine if it is a FunctionDeclSyntax func getFunctionDeclSyntax(codeBlockItem: CodeBlockItemSyntax) -> FunctionDeclSyntax? { From 5544376722d6badc9f120d3124a4a761e280e863 Mon Sep 17 00:00:00 2001 From: uabyss Date: Thu, 19 Sep 2024 22:25:02 +0900 Subject: [PATCH 17/19] refactor --- .../VoidFunctionInTernaryConditionRule.swift | 50 ++++++++++--------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift index 978725d827..81e3e2c5cb 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift @@ -124,20 +124,44 @@ struct VoidFunctionInTernaryConditionRule: Rule { func exampleNestedIfExpr() -> String { test() if true { - isTrue ? defaultValue() : defaultValue() + return isTrue ? defaultValue() : defaultValue() } else { - "Default" + return "Default" } } """), Example(""" func collectionView() -> CGSize { switch indexPath.section { - case 0: isEditing ? CGSize(width: 150, height: 20) : CGSize(width: 100, height: 20) + case 0: return isEditing ? CGSize(width: 150, height: 20) : CGSize(width: 100, height: 20) default: .zero } } """), + Example(""" + func exampleFunction() -> String { + if true { + switch value { + case 1: + if flag { + return isTrue ? "1" : "2" + } else { + return "3" + } + case 2: + if true { + return "4" + } else { + return "5" + } + default: + return "6" + } + } else { + return "7" + } + } + """) ], triggeringExamples: [ Example("success ↓? askQuestion() : exit()"), @@ -345,26 +369,6 @@ private extension CodeBlockItemSyntax { return parent.children(viewMode: .sourceAccurate).count == 1 } - func getFunctionDeclSyntax(parent: CodeBlockItemListSyntax) -> FunctionDeclSyntax? { - let targetSyntax = parent.parent?.parent - if let targetSyntax = targetSyntax?.as(FunctionDeclSyntax.self) { - return targetSyntax - } - if let ifExprSyntax = targetSyntax?.as(IfExprSyntax.self) { - guard let codeBlockItemListSyntax = ifExprSyntax.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self) else { - return nil - } - return getFunctionDeclSyntax(parent: codeBlockItemListSyntax) - } - if let switchExpr = targetSyntax?.parent?.as(SwitchExprSyntax.self) { - guard let codeBlockItemListSyntax = switchExpr.parent?.parent?.parent?.as(CodeBlockItemListSyntax.self) else { - return nil - } - return getFunctionDeclSyntax(parent: codeBlockItemListSyntax) - } - return nil - } - // Recursively traverse the codeBlockItem to determine if it is a FunctionDeclSyntax func getFunctionDeclSyntax(codeBlockItem: CodeBlockItemSyntax) -> FunctionDeclSyntax? { let targetSyntax = codeBlockItem.parent?.parent?.parent?.parent From a38ce322b544ef6d67e43bd1fb4c90255c354b85 Mon Sep 17 00:00:00 2001 From: uabyss Date: Sat, 12 Oct 2024 16:47:20 +0900 Subject: [PATCH 18/19] remove duplicated test case --- .../VoidFunctionInTernaryConditionRule.swift | 52 ------------------- 1 file changed, 52 deletions(-) diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift index 81e3e2c5cb..d6674aa62b 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift @@ -79,16 +79,6 @@ struct VoidFunctionInTernaryConditionRule: Rule { } """), Example(""" - func exampleNestedIfExpr() -> String { - test() - if true { - return isTrue ? defaultValue() : defaultValue() - } else { - return "Default" - } - } - """), - Example(""" func collectionView() -> CGSize { switch indexPath.section { case 0: return isEditing ? CGSize(width: 150, height: 20) : CGSize(width: 100, height: 20) @@ -120,48 +110,6 @@ struct VoidFunctionInTernaryConditionRule: Rule { } } """), - Example(""" - func exampleNestedIfExpr() -> String { - test() - if true { - return isTrue ? defaultValue() : defaultValue() - } else { - return "Default" - } - } - """), - Example(""" - func collectionView() -> CGSize { - switch indexPath.section { - case 0: return isEditing ? CGSize(width: 150, height: 20) : CGSize(width: 100, height: 20) - default: .zero - } - } - """), - Example(""" - func exampleFunction() -> String { - if true { - switch value { - case 1: - if flag { - return isTrue ? "1" : "2" - } else { - return "3" - } - case 2: - if true { - return "4" - } else { - return "5" - } - default: - return "6" - } - } else { - return "7" - } - } - """) ], triggeringExamples: [ Example("success ↓? askQuestion() : exit()"), From e52ccd3d63916c913037e944b980b85d5b0a7c63 Mon Sep 17 00:00:00 2001 From: uabyss Date: Sat, 12 Oct 2024 17:29:59 +0900 Subject: [PATCH 19/19] change: test case --- .../VoidFunctionInTernaryConditionRule.swift | 35 +++++++------------ 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift index d6674aa62b..d5e80cf3bb 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift @@ -61,18 +61,18 @@ struct VoidFunctionInTernaryConditionRule: Rule { index == 0 ? defaultValue() : compute(index) """), Example(""" - func example() -> String { + func example(index: Int) -> String { if true { - return isTrue ? defaultValue() : defaultValue() + return index == 0 ? defaultValue() : defaultValue() } else { return "Default" } } """), Example(""" - func exampleNestedIfExpr() -> String { + func exampleNestedIfExpr(index: Int) -> String { if true { - return isTrue ? defaultValue() : defaultValue() + return index == 0 ? defaultValue() : defaultValue() } else { return "Default" } @@ -87,17 +87,17 @@ struct VoidFunctionInTernaryConditionRule: Rule { } """), Example(""" - func exampleFunction() -> String { - if true { - switch value { + func exampleNestedIfExprAndSwitchExpr(index: Int) -> String { + if index <= 3 { + switch index { case 1: - if flag { + if isTrue { return isTrue ? "1" : "2" } else { return "3" } case 2: - if true { + if isTrue { return "4" } else { return "5" @@ -164,16 +164,6 @@ struct VoidFunctionInTernaryConditionRule: Rule { } """), Example(""" - func exampleNestedIfExpr() -> String { - if true { - isTrue ↓? defaultValue() : defaultValue() - } else { - "Default" - } - return hoge - } - """), - Example(""" func collectionView() -> CGSize { switch indexPath.section { case 0: isEditing ↓? CGSize(width: 150, height: 20) : CGSize(width: 100, height: 20) @@ -187,17 +177,18 @@ struct VoidFunctionInTernaryConditionRule: Rule { if true { if true { isTrue ↓? defaultValue() : defaultValue() + retun "True" } else { return "False" } } else { return "Default" } - return hoge + return "hoge" } """), Example(""" - func exampleFunction() -> String { + func exampleNestedIfExprAndSwitchExpr() -> String { if true { switch value { case 1: @@ -317,7 +308,7 @@ private extension CodeBlockItemSyntax { return parent.children(viewMode: .sourceAccurate).count == 1 } - // Recursively traverse the codeBlockItem to determine if it is a FunctionDeclSyntax + // For codeBlockItem, recursively traverse it to determine if it is within its own FunctionDeclSyntax. func getFunctionDeclSyntax(codeBlockItem: CodeBlockItemSyntax) -> FunctionDeclSyntax? { let targetSyntax = codeBlockItem.parent?.parent?.parent?.parent if let targetSyntax = targetSyntax?.as(FunctionDeclSyntax.self) {