From 0fb3b1ef83ac63ea8f1afa39688847b051df8797 Mon Sep 17 00:00:00 2001 From: Ian Leitch Date: Tue, 19 Dec 2023 17:31:24 +0000 Subject: [PATCH] Fix redundant public accessibility analysis false-positive for function parameter default values, closes #691 --- CHANGELOG.md | 1 + .../Syntax/DeclarationSyntaxVisitor.swift | 48 ++++++++++++------- .../Sources/MainTarget/main.swift | 2 + ...sPublicFunctionParameterDefaultValue.swift | 11 +++++ .../RedundantPublicAccessibilityTest.swift | 8 ++++ 5 files changed, 54 insertions(+), 16 deletions(-) create mode 100644 Tests/AccessibilityTests/AccessibilityProject/Sources/TargetA/PublicTypeUsedAsPublicFunctionParameterDefaultValue.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 271c0c507..806757a5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ - Fix redundant public accessibility analysis false-positive for actors. - Fix redundant public accessibility analysis false-positive for property wrappers. - Fix redundant public accessibility analysis false-positive for declarations referenced from a public `@inlinable` function. +- Fix redundant public accessibility analysis false-positive for function parameter default values. ## 2.17.1 (2023-12-04) diff --git a/Sources/PeripheryKit/Syntax/DeclarationSyntaxVisitor.swift b/Sources/PeripheryKit/Syntax/DeclarationSyntaxVisitor.swift index 8893c6f55..e67bf9381 100644 --- a/Sources/PeripheryKit/Syntax/DeclarationSyntaxVisitor.swift +++ b/Sources/PeripheryKit/Syntax/DeclarationSyntaxVisitor.swift @@ -336,22 +336,22 @@ final class DeclarationSyntaxVisitor: PeripherySyntaxVisitor { .union(closureParameterClauseLocations) results.append(( - location, - accessibility, - modifierNames, - attributeNames, - CommentCommand.parseCommands(in: trivia), - type(for: variableType), - typeLocations(for: variableType), - allParameterClauseLocations, - returnClauseTypeLocations.mapSet { $0.location }, - typeLocations(for: inheritanceClause), - typeLocations(for: genericParameterClause), - typeLocations(for: genericWhereClause), - locations(for: variableInitFunctionCallExpr), - functionCallMetatypeArgumentLocations(for: variableInitFunctionCallExpr), - didVisitCapitalSelfFunctionCall, - hasGenericFunctionReturnedMetatypeParameters + location: location, + accessibility: accessibility, + modifiers: modifierNames, + attributes: attributeNames, + commentCommands: CommentCommand.parseCommands(in: trivia), + variableType: type(for: variableType), + variableTypeLocations: typeLocations(for: variableType), + parameterTypeLocations: allParameterClauseLocations, + returnTypeLocations: returnClauseTypeLocations.mapSet { $0.location }, + inheritedTypeLocations: typeLocations(for: inheritanceClause), + genericParameterLocations: typeLocations(for: genericParameterClause), + genericConformanceRequirementLocations: typeLocations(for: genericWhereClause), + variableInitFunctionCallLocations: locations(for: variableInitFunctionCallExpr), + functionCallMetatypeArgumentLocations: functionCallMetatypeArgumentLocations(for: variableInitFunctionCallExpr), + hasCapitalSelfFunctionCall: didVisitCapitalSelfFunctionCall, + hasGenericFunctionReturnedMetatypeParameters: hasGenericFunctionReturnedMetatypeParameters )) } @@ -396,9 +396,25 @@ final class DeclarationSyntaxVisitor: PeripherySyntaxVisitor { return clause.parameters.reduce(into: .init(), { result, param in result.formUnion(typeSyntaxInspector.typeLocations(for: param.type)) + + if let defaultValue = param.defaultValue?.value { + result.formUnion(identifierLocations(for: defaultValue)) + } }) } + private func identifierLocations(for expr: ExprSyntax) -> Set { + expr.children(viewMode: .sourceAccurate).flatMapSet { child in + if let token = child.as(TokenSyntax.self), case .identifier = token.tokenKind { + return [sourceLocationBuilder.location(at: token.positionAfterSkippingLeadingTrivia)] + } else if let childExpr = child.as(ExprSyntax.self) { + return identifierLocations(for: childExpr) + } + + return [] + } + } + private func typeLocations(for clause: ClosureParameterClauseSyntax?) -> Set { guard let clause = clause else { return [] } diff --git a/Tests/AccessibilityTests/AccessibilityProject/Sources/MainTarget/main.swift b/Tests/AccessibilityTests/AccessibilityProject/Sources/MainTarget/main.swift index 9a1a4c0fe..43a8ba7ca 100644 --- a/Tests/AccessibilityTests/AccessibilityProject/Sources/MainTarget/main.swift +++ b/Tests/AccessibilityTests/AccessibilityProject/Sources/MainTarget/main.swift @@ -17,6 +17,8 @@ PublicTypeUsedAsPublicFunctionParameterTypeRetainer().retain1() PublicTypeUsedAsPublicFunctionParameterTypeRetainer().retain2() PublicTypeUsedAsPublicFunctionParameterTypeRetainer().retain3() +PublicTypeUsedAsPublicFunctionParameterDefaultValueRetainer().somePublicFunc() + _ = PublicTypeUsedAsPublicFunctionReturnTypeRetainer().retain1() _ = PublicTypeUsedAsPublicFunctionReturnTypeRetainer().retain2() _ = PublicTypeUsedAsPublicFunctionReturnTypeRetainer().retain3() diff --git a/Tests/AccessibilityTests/AccessibilityProject/Sources/TargetA/PublicTypeUsedAsPublicFunctionParameterDefaultValue.swift b/Tests/AccessibilityTests/AccessibilityProject/Sources/TargetA/PublicTypeUsedAsPublicFunctionParameterDefaultValue.swift new file mode 100644 index 000000000..3819bbcc2 --- /dev/null +++ b/Tests/AccessibilityTests/AccessibilityProject/Sources/TargetA/PublicTypeUsedAsPublicFunctionParameterDefaultValue.swift @@ -0,0 +1,11 @@ +import Foundation + +public struct PublicTypeUsedAsPublicFunctionParameterDefaultValue { + public static let somePublicValue = 1 +} + +public class PublicTypeUsedAsPublicFunctionParameterDefaultValueRetainer { + public init() {} + + public func somePublicFunc(value: Int = PublicTypeUsedAsPublicFunctionParameterDefaultValue.somePublicValue) {} +} diff --git a/Tests/AccessibilityTests/RedundantPublicAccessibilityTest.swift b/Tests/AccessibilityTests/RedundantPublicAccessibilityTest.swift index d4cd3ab01..87c285c0f 100644 --- a/Tests/AccessibilityTests/RedundantPublicAccessibilityTest.swift +++ b/Tests/AccessibilityTests/RedundantPublicAccessibilityTest.swift @@ -60,6 +60,14 @@ class RedundantPublicAccessibilityTest: SourceGraphTestCase { assertNotRedundantPublicAccessibility(.class("PublicTypeUsedAsPublicFunctionParameterTypeClosureReturnType")) } + func testPublicTypeUsedAsPublicFunctionParameterDefaultValue() { + Self.index() + + assertNotRedundantPublicAccessibility(.struct("PublicTypeUsedAsPublicFunctionParameterDefaultValue")) { + self.assertNotRedundantPublicAccessibility(.varStatic("somePublicValue")) + } + } + func testPublicTypeUsedAsPublicFunctionReturnType() { Self.index()