Skip to content

Commit 53ea6d9

Browse files
authored
Merge pull request #1147 from ahoppen/ahoppen/vendor-main
[6.0] Merge changes from `main`
2 parents 91f2914 + e0d1e96 commit 53ea6d9

File tree

106 files changed

+2471
-1443
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

106 files changed

+2471
-1443
lines changed

Package.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ let package = Package(
119119
"LanguageServerProtocol",
120120
"LSPLogging",
121121
],
122-
exclude: ["CMakeLists.txt"]
122+
exclude: ["CMakeLists.txt"],
123+
swiftSettings: [.enableExperimentalFeature("StrictConcurrency")]
123124
),
124125

125126
.testTarget(
@@ -177,7 +178,8 @@ let package = Package(
177178
.product(name: "SwiftPMDataModel-auto", package: "swift-package-manager"),
178179
.product(name: "SwiftToolsSupport-auto", package: "swift-tools-support-core"),
179180
],
180-
exclude: ["CMakeLists.txt"]
181+
exclude: ["CMakeLists.txt"],
182+
swiftSettings: [.enableExperimentalFeature("StrictConcurrency")]
181183
),
182184

183185
.testTarget(
@@ -224,7 +226,8 @@ let package = Package(
224226
.product(name: "SwiftPM-auto", package: "swift-package-manager"),
225227
.product(name: "SwiftToolsSupport-auto", package: "swift-tools-support-core"),
226228
],
227-
exclude: ["CMakeLists.txt"]
229+
exclude: ["CMakeLists.txt"],
230+
swiftSettings: [.enableExperimentalFeature("StrictConcurrency")]
228231
),
229232

230233
.testTarget(

Sources/Diagnose/CMakeLists.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
add_library(Diagnose STATIC
22
CommandLineArgumentsReducer.swift
33
DiagnoseCommand.swift
4+
MergeSwiftFiles.swift
45
OSLogScraper.swift
56
ReduceCommand.swift
7+
ReduceFrontendCommand.swift
8+
ReduceSourceKitDRequest.swift
9+
ReduceSwiftFrontend.swift
610
ReductionError.swift
711
ReproducerBundle.swift
812
RequestInfo.swift
913
SourceKitD+RunWithYaml.swift
1014
SourceKitDRequestExecutor.swift
15+
SourceReducer.swift
1116
SourcekitdRequestCommand.swift
12-
SourceReducer.swift)
17+
SwiftFrontendCrashScraper.swift
18+
Toolchain+SwiftFrontend.swift)
1319

1420
set_target_properties(Diagnose PROPERTIES
1521
INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY})

Sources/Diagnose/CommandLineArgumentsReducer.swift

Lines changed: 54 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
import Foundation
14+
import LSPLogging
1415

1516
// MARK: - Entry point
1617

@@ -34,9 +35,6 @@ fileprivate class CommandLineArgumentReducer {
3435
/// still crashes.
3536
private let sourcekitdExecutor: SourceKitRequestExecutor
3637

37-
/// The file to which we write the reduced source code.
38-
private let temporarySourceFile: URL
39-
4038
/// A callback to be called when the reducer has made progress reducing the request
4139
private let progressUpdate: (_ progress: Double, _ message: String) -> Void
4240

@@ -48,69 +46,68 @@ fileprivate class CommandLineArgumentReducer {
4846
progressUpdate: @escaping (_ progress: Double, _ message: String) -> Void
4947
) {
5048
self.sourcekitdExecutor = sourcekitdExecutor
51-
self.temporarySourceFile = FileManager.default.temporaryDirectory.appendingPathComponent("reduce-\(UUID()).swift")
5249
self.progressUpdate = progressUpdate
5350
}
5451

55-
deinit {
56-
try? FileManager.default.removeItem(at: temporarySourceFile)
52+
func run(initialRequestInfo: RequestInfo) async throws -> RequestInfo {
53+
var requestInfo = initialRequestInfo
54+
requestInfo = try await reduce(initialRequestInfo: requestInfo, simultaneousRemove: 10)
55+
requestInfo = try await reduce(initialRequestInfo: requestInfo, simultaneousRemove: 1)
56+
return requestInfo
5757
}
5858

59-
func logSuccessfulReduction(_ requestInfo: RequestInfo) {
60-
progressUpdate(
61-
1 - (Double(requestInfo.compilerArgs.count) / Double(initialCommandLineCount)),
62-
"Reduced compiler arguments to \(requestInfo.compilerArgs.count)"
63-
)
64-
}
59+
/// Reduce the command line arguments of the given `RequestInfo`.
60+
///
61+
/// If `simultaneousRemove` is set, the reducer will try to remove that many arguments at once. This is useful to
62+
/// quickly remove multiple arguments from the request.
63+
private func reduce(initialRequestInfo: RequestInfo, simultaneousRemove: Int) async throws -> RequestInfo {
64+
guard initialRequestInfo.compilerArgs.count > simultaneousRemove else {
65+
// Trying to remove more command line arguments than we have. This isn't going to work.
66+
return initialRequestInfo
67+
}
6568

66-
func run(initialRequestInfo: RequestInfo) async throws -> RequestInfo {
67-
try initialRequestInfo.fileContents.write(to: temporarySourceFile, atomically: true, encoding: .utf8)
6869
var requestInfo = initialRequestInfo
6970
self.initialCommandLineCount = requestInfo.compilerArgs.count
7071

7172
var argumentIndexToRemove = requestInfo.compilerArgs.count - 1
72-
while argumentIndexToRemove >= 0 {
73-
var numberOfArgumentsToRemove = 1
73+
while argumentIndexToRemove + 1 >= simultaneousRemove {
74+
defer {
75+
// argumentIndexToRemove can become negative by being decremented in the code below
76+
let progress = 1 - (Double(max(argumentIndexToRemove, 0)) / Double(initialCommandLineCount))
77+
progressUpdate(progress, "Reduced compiler arguments to \(requestInfo.compilerArgs.count)")
78+
}
79+
var numberOfArgumentsToRemove = simultaneousRemove
7480
// If the argument is preceded by -Xswiftc or -Xcxx, we need to remove the `-X` flag as well.
75-
if argumentIndexToRemove - numberOfArgumentsToRemove >= 0
76-
&& requestInfo.compilerArgs[argumentIndexToRemove - numberOfArgumentsToRemove].hasPrefix("-X")
77-
{
81+
if requestInfo.compilerArgs[safe: argumentIndexToRemove - numberOfArgumentsToRemove]?.hasPrefix("-X") ?? false {
7882
numberOfArgumentsToRemove += 1
7983
}
8084

81-
if let reduced = try await tryRemoving(
82-
(argumentIndexToRemove - numberOfArgumentsToRemove + 1)...argumentIndexToRemove,
83-
from: requestInfo
84-
) {
85+
let rangeToRemove = (argumentIndexToRemove - numberOfArgumentsToRemove + 1)...argumentIndexToRemove
86+
if let reduced = try await tryRemoving(rangeToRemove, from: requestInfo) {
8587
requestInfo = reduced
8688
argumentIndexToRemove -= numberOfArgumentsToRemove
8789
continue
8890
}
8991

90-
// If removing the argument failed and the argument is preceded by an argument starting with `-`, try removing that as well.
91-
// E.g. removing `-F` followed by a search path.
92-
if argumentIndexToRemove - numberOfArgumentsToRemove >= 0
93-
&& requestInfo.compilerArgs[argumentIndexToRemove - numberOfArgumentsToRemove].hasPrefix("-")
94-
{
92+
// If removing the argument failed and the argument is preceded by an argument starting with `-`, try removing
93+
// that as well. E.g. removing `-F` followed by a search path.
94+
if requestInfo.compilerArgs[safe: argumentIndexToRemove - numberOfArgumentsToRemove]?.hasPrefix("-") ?? false {
9595
numberOfArgumentsToRemove += 1
96-
}
9796

98-
// If the argument is preceded by -Xswiftc or -Xcxx, we need to remove the `-X` flag as well.
99-
if argumentIndexToRemove - numberOfArgumentsToRemove >= 0
100-
&& requestInfo.compilerArgs[argumentIndexToRemove - numberOfArgumentsToRemove].hasPrefix("-X")
101-
{
102-
numberOfArgumentsToRemove += 1
97+
// If the argument is preceded by -Xswiftc or -Xcxx, we need to remove the `-X` flag as well.
98+
if requestInfo.compilerArgs[safe: argumentIndexToRemove - numberOfArgumentsToRemove]?.hasPrefix("-X") ?? false {
99+
numberOfArgumentsToRemove += 1
100+
}
101+
102+
let rangeToRemove = (argumentIndexToRemove - numberOfArgumentsToRemove + 1)...argumentIndexToRemove
103+
if let reduced = try await tryRemoving(rangeToRemove, from: requestInfo) {
104+
requestInfo = reduced
105+
argumentIndexToRemove -= numberOfArgumentsToRemove
106+
continue
107+
}
103108
}
104109

105-
if let reduced = try await tryRemoving(
106-
(argumentIndexToRemove - numberOfArgumentsToRemove + 1)...argumentIndexToRemove,
107-
from: requestInfo
108-
) {
109-
requestInfo = reduced
110-
argumentIndexToRemove -= numberOfArgumentsToRemove
111-
continue
112-
}
113-
argumentIndexToRemove -= 1
110+
argumentIndexToRemove -= simultaneousRemove
114111
}
115112

116113
return requestInfo
@@ -120,16 +117,28 @@ fileprivate class CommandLineArgumentReducer {
120117
_ argumentsToRemove: ClosedRange<Int>,
121118
from requestInfo: RequestInfo
122119
) async throws -> RequestInfo? {
120+
logger.debug("Try removing the following compiler arguments:\n\(requestInfo.compilerArgs[argumentsToRemove])")
123121
var reducedRequestInfo = requestInfo
124122
reducedRequestInfo.compilerArgs.removeSubrange(argumentsToRemove)
125123

126-
let result = try await sourcekitdExecutor.run(request: reducedRequestInfo.request(for: temporarySourceFile))
124+
let result = try await sourcekitdExecutor.run(request: reducedRequestInfo)
127125
if case .reproducesIssue = result {
128-
logSuccessfulReduction(reducedRequestInfo)
126+
logger.debug("Reduction successful")
129127
return reducedRequestInfo
130128
} else {
131129
// The reduced request did not crash. We did not find a reduced test case, so return `nil`.
130+
logger.debug("Reduction did not reproduce the issue")
131+
return nil
132+
}
133+
}
134+
}
135+
136+
fileprivate extension Array {
137+
/// Access index in the array if it's in bounds or return `nil` if `index` is outside of the array's bounds.
138+
subscript(safe index: Int) -> Element? {
139+
if index < 0 || index >= count {
132140
return nil
133141
}
142+
return self[index]
134143
}
135144
}

0 commit comments

Comments
 (0)