Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Sources/Frontend/Scan.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ final class Scan {
let indexLogger = logger.contextualized(with: "index")
let plan = try driver.plan(logger: indexLogger)
let syncSourceGraph = SynchronizedSourceGraph(graph: graph)
let pipeline = IndexPipeline(plan: plan, graph: syncSourceGraph, logger: indexLogger, configuration: configuration)
let pipeline = IndexPipeline(plan: plan, graph: syncSourceGraph, logger: indexLogger, configuration: configuration, swiftVersion: swiftVersion)
try pipeline.perform()
logger.endInterval(indexInterval)
}
Expand Down
8 changes: 6 additions & 2 deletions Sources/Indexer/IndexPipeline.swift
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
import Configuration
import Foundation
import Logger
import Shared
import SourceGraph

public struct IndexPipeline {
private let plan: IndexPlan
private let graph: SynchronizedSourceGraph
private let logger: ContextualLogger
private let configuration: Configuration
private let swiftVersion: SwiftVersion

public init(plan: IndexPlan, graph: SynchronizedSourceGraph, logger: ContextualLogger, configuration: Configuration) {
public init(plan: IndexPlan, graph: SynchronizedSourceGraph, logger: ContextualLogger, configuration: Configuration, swiftVersion: SwiftVersion) {
self.plan = plan
self.graph = graph
self.logger = logger
self.configuration = configuration
self.swiftVersion = swiftVersion
}

public func perform() throws {
try SwiftIndexer(
sourceFiles: plan.sourceFiles,
graph: graph,
logger: logger,
configuration: configuration
configuration: configuration,
swiftVersion: swiftVersion
).perform()

if !plan.plistPaths.isEmpty {
Expand Down
15 changes: 11 additions & 4 deletions Sources/Indexer/SwiftIndexer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,20 @@ final class SwiftIndexer: Indexer {
private let graph: SynchronizedSourceGraph
private let logger: ContextualLogger
private let configuration: Configuration
private let swiftVersion: SwiftVersion

required init(
sourceFiles: [SourceFile: [IndexUnit]],
graph: SynchronizedSourceGraph,
logger: ContextualLogger,
configuration: Configuration
configuration: Configuration,
swiftVersion: SwiftVersion
) {
self.sourceFiles = sourceFiles
self.graph = graph
self.logger = logger.contextualized(with: "swift")
self.configuration = configuration
self.swiftVersion = swiftVersion
super.init(configuration: configuration)
}

Expand All @@ -39,7 +42,8 @@ final class SwiftIndexer: Indexer {
retainAllDeclarations: isRetained(file),
graph: graph,
logger: logger,
configuration: configuration
configuration: configuration,
swiftVersion: swiftVersion
)
}

Expand Down Expand Up @@ -88,21 +92,24 @@ final class SwiftIndexer: Indexer {
private let logger: ContextualLogger
private let configuration: Configuration
private var retainAllDeclarations: Bool
private let swiftVersion: SwiftVersion

required init(
sourceFile: SourceFile,
units: [IndexUnit],
retainAllDeclarations: Bool,
graph: SynchronizedSourceGraph,
logger: ContextualLogger,
configuration: Configuration
configuration: Configuration,
swiftVersion: SwiftVersion
) {
self.sourceFile = sourceFile
self.units = units
self.retainAllDeclarations = retainAllDeclarations
self.graph = graph
self.logger = logger
self.configuration = configuration
self.swiftVersion = swiftVersion
}

// swiftlint:disable nesting
Expand Down Expand Up @@ -242,7 +249,7 @@ final class SwiftIndexer: Indexer {
graph.addIndexedModules(sourceFile.modules)
}

let multiplexingSyntaxVisitor = try MultiplexingSyntaxVisitor(file: sourceFile)
let multiplexingSyntaxVisitor = try MultiplexingSyntaxVisitor(file: sourceFile, swiftVersion: swiftVersion)
let declarationSyntaxVisitor = multiplexingSyntaxVisitor.add(DeclarationSyntaxVisitor.self)
let importSyntaxVisitor = multiplexingSyntaxVisitor.add(ImportSyntaxVisitor.self)

Expand Down
21 changes: 15 additions & 6 deletions Sources/SyntaxAnalysis/DeclarationSyntaxVisitor.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Foundation
import Shared
import SourceGraph
import SwiftSyntax

Expand All @@ -24,6 +25,7 @@ public final class DeclarationSyntaxVisitor: PeripherySyntaxVisitor {

private let sourceLocationBuilder: SourceLocationBuilder
private let typeSyntaxInspector: TypeSyntaxInspector
private let swiftVersion: SwiftVersion
private(set) var results: [Result] = []

public var resultsByLocation: [Location: Result] {
Expand All @@ -32,8 +34,9 @@ public final class DeclarationSyntaxVisitor: PeripherySyntaxVisitor {
}
}

public init(sourceLocationBuilder: SourceLocationBuilder) {
public init(sourceLocationBuilder: SourceLocationBuilder, swiftVersion: SwiftVersion) {
self.sourceLocationBuilder = sourceLocationBuilder
self.swiftVersion = swiftVersion
typeSyntaxInspector = .init(sourceLocationBuilder: sourceLocationBuilder)
}

Expand Down Expand Up @@ -113,11 +116,17 @@ public final class DeclarationSyntaxVisitor: PeripherySyntaxVisitor {

if let memberType = node.extendedType.as(MemberTypeSyntax.self) {
position = memberType.name.positionAfterSkippingLeadingTrivia
} else if let genericArgumentClause = node.extendedType.as(IdentifierTypeSyntax.self)?.genericArgumentClause {
// Generic protocol extensions in the form `extension Foo<Type>` have incorrect locations in the index store.
// This results in syntax metadata not being applied to the declaration due to the location mismatch. To
// workaround this, parse this node with the incorrect location.
position = genericArgumentClause.rightAngle.positionAfterSkippingLeadingTrivia
} else if let identifierType = node.extendedType.as(IdentifierTypeSyntax.self),
let genericArgumentClause = identifierType.genericArgumentClause
{
if swiftVersion.version.isVersion(lessThanOrEqualTo: "6.2.3") {
// Swift <= 6.2.3: Generic protocol extensions in the form `extension Foo<Type>` have incorrect locations
// in the index store. This results in syntax metadata not being applied to the declaration due to the
// location mismatch. To workaround this, parse this node with the incorrect location.
position = genericArgumentClause.rightAngle.positionAfterSkippingLeadingTrivia
} else {
position = identifierType.name.positionAfterSkippingLeadingTrivia
}
}

parse(
Expand Down
4 changes: 3 additions & 1 deletion Sources/SyntaxAnalysis/ImportSyntaxVisitor.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Foundation
import Shared
import SourceGraph
import SwiftSyntax

Expand All @@ -7,8 +8,9 @@ public final class ImportSyntaxVisitor: PeripherySyntaxVisitor {

private let sourceLocationBuilder: SourceLocationBuilder

public init(sourceLocationBuilder: SourceLocationBuilder) {
public init(sourceLocationBuilder: SourceLocationBuilder, swiftVersion _: SwiftVersion) {
self.sourceLocationBuilder = sourceLocationBuilder
// swiftVersion is not used in this visitor but is required by the protocol
}

public func visit(_ node: ImportDeclSyntax) {
Expand Down
9 changes: 6 additions & 3 deletions Sources/SyntaxAnalysis/MultiplexingSyntaxVisitor.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import Foundation
import Shared
import SourceGraph
import SwiftParser
import SwiftSyntax
import SystemPackage

public protocol PeripherySyntaxVisitor {
init(sourceLocationBuilder: SourceLocationBuilder)
init(sourceLocationBuilder: SourceLocationBuilder, swiftVersion: SwiftVersion)

func visit(_ node: ActorDeclSyntax)
func visit(_ node: ClassDeclSyntax)
Expand Down Expand Up @@ -95,20 +96,22 @@ public final class MultiplexingSyntaxVisitor: SyntaxVisitor {
public let syntax: SourceFileSyntax
public let locationConverter: SourceLocationConverter
let sourceLocationBuilder: SourceLocationBuilder
let swiftVersion: SwiftVersion

private var visitors: [PeripherySyntaxVisitor] = []

public required init(file: SourceFile) throws {
public required init(file: SourceFile, swiftVersion: SwiftVersion) throws {
sourceFile = file
let source = try String(contentsOf: file.path.url)
syntax = Parser.parse(source: source)
locationConverter = SourceLocationConverter(fileName: file.path.string, tree: syntax)
sourceLocationBuilder = SourceLocationBuilder(file: file, locationConverter: locationConverter)
self.swiftVersion = swiftVersion
super.init(viewMode: .sourceAccurate)
}

public func add<T: PeripherySyntaxVisitor>(_ visitorType: T.Type) -> T {
let visitor = visitorType.init(sourceLocationBuilder: sourceLocationBuilder)
let visitor = visitorType.init(sourceLocationBuilder: sourceLocationBuilder, swiftVersion: swiftVersion)
visitors.append(visitor)
return visitor
}
Expand Down
6 changes: 5 additions & 1 deletion Tests/PeripheryTests/Syntax/FunctionVisitTest.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import Foundation
import Logger
import Shared
@testable import SourceGraph
@testable import SyntaxAnalysis
@testable import TestShared
Expand All @@ -9,7 +11,9 @@ final class FunctionVisitTest: XCTestCase {

override func setUpWithError() throws {
try super.setUpWithError()
let multiplexingVisitor = try MultiplexingSyntaxVisitor(file: fixturePath)
let shell = Shell(logger: Logger(quiet: true))
let swiftVersion = SwiftVersion(shell: shell)
let multiplexingVisitor = try MultiplexingSyntaxVisitor(file: fixturePath, swiftVersion: swiftVersion)
let visitor = multiplexingVisitor.add(DeclarationSyntaxVisitor.self)
multiplexingVisitor.visit()
results = visitor.resultsByLocation
Expand Down
6 changes: 5 additions & 1 deletion Tests/PeripheryTests/Syntax/ImportVisitTest.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import Foundation
import Logger
import Shared
@testable import SourceGraph
@testable import SyntaxAnalysis
@testable import TestShared
Expand All @@ -9,7 +11,9 @@ final class ImportVisitTest: XCTestCase {

override func setUpWithError() throws {
try super.setUpWithError()
let multiplexingVisitor = try MultiplexingSyntaxVisitor(file: fixturePath)
let shell = Shell(logger: Logger(quiet: true))
let swiftVersion = SwiftVersion(shell: shell)
let multiplexingVisitor = try MultiplexingSyntaxVisitor(file: fixturePath, swiftVersion: swiftVersion)
let visitor = multiplexingVisitor.add(ImportSyntaxVisitor.self)
multiplexingVisitor.visit()
results = visitor.importStatements
Expand Down
6 changes: 5 additions & 1 deletion Tests/PeripheryTests/Syntax/PropertyVisitTest.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import Foundation
import Logger
import Shared
@testable import SourceGraph
@testable import SyntaxAnalysis
@testable import TestShared
Expand All @@ -9,7 +11,9 @@ final class PropertyVisitTest: XCTestCase {

override func setUpWithError() throws {
try super.setUpWithError()
let multiplexingVisitor = try MultiplexingSyntaxVisitor(file: fixturePath)
let shell = Shell(logger: Logger(quiet: true))
let swiftVersion = SwiftVersion(shell: shell)
let multiplexingVisitor = try MultiplexingSyntaxVisitor(file: fixturePath, swiftVersion: swiftVersion)
let visitor = multiplexingVisitor.add(DeclarationSyntaxVisitor.self)
multiplexingVisitor.visit()
results = visitor.resultsByLocation
Expand Down
6 changes: 4 additions & 2 deletions Tests/Shared/SourceGraphTestCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,13 @@ open class SourceGraphTestCase: XCTestCase {
}

graph = SourceGraph(configuration: configuration, logger: logger)
let swiftVersion = SwiftVersion(shell: shell)
let pipeline = IndexPipeline(
plan: newPlan,
graph: SynchronizedSourceGraph(graph: graph),
logger: logger.contextualized(with: "index"),
configuration: configuration
configuration: configuration,
swiftVersion: swiftVersion
)
try! pipeline.perform()

Expand All @@ -68,7 +70,7 @@ open class SourceGraphTestCase: XCTestCase {
graph: graph,
logger: logger,
configuration: configuration,
swiftVersion: SwiftVersion(shell: shell)
swiftVersion: swiftVersion
).perform()
results = ScanResultBuilder.build(for: graph)
}
Expand Down