Skip to content

Merge main into release/6.0 #1199

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 39 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
2137056
Adjustment for the removal of `IncrementalEdit(offset:length:replacem…
ahoppen Apr 4, 2024
1770204
Implement test discovery for swift-testing tests for the `textDocumen…
ahoppen Apr 13, 2024
465ca45
Set time zone to the user's local time zone when using date formatters
ahoppen Apr 16, 2024
f482982
Instead of returning an empty array in `prepareTypeHierarchy`, source…
ahoppen Apr 16, 2024
a8b61a5
Introduce new refactoring code actions based on the Swift syntax tree.
DougGregor Apr 16, 2024
e13ce13
Merge pull request #1179 from DougGregor/syntax-code-action-refactorings
DougGregor Apr 17, 2024
63171ab
Merge pull request #1178 from ahoppen/nil-for-empty-prepare-type-hier…
ahoppen Apr 17, 2024
a6f74fc
Fix a race condition during the computation of `uriToWorkspaceCache`
ahoppen Apr 8, 2024
440dc62
Fix jump-to-definition to methods in swift interfaces that are in syn…
ahoppen Apr 18, 2024
b104d54
Merge pull request #1151 from ahoppen/ahoppen/swift-testing-discovery
ahoppen Apr 18, 2024
deed5e4
Remove a couple underscored properties/methods
ahoppen Apr 15, 2024
0d25ce3
Merge pull request #1170 from ahoppen/uri-to-workspace-cache-race-con…
ahoppen Apr 19, 2024
4b7d27c
Merge pull request #1187 from ahoppen/underscored-properties
ahoppen Apr 19, 2024
b9af0cf
Merge pull request #1158 from ahoppen/incremental-edit-takes-range
ahoppen Apr 19, 2024
fc8a730
Wait for indexstore-db to update after building a SwiftPM project in …
ahoppen Apr 18, 2024
2edfb2a
Slightly simplify code completion logic
ahoppen Apr 19, 2024
8f74261
Truncate log message in `NonDarwinLogger` at 10.000 characters
ahoppen Apr 18, 2024
8ed842b
Show unapplied function references in call hierarchy
ahoppen Apr 19, 2024
ce83fcb
Merge pull request #1186 from ahoppen/truncate-non-darwing-log-message
ahoppen Apr 20, 2024
3dd5045
Merge pull request #1190 from ahoppen/ahoppen/unapplied-function-refs…
ahoppen Apr 20, 2024
e1b5ffa
Make hover popover prettier
ahoppen Apr 18, 2024
94cce3c
Merge pull request #1176 from ahoppen/ahoppen/time-zone
ahoppen Apr 23, 2024
771d2a7
Merge pull request #1185 from ahoppen/ahoppen/jump-to-system-interface
ahoppen Apr 23, 2024
f9ce7ae
Merge pull request #1188 from ahoppen/poll-index-after-build-in-tests
ahoppen Apr 23, 2024
f73df6d
Merge pull request #1192 from ahoppen/completionsession-improvements
ahoppen Apr 23, 2024
17c0a44
Merge pull request #1183 from ahoppen/pretty-hover
ahoppen Apr 23, 2024
a799da3
Implement a syntactic workspace-wide test index
ahoppen Apr 16, 2024
b3c519b
Improve performance of `SyntacticTestIndex` in large projects by scan…
ahoppen Apr 15, 2024
fd7b268
Reload a file when other files within the same module or a `.swiftmod…
ahoppen Apr 17, 2024
313be88
Minor improvements to the diagnose subcommand
ahoppen Apr 23, 2024
66dd25e
Merge branch 'main' into release/6.0
ahoppen Apr 23, 2024
4805ded
Skip a few hover tests if sourcekitd doesn’t return raw documentation…
ahoppen Apr 23, 2024
10ddcb5
Revert "Adjustment for the removal of `IncrementalEdit(offset:length:…
ahoppen Apr 24, 2024
eb9b0c8
Merge pull request #1198 from ahoppen/diagnose-improvements
ahoppen Apr 24, 2024
30a3d69
Merge pull request #1200 from ahoppen/skip-hover-tests-on-old-toolchains
ahoppen Apr 24, 2024
ae215f9
Fix a bug that would cause a file to never be part of the syntactic i…
ahoppen Apr 24, 2024
c72fe50
Merge pull request #1180 from ahoppen/refresh-file-on-updated-depende…
ahoppen Apr 24, 2024
ec5c614
Merge pull request #1175 from ahoppen/syntactic-test-index
ahoppen Apr 24, 2024
b6a2008
Merge branch 'main' into 6.0/merge-main-2024-04-23
ahoppen Apr 24, 2024
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
21 changes: 12 additions & 9 deletions Sources/Diagnose/DiagnoseCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ private var progressBar: PercentProgressAnimation? = nil

/// A component of the diagnostic bundle that's collected in independent stages.
fileprivate enum BundleComponent: String, CaseIterable, ExpressibleByArgument {
case crashReports
case logs
case swiftVersions
case sourcekitdCrashes
case swiftFrontendCrashes
case crashReports = "crash-reports"
case logs = "logs"
case swiftVersions = "swift-versions"
case sourcekitdCrashes = "sourcekitd-crashes"
case swiftFrontendCrashes = "swift-frontend-crashes"
}

public struct DiagnoseCommand: AsyncParsableCommand {
Expand Down Expand Up @@ -134,6 +134,7 @@ public struct DiagnoseCommand: AsyncParsableCommand {

for crashInfo in crashInfos {
let dateFormatter = DateFormatter()
dateFormatter.timeZone = NSTimeZone.local
dateFormatter.dateStyle = .none
dateFormatter.timeStyle = .medium
let progressMessagePrefix = "Reducing Swift compiler crash at \(dateFormatter.string(from: crashInfo.date))"
Expand Down Expand Up @@ -304,7 +305,9 @@ public struct DiagnoseCommand: AsyncParsableCommand {

progressBar = PercentProgressAnimation(stream: stderrStream, header: "Diagnosing sourcekit-lsp issues")

let date = ISO8601DateFormatter().string(from: Date()).replacingOccurrences(of: ":", with: "-")
let dateFormatter = ISO8601DateFormatter()
dateFormatter.timeZone = NSTimeZone.local
let date = dateFormatter.string(from: Date()).replacingOccurrences(of: ":", with: "-")
let bundlePath = FileManager.default.temporaryDirectory
.appendingPathComponent("sourcekitd-reproducer-\(date)")
try FileManager.default.createDirectory(at: bundlePath, withIntermediateDirectories: true)
Expand All @@ -330,9 +333,9 @@ public struct DiagnoseCommand: AsyncParsableCommand {
print(
"""

Bundle created.
When filing an issue at https://github.com/apple/sourcekit-lsp/issues/new,
please attach the bundle located at
Bundle created.
When filing an issue at https://github.com/apple/sourcekit-lsp/issues/new,
please attach the bundle located at
\(bundlePath.path)
"""
)
Expand Down
2 changes: 1 addition & 1 deletion Sources/Diagnose/ReproducerBundle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func makeReproducerBundle(for requestInfo: RequestInfo, toolchain: Toolchain, bu
} else {
let request = try requestInfo.request(for: URL(fileURLWithPath: "/input.swift"))
try request.write(
to: bundlePath.appendingPathComponent("request.json"),
to: bundlePath.appendingPathComponent("request.yml"),
atomically: true,
encoding: .utf8
)
Expand Down
1 change: 1 addition & 0 deletions Sources/Diagnose/SwiftFrontendCrashScraper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ struct SwiftFrontendCrashScraper {
}
let interestingString = fileContents[firstNewline...]
let dateFormatter = DateFormatter()
dateFormatter.timeZone = NSTimeZone.local
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSSS Z"
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(dateFormatter)
Expand Down
14 changes: 12 additions & 2 deletions Sources/LSPLogging/NonDarwinLogging.swift
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,8 @@ public struct NonDarwinLogMessage: ExpressibleByStringInterpolation, Expressible
/// a new `DateFormatter` is rather expensive and its the same for all loggers.
private let dateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
dateFormatter.timeZone = NSTimeZone.local
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSSS Z"
return dateFormatter
}()

Expand Down Expand Up @@ -299,11 +300,20 @@ public struct NonDarwinLogger: Sendable {
guard level >= self.logLevel else { return }
let date = Date()
loggingQueue.async {
// Truncate log message after 10.000 characters to avoid flooding the log with huge log messages (eg. from a
// sourcekitd response). 10.000 characters was chosen because it seems to fit the result of most sourcekitd
// responses that are not generated interface or global completion results (which are a lot bigger).
var message = message().value.string(for: self.privacyLevel)
if message.utf8.count > 10_000 {
// Check for UTF-8 byte length first because that's faster since it doesn't need to count UTF-8 characters.
// Truncate using `.prefix` to avoid cutting of in the middle of a UTF-8 multi-byte character.
message = message.prefix(10_000) + "..."
}
// Start each log message with `[org.swift.sourcekit-lsp` so that it’s easy to split the log to the different messages
logHandler(
"""
[\(subsystem):\(category)] \(level) \(dateFormatter.string(from: date))
\(message().value.string(for: self.privacyLevel))
\(message)
---
"""
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,24 @@ public struct OpenInterfaceRequest: TextDocumentRequest, Hashable {
public var moduleName: String

/// The module group name.
public var groupNames: [String]
public var groupName: String?

/// The symbol USR to search for in the generated module interface.
public var symbolUSR: String?

public init(textDocument: TextDocumentIdentifier, name: String, symbolUSR: String?) {
public init(textDocument: TextDocumentIdentifier, name: String, groupName: String?, symbolUSR: String?) {
self.textDocument = textDocument
self.symbolUSR = symbolUSR
// Stdlib Swift modules are all in the "Swift" module, but their symbols return a module name `Swift.***`.
let splitName = name.split(separator: ".")
self.moduleName = String(splitName[0])
self.groupNames = [String.SubSequence](splitName.dropFirst()).map(String.init)
self.moduleName = name
self.groupName = groupName
}

/// Name of interface module name with group names appended
public var name: String {
if groupNames.count > 0 {
return "\(self.moduleName).\(self.groupNames.joined(separator: "."))"
} else {
return self.moduleName
if let groupName {
return "\(self.moduleName).\(groupName.replacing("/", with: "."))"
}
return self.moduleName
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ public struct SymbolInfoRequest: TextDocumentRequest, Hashable {
/// Detailed information about a symbol, such as the response to a `SymbolInfoRequest`
/// **(LSP Extension)**.
public struct SymbolDetails: ResponseType, Hashable {
public struct ModuleInfo: Codable, Hashable, Sendable {
/// The name of the module in which the symbol is defined.
public let moduleName: String

/// If the symbol is defined within a subgroup of a module, the name of the group. Otherwise `nil`.
public let groupName: String?

public init(moduleName: String, groupName: String? = nil) {
self.moduleName = moduleName
self.groupName = groupName
}
}

/// The name of the symbol, if any.
public var name: String?
Expand Down Expand Up @@ -87,6 +99,11 @@ public struct SymbolDetails: ResponseType, Hashable {
/// Optional because `clangd` does not return whether a symbol is dynamic.
public var isDynamic: Bool?

/// Whether this symbol is defined in the SDK or standard library.
///
/// This property only applies to Swift symbols.
public var isSystem: Bool?

/// If the symbol is dynamic, the USRs of the types that might be called.
///
/// This is relevant in the following cases
Expand All @@ -112,21 +129,31 @@ public struct SymbolDetails: ResponseType, Hashable {
/// `B` may be called dynamically.
public var receiverUsrs: [String]?

/// If the symbol is defined in a module that doesn't have source information associated with it, the name and group
/// and group name that defines this symbol.
///
/// This property only applies to Swift symbols.
public var systemModule: ModuleInfo?

public init(
name: String?,
containerName: String?,
usr: String?,
bestLocalDeclaration: Location?,
kind: SymbolKind?,
isDynamic: Bool?,
receiverUsrs: [String]?
isSystem: Bool?,
receiverUsrs: [String]?,
systemModule: ModuleInfo?
) {
self.name = name
self.containerName = containerName
self.usr = usr
self.bestLocalDeclaration = bestLocalDeclaration
self.kind = kind
self.isDynamic = isDynamic
self.isSystem = isSystem
self.receiverUsrs = receiverUsrs
self.systemModule = systemModule
}
}
10 changes: 10 additions & 0 deletions Sources/LanguageServerProtocol/SupportTypes/TestItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ public struct TestItem: ResponseType, Equatable {
/// When `nil` the `label` is used.
public let sortText: String?

/// Whether the test is disabled.
public let disabled: Bool

/// The type of test, eg. the testing framework that was used to declare the test.
public let style: String

/// The location of the test item in the source code.
public let location: Location

Expand All @@ -55,6 +61,8 @@ public struct TestItem: ResponseType, Equatable {
label: String,
description: String? = nil,
sortText: String? = nil,
disabled: Bool,
style: String,
location: Location,
children: [TestItem],
tags: [TestTag]
Expand All @@ -63,6 +71,8 @@ public struct TestItem: ResponseType, Equatable {
self.label = label
self.description = description
self.sortText = sortText
self.disabled = disabled
self.style = style
self.location = location
self.children = children
self.tags = tags
Expand Down
11 changes: 11 additions & 0 deletions Sources/SKCore/BuildServerBuildSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,17 @@ extension BuildServerBuildSystem: BuildSystem {

return .unhandled
}

public func testFiles() async -> [DocumentURI] {
// BuildServerBuildSystem does not support syntactic test discovery
// (https://github.com/apple/sourcekit-lsp/issues/1173).
return []
}

public func addTestFilesDidChangeCallback(_ callback: @escaping () async -> Void) {
// BuildServerBuildSystem does not support syntactic test discovery
// (https://github.com/apple/sourcekit-lsp/issues/1173).
}
}

private func loadBuildServerConfig(path: AbsolutePath, fileSystem: FileSystem) throws -> BuildServerConfig {
Expand Down
12 changes: 12 additions & 0 deletions Sources/SKCore/BuildSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,18 @@ public protocol BuildSystem: AnyObject, Sendable {
func filesDidChange(_ events: [FileEvent]) async

func fileHandlingCapability(for uri: DocumentURI) async -> FileHandlingCapability

/// Returns the list of files that might contain test cases.
///
/// The returned file list is an over-approximation. It might contain tests from non-test targets or files that don't
/// actually contain any tests. Keeping this list as minimal as possible helps reduce the amount of work that the
/// syntactic test indexer needs to perform.
func testFiles() async -> [DocumentURI]

/// Adds a callback that should be called when the value returned by `testFiles()` changes.
///
/// The callback might also be called without an actual change to `testFiles`.
func addTestFilesDidChangeCallback(_ callback: @Sendable @escaping () async -> Void) async
}

public let buildTargetsNotSupported =
Expand Down
28 changes: 11 additions & 17 deletions Sources/SKCore/BuildSystemManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ public actor BuildSystemManager {
let fallbackBuildSystem: FallbackBuildSystem?

/// Provider of file to main file mappings.
var _mainFilesProvider: MainFilesProvider?
var mainFilesProvider: MainFilesProvider?

/// Build system delegate that will receive notifications about setting changes, etc.
var _delegate: BuildSystemDelegate?
var delegate: BuildSystemDelegate?

/// The root of the project that this build system manages. For example, for SwiftPM packages, this is the folder
/// containing Package.swift. For compilation databases it is the root folder based on which the compilation database
Expand All @@ -71,7 +71,7 @@ public actor BuildSystemManager {
precondition(!buildSystemHasDelegate)
self.buildSystem = buildSystem
self.fallbackBuildSystem = fallbackBuildSystem
self._mainFilesProvider = mainFilesProvider
self.mainFilesProvider = mainFilesProvider
self.fallbackSettingsTimeout = fallbackSettingsTimeout
await self.buildSystem?.setDelegate(self)
}
Expand All @@ -82,21 +82,11 @@ public actor BuildSystemManager {
}

extension BuildSystemManager {
public var delegate: BuildSystemDelegate? {
get { _delegate }
set { _delegate = newValue }
}

/// - Note: Needed so we can set the delegate from a different isolation context.
public func setDelegate(_ delegate: BuildSystemDelegate?) {
self.delegate = delegate
}

public var mainFilesProvider: MainFilesProvider? {
get { _mainFilesProvider }
set { _mainFilesProvider = newValue }
}

/// - Note: Needed so we can set the delegate from a different isolation context.
public func setMainFilesProvider(_ mainFilesProvider: MainFilesProvider?) {
self.mainFilesProvider = mainFilesProvider
Expand Down Expand Up @@ -186,6 +176,10 @@ extension BuildSystemManager {
fallbackBuildSystem != nil ? .fallback : .unhandled
)
}

public func testFiles() async -> [DocumentURI] {
return await buildSystem?.testFiles() ?? []
}
}

extension BuildSystemManager: BuildSystemDelegate {
Expand All @@ -204,15 +198,15 @@ extension BuildSystemManager: BuildSystemDelegate {
public func fileBuildSettingsChanged(_ changedFiles: Set<DocumentURI>) async {
let changedWatchedFiles = watchedFilesReferencing(mainFiles: changedFiles)

if !changedWatchedFiles.isEmpty, let delegate = self._delegate {
if !changedWatchedFiles.isEmpty, let delegate = self.delegate {
await delegate.fileBuildSettingsChanged(changedWatchedFiles)
}
}

public func filesDependenciesUpdated(_ changedFiles: Set<DocumentURI>) async {
// Empty changes --> assume everything has changed.
guard !changedFiles.isEmpty else {
if let delegate = self._delegate {
if let delegate = self.delegate {
await delegate.filesDependenciesUpdated(changedFiles)
}
return
Expand All @@ -226,13 +220,13 @@ extension BuildSystemManager: BuildSystemDelegate {
}

public func buildTargetsChanged(_ changes: [BuildTargetEvent]) async {
if let delegate = self._delegate {
if let delegate = self.delegate {
await delegate.buildTargetsChanged(changes)
}
}

public func fileHandlingCapabilityChanged() async {
if let delegate = self._delegate {
if let delegate = self.delegate {
await delegate.fileHandlingCapabilityChanged()
}
}
Expand Down
1 change: 1 addition & 0 deletions Sources/SKCore/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ add_library(SKCore STATIC
BuildSystemManager.swift
CompilationDatabase.swift
CompilationDatabaseBuildSystem.swift
Debouncer.swift
FallbackBuildSystem.swift
FileBuildSettings.swift
MainFilesProvider.swift
Expand Down
14 changes: 14 additions & 0 deletions Sources/SKCore/CompilationDatabaseBuildSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ public actor CompilationDatabaseBuildSystem {
/// Delegate to handle any build system events.
public weak var delegate: BuildSystemDelegate? = nil

/// Callbacks that should be called if the list of possible test files has changed.
public var testFilesDidChangeCallbacks: [() async -> Void] = []

public func setDelegate(_ delegate: BuildSystemDelegate?) async {
self.delegate = delegate
}
Expand Down Expand Up @@ -167,6 +170,9 @@ extension CompilationDatabaseBuildSystem: BuildSystem {
if let delegate = self.delegate {
await delegate.fileBuildSettingsChanged(self.watchedFiles)
}
for testFilesDidChangeCallback in testFilesDidChangeCallbacks {
await testFilesDidChangeCallback()
}
}

public func filesDidChange(_ events: [FileEvent]) async {
Expand All @@ -185,4 +191,12 @@ extension CompilationDatabaseBuildSystem: BuildSystem {
return .unhandled
}
}

public func testFiles() async -> [DocumentURI] {
return compdb?.allCommands.map { DocumentURI($0.url) } ?? []
}

public func addTestFilesDidChangeCallback(_ callback: @escaping () async -> Void) async {
testFilesDidChangeCallbacks.append(callback)
}
}
Loading