diff --git a/Generator/Package.swift b/Generator/Package.swift index 09b5ab91..b7419968 100644 --- a/Generator/Package.swift +++ b/Generator/Package.swift @@ -11,10 +11,10 @@ let package = Package( .library(name: "NeedleFramework", targets: ["NeedleFramework"]) ], dependencies: [ - .package(url: "https://github.com/apple/swift-tools-support-core", .exact("0.2.7")), + .package(url: "https://github.com/apple/swift-tools-support-core", exact: "0.2.7"), .package(url: "https://github.com/uber/swift-concurrency.git", .upToNextMajor(from: "0.6.5")), - .package(url: "https://github.com/uber/swift-common.git", .exact("0.5.0")), - .package(url: "https://github.com/apple/swift-syntax.git", revision: "0e85cf7"), + .package(url: "https://github.com/uber/swift-common.git", exact: "0.5.0"), + .package(url: "https://github.com/apple/swift-syntax.git", .upToNextMajor(from: "510.0.0")), ], targets: [ .target( @@ -24,7 +24,7 @@ let package = Package( .product(name: "Concurrency", package: "swift-concurrency"), .product(name: "SourceParsingFramework", package: "swift-common"), .product(name: "SwiftSyntax", package: "swift-syntax"), - .product(name: "SwiftSyntaxParser", package: "swift-syntax"), + .product(name: "SwiftParser", package: "swift-syntax"), ]), .testTarget( name: "NeedleFrameworkTests", diff --git a/Generator/Sources/NeedleFramework/Parsing/BaseVisitor.swift b/Generator/Sources/NeedleFramework/Parsing/BaseVisitor.swift index 66304ff5..f12f36e6 100644 --- a/Generator/Sources/NeedleFramework/Parsing/BaseVisitor.swift +++ b/Generator/Sources/NeedleFramework/Parsing/BaseVisitor.swift @@ -39,8 +39,10 @@ class BaseVisitor: SyntaxVisitor { var isParsingComponentDeclarationLine: Bool = false override func visitPost(_ node: FunctionCallExprSyntax) { - if let callexpr = node.calledExpression.firstToken?.text, - let currentEntityName = currentEntityNode?.typeName { + if + let callexpr = node.calledExpression.firstToken(viewMode: .sourceAccurate)?.text, + let currentEntityName = currentEntityNode?.typeName + { componentToCallExprs[currentEntityName, default: []].insert(callexpr) } } @@ -60,9 +62,11 @@ class BaseVisitor: SyntaxVisitor { let isInternal = !(isPublic || isPrivate || isFileprivate) let memberProperties = node.bindings.compactMap { pattern -> Property? in - guard let propertyType = pattern.typeAnnotation?.type.description.trimmed, - let propertyName = pattern.firstToken?.text else { - return nil + guard + let propertyType = pattern.typeAnnotation?.type.description.trimmed, + let propertyName = pattern.firstToken(viewMode: .sourceAccurate)?.text + else { + return nil } if isPrivate || isFileprivate { info("\(currentEntityName) (\(propertyName): \(propertyType)) property is private/fileprivate, therefore inaccessible on DI graph.") @@ -76,11 +80,11 @@ class BaseVisitor: SyntaxVisitor { } override func visitPost(_ node: ImportDeclSyntax) { - let importStatement = node.withoutTrivia().description.trimmed + let importStatement = node.trimmed.description.trimmed imports.append(importStatement) } - override func visit(_ node: MemberDeclBlockSyntax) -> SyntaxVisitorContinueKind { + override func visit(_ node: MemberBlockSyntax) -> SyntaxVisitorContinueKind { isParsingComponentDeclarationLine = false return .visitChildren } diff --git a/Generator/Sources/NeedleFramework/Parsing/Pluginized/Tasks/PluginizedASTDeclarationParserTask.swift b/Generator/Sources/NeedleFramework/Parsing/Pluginized/Tasks/PluginizedASTDeclarationParserTask.swift index 67fa6390..12ccb78b 100644 --- a/Generator/Sources/NeedleFramework/Parsing/Pluginized/Tasks/PluginizedASTDeclarationParserTask.swift +++ b/Generator/Sources/NeedleFramework/Parsing/Pluginized/Tasks/PluginizedASTDeclarationParserTask.swift @@ -138,7 +138,7 @@ private final class PluginizedVisitor: BaseVisitor { if currentEntityNode?.typeName == currentPluginizedComponentName { for (i, genericArgument) in node.enumerated() { - let argumentName = genericArgument.argumentType.description.trimmed.removingModulePrefix + let argumentName = genericArgument.argument.description.trimmed.removingModulePrefix switch i { case 0: @@ -152,7 +152,7 @@ private final class PluginizedVisitor: BaseVisitor { } } } else if currentEntityNode?.typeName == currentNonCoreComponentName { - currentDependencyProtocol = node.first?.argumentType.description.trimmed.removingModulePrefix + currentDependencyProtocol = node.first?.argument.description.trimmed.removingModulePrefix } } diff --git a/Generator/Sources/NeedleFramework/Parsing/Tasks/ASTProducerTask.swift b/Generator/Sources/NeedleFramework/Parsing/Tasks/ASTProducerTask.swift index e67a4377..74fe7255 100644 --- a/Generator/Sources/NeedleFramework/Parsing/Tasks/ASTProducerTask.swift +++ b/Generator/Sources/NeedleFramework/Parsing/Tasks/ASTProducerTask.swift @@ -17,11 +17,7 @@ import Concurrency import Foundation import SourceParsingFramework -#if swift(>=5.6) -import SwiftSyntaxParser -#else -import SwiftSyntax -#endif +import SwiftParser /// A task that parses a Swift source content and produces Swift AST that /// can then be parsed into the dependency graph. @@ -42,7 +38,7 @@ class ASTProducerTask: AbstractTask { /// - returns: The `AST` data model. /// - throws: Any error occurred during execution. override func execute() throws -> AST { - let syntax = try SyntaxParser.parse(sourceUrl) + let syntax = try Parser.parse(source: String(contentsOf: sourceUrl)) return AST(sourceHash: MD5(string: sourceContent), sourceFileSyntax: syntax, filePath: sourceUrl.path) } diff --git a/Generator/Sources/NeedleFramework/Parsing/Tasks/ComponentExtensionsParserTask.swift b/Generator/Sources/NeedleFramework/Parsing/Tasks/ComponentExtensionsParserTask.swift index 79b130d6..cf4ef9cd 100644 --- a/Generator/Sources/NeedleFramework/Parsing/Tasks/ComponentExtensionsParserTask.swift +++ b/Generator/Sources/NeedleFramework/Parsing/Tasks/ComponentExtensionsParserTask.swift @@ -17,7 +17,6 @@ import Concurrency import Foundation import SwiftSyntax -import SourceParsingFramework /// A task that parses Swift AST component extensions into data models. class ComponentExtensionsParserTask: AbstractTask { diff --git a/Generator/Sources/NeedleFramework/Parsing/Tasks/DeclarationsParserTask.swift b/Generator/Sources/NeedleFramework/Parsing/Tasks/DeclarationsParserTask.swift index 3c138d00..c865c155 100644 --- a/Generator/Sources/NeedleFramework/Parsing/Tasks/DeclarationsParserTask.swift +++ b/Generator/Sources/NeedleFramework/Parsing/Tasks/DeclarationsParserTask.swift @@ -112,7 +112,7 @@ private final class Visitor: BaseVisitor { override func visitPost(_ node: GenericArgumentListSyntax) { guard isParsingComponentDeclarationLine else {return } - currentDependencyProtocol = node.first?.argumentType.description.trimmed.removingModulePrefix + currentDependencyProtocol = node.first?.argument.description.trimmed.removingModulePrefix } override func visit(_ node: ExtensionDeclSyntax) -> SyntaxVisitorContinueKind { diff --git a/Generator/Sources/NeedleFramework/Utilities/SwiftSyntaxExtensions.swift b/Generator/Sources/NeedleFramework/Utilities/SwiftSyntaxExtensions.swift index 81913e16..e6610ac1 100644 --- a/Generator/Sources/NeedleFramework/Utilities/SwiftSyntaxExtensions.swift +++ b/Generator/Sources/NeedleFramework/Utilities/SwiftSyntaxExtensions.swift @@ -21,57 +21,57 @@ import SwiftSyntax /// An entity node is either a Protocol or Class syntax node protocol EntityNode: SyntaxNodeWithModifiers { var typeName: String { get } - var inheritanceClause: TypeInheritanceClauseSyntax? { get } + var inheritanceClause: InheritanceClauseSyntax? { get } } extension EntityNode { /// Checks whether the entity inherits from a certain type with `typeName` func inherits(from typeName: String) -> Bool { - let inheritedTypeSyntax = inheritanceClause?.inheritedTypeCollection.first?.typeName + let inheritedTypeSyntax = inheritanceClause?.inheritedTypes.first?.type // Usually, first token is the inherited type name. But sometimes it could also be the module prefix. // In that case, we need to look for the actual type name by checking for `MemberTypeIdentifierSyntax` - if inheritedTypeSyntax?.firstToken?.nextToken?.tokenKind != TokenKind.period { - return inheritedTypeSyntax?.firstToken?.text == typeName + if inheritedTypeSyntax?.firstToken(viewMode: .sourceAccurate)?.nextToken(viewMode: .sourceAccurate)?.tokenKind != TokenKind.period { + return inheritedTypeSyntax?.firstToken(viewMode: .sourceAccurate)?.text == typeName } else { - return inheritedTypeSyntax?.as(MemberTypeIdentifierSyntax.self)?.name.text == typeName + return inheritedTypeSyntax?.as(MemberTypeSyntax.self)?.name.text == typeName } } var inheritanceHasGenericArgument: Bool { - let inheritanceTypeToken = inheritanceClause?.inheritedTypeCollection.first?.typeName - return inheritanceTypeToken?.as(SimpleTypeIdentifierSyntax.self)?.genericArgumentClause != nil || - inheritanceTypeToken?.as(MemberTypeIdentifierSyntax.self)?.genericArgumentClause != nil + let inheritanceTypeToken = inheritanceClause?.inheritedTypes.first?.type + return inheritanceTypeToken?.as(IdentifierTypeSyntax.self)?.genericArgumentClause != nil || + inheritanceTypeToken?.as(MemberTypeSyntax.self)?.genericArgumentClause != nil } } protocol SyntaxNodeWithModifiers { - var modifiers: ModifierListSyntax? { get } + var modifiers: DeclModifierListSyntax { get } } extension SyntaxNodeWithModifiers { var isInternal: Bool { - modifiers?.first?.name.text == nil || modifiers?.first?.name.text == "internal" + modifiers.first?.name.text == nil || modifiers.first?.name.text == "internal" } var isPublic: Bool { - modifiers?.first?.name.text == "public" + modifiers.first?.name.text == "public" } var isPrivate: Bool { - modifiers?.first?.name.text == "private" + modifiers.first?.name.text == "private" } var isFileprivate: Bool { - modifiers?.first?.name.text == "fileprivate" + modifiers.first?.name.text == "fileprivate" } } // MARK: - SwiftSyntax Protocol Extensions -extension IdentifiedDeclSyntax { +extension NamedDeclSyntax { var typeName: String { - return identifier.description.trimmed + return name.description.trimmed } } diff --git a/Generator/Tests/NeedleFrameworkTests/Parsing/ASTProducerTaskTests.swift b/Generator/Tests/NeedleFrameworkTests/Parsing/ASTProducerTaskTests.swift index 321658ac..9aa1e514 100644 --- a/Generator/Tests/NeedleFrameworkTests/Parsing/ASTProducerTaskTests.swift +++ b/Generator/Tests/NeedleFrameworkTests/Parsing/ASTProducerTaskTests.swift @@ -16,18 +16,14 @@ import XCTest @testable import NeedleFramework -#if swift(>=5.6) -import SwiftSyntaxParser -#else -import SwiftSyntax -#endif +import SwiftParser class ASTProducerTaskTests: AbstractParserTests { func test_execute_verifyNextTask() { let sourceUrl = fixtureUrl(for: "ComponentSample.swift") let sourceContent = try! String(contentsOf: sourceUrl) - let astContent = try! SyntaxParser.parse(sourceUrl) + let astContent = Parser.parse(source: sourceContent) let task = ASTProducerTask(sourceUrl: sourceUrl, sourceContent: sourceContent) let result = try! task.execute() diff --git a/Generator/Tests/NeedleFrameworkTests/Parsing/DeclarationsParserTaskTests.swift b/Generator/Tests/NeedleFrameworkTests/Parsing/DeclarationsParserTaskTests.swift index b97af6e5..90cca18c 100644 --- a/Generator/Tests/NeedleFrameworkTests/Parsing/DeclarationsParserTaskTests.swift +++ b/Generator/Tests/NeedleFrameworkTests/Parsing/DeclarationsParserTaskTests.swift @@ -17,11 +17,7 @@ import XCTest @testable import NeedleFramework @testable import SourceParsingFramework -#if swift(>=5.6) -import SwiftSyntaxParser -#else -import SwiftSyntax -#endif +import SwiftParser class DeclarationsParserTaskTests: AbstractParserTests { @@ -29,7 +25,7 @@ class DeclarationsParserTaskTests: AbstractParserTests { let sourceUrl = fixtureUrl(for: "PrivateSample.swift") let sourceContent = try! String(contentsOf: sourceUrl) let ast = AST(sourceHash: MD5(string: sourceContent), - sourceFileSyntax: try! SyntaxParser.parse(sourceUrl), filePath: sourceUrl.path) + sourceFileSyntax: Parser.parse(source: sourceContent), filePath: sourceUrl.path) let task = DeclarationsParserTask(ast: ast) _ = try! task.execute() @@ -46,8 +42,8 @@ class DeclarationsParserTaskTests: AbstractParserTests { let sourceContent = try! String(contentsOf: sourceUrl) let imports = ["import UIKit", "import RIBs", "import Foundation", "import protocol Audio.Recordable"] let ast = AST(sourceHash: MD5(string: sourceContent), - sourceFileSyntax: try! SyntaxParser.parse(sourceUrl), filePath: sourceUrl.path) - + sourceFileSyntax: Parser.parse(source: sourceContent), filePath: sourceUrl.path) + let task = DeclarationsParserTask(ast: ast) let node = try! task.execute() diff --git a/Generator/Tests/NeedleFrameworkTests/Parsing/Pluginized/PluginizedDeclarationsParserTaskTests.swift b/Generator/Tests/NeedleFrameworkTests/Parsing/Pluginized/PluginizedDeclarationsParserTaskTests.swift index bebb2379..d7bdb6bf 100644 --- a/Generator/Tests/NeedleFrameworkTests/Parsing/Pluginized/PluginizedDeclarationsParserTaskTests.swift +++ b/Generator/Tests/NeedleFrameworkTests/Parsing/Pluginized/PluginizedDeclarationsParserTaskTests.swift @@ -16,11 +16,7 @@ import XCTest @testable import NeedleFramework -#if swift(>=5.6) -import SwiftSyntaxParser -#else -import SwiftSyntax -#endif +import SwiftParser class PluginizedDeclarationsParserTaskTests: AbstractParserTests { @@ -29,7 +25,7 @@ class PluginizedDeclarationsParserTaskTests: AbstractParserTests { let sourceContent = try! String(contentsOf: sourceUrl) let imports = ["import UIKit", "import RIBs", "import Foundation"] let ast = AST(sourceHash: MD5(string: sourceContent), - sourceFileSyntax: try! SyntaxParser.parse(sourceUrl), filePath: sourceUrl.path) + sourceFileSyntax: Parser.parse(source: sourceContent), filePath: sourceUrl.path) let task = PluginizedDeclarationsParserTask(ast: ast) let node = try! task.execute()