Skip to content

Commit 2be4e73

Browse files
authored
Merge pull request swiftlang#1838 from cwakamo/eng/PR-146875054-add-more-parameters-getSingleFrontendInvocationFromDriverArguments
Added a getSingleFrontendInvocationFromDriverArgumentsV3 function whi…
2 parents 78956df + deb32b2 commit 2be4e73

File tree

3 files changed

+134
-19
lines changed

3 files changed

+134
-19
lines changed

Sources/SwiftDriver/ToolingInterface/SimpleExecutor.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,20 @@ import class TSCBasic.Process
2020
/// TODO: It would be nice if build planning did not involve an executor.
2121
/// We must hunt down all uses of an executor during planning and move
2222
/// relevant compiler functionality into libSwiftScan.
23-
internal class SimpleExecutor: DriverExecutor {
24-
let resolver: ArgsResolver
23+
@_spi(Testing) public class SimpleExecutor: DriverExecutor {
24+
public let resolver: ArgsResolver
2525
let fileSystem: FileSystem
2626
let env: [String: String]
2727

28-
init(resolver: ArgsResolver, fileSystem: FileSystem, env: [String: String]) {
28+
public init(resolver: ArgsResolver, fileSystem: FileSystem, env: [String: String]) {
2929
self.resolver = resolver
3030
self.fileSystem = fileSystem
3131
self.env = env
3232
}
3333

34-
func execute(job: Job,
35-
forceResponseFiles: Bool,
36-
recordedInputModificationDates: [TypedVirtualPath : TimePoint]) throws -> ProcessResult {
34+
public func execute(job: Job,
35+
forceResponseFiles: Bool,
36+
recordedInputModificationDates: [TypedVirtualPath : TimePoint]) throws -> ProcessResult {
3737
let arguments: [String] = try resolver.resolveArgumentList(for: job,
3838
useResponseFiles: .heuristic)
3939
var childEnv = env
@@ -42,17 +42,17 @@ internal class SimpleExecutor: DriverExecutor {
4242
return try process.waitUntilExit()
4343
}
4444

45-
func execute(workload: DriverExecutorWorkload, delegate: JobExecutionDelegate,
46-
numParallelJobs: Int, forceResponseFiles: Bool,
47-
recordedInputModificationDates: [TypedVirtualPath : TimePoint]) throws {
45+
public func execute(workload: DriverExecutorWorkload, delegate: JobExecutionDelegate,
46+
numParallelJobs: Int, forceResponseFiles: Bool,
47+
recordedInputModificationDates: [TypedVirtualPath : TimePoint]) throws {
4848
fatalError("Unsupported operation on current executor")
4949
}
5050

51-
func checkNonZeroExit(args: String..., environment: [String : String]) throws -> String {
51+
public func checkNonZeroExit(args: String..., environment: [String : String]) throws -> String {
5252
try Process.checkNonZeroExit(arguments: args, environment: environment)
5353
}
5454

55-
func description(of job: Job, forceResponseFiles: Bool) throws -> String {
55+
public func description(of job: Job, forceResponseFiles: Bool) throws -> String {
5656
let useResponseFiles : ResponseFileHandling = forceResponseFiles ? .forced : .heuristic
5757
let (args, usedResponseFile) = try resolver.resolveArgumentList(for: job, useResponseFiles: useResponseFiles)
5858
var result = args.map { $0.spm_shellEscaped() }.joined(separator: " ")

Sources/SwiftDriver/ToolingInterface/ToolingUtil.swift

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import class TSCBasic.DiagnosticsEngine
1414
import struct TSCBasic.Diagnostic
1515
import class TSCBasic.ProcessSet
1616
import enum TSCBasic.ProcessEnv
17+
import struct TSCBasic.ProcessEnvironmentBlock
1718
import var TSCBasic.localFileSystem
1819
import SwiftOptions
1920

@@ -79,6 +80,28 @@ public func getSingleFrontendInvocationFromDriverArgumentsV3(driverPath: UnsafeP
7980
return result
8081
}
8182

83+
public func getSingleFrontendInvocationFromDriverArgumentsV2(driverPath: String,
84+
argList: [String],
85+
action: ([String]) -> Bool,
86+
diagnostics: inout [Diagnostic],
87+
diagnosticCallback: @escaping (CInt, String) -> Void,
88+
compilerIntegratedTooling: Bool = false,
89+
forceNoOutputs: Bool = false) -> Bool {
90+
let env = ProcessEnv.vars
91+
let executor: SimpleExecutor
92+
do {
93+
let resolver = try ArgsResolver(fileSystem: localFileSystem)
94+
executor = SimpleExecutor(resolver: resolver,
95+
fileSystem: localFileSystem,
96+
env: env)
97+
} catch {
98+
print("Unexpected error: \(error)")
99+
return true
100+
}
101+
102+
return getSingleFrontendInvocationFromDriverArgumentsV3(driverPath: driverPath, argList: argList, action: action, diagnostics: &diagnostics, diagnosticCallback: diagnosticCallback, env: env, executor: executor, compilerIntegratedTooling: compilerIntegratedTooling, forceNoOutputs: forceNoOutputs)
103+
}
104+
82105
/// Generates the list of arguments that would be passed to the compiler
83106
/// frontend from the given driver arguments, for a single-compiler-invocation
84107
/// context.
@@ -97,11 +120,13 @@ public func getSingleFrontendInvocationFromDriverArgumentsV3(driverPath: UnsafeP
97120
///
98121
/// \note This function is not intended to create invocations which are
99122
/// suitable for use in REPL or immediate modes.
100-
public func getSingleFrontendInvocationFromDriverArgumentsV2(driverPath: String,
123+
public func getSingleFrontendInvocationFromDriverArgumentsV3(driverPath: String,
101124
argList: [String],
102125
action: ([String]) -> Bool,
103126
diagnostics: inout [Diagnostic],
104127
diagnosticCallback: @escaping (CInt, String) -> Void,
128+
env: [String: String],
129+
executor: some DriverExecutor,
105130
compilerIntegratedTooling: Bool = false,
106131
forceNoOutputs: Bool = false) -> Bool {
107132
/// Handler for emitting diagnostics to tooling clients.
@@ -160,11 +185,8 @@ public func getSingleFrontendInvocationFromDriverArgumentsV2(driverPath: String,
160185
}
161186

162187
// Instantiate the driver, setting up the toolchain in the process, etc.
163-
let resolver = try ArgsResolver(fileSystem: localFileSystem)
164-
let executor = SimpleExecutor(resolver: resolver,
165-
fileSystem: localFileSystem,
166-
env: ProcessEnv.vars)
167188
var driver = try Driver(args: parsedOptions.commandLine,
189+
env: env,
168190
diagnosticsOutput: .engine(diagnosticsEngine),
169191
executor: executor,
170192
compilerIntegratedTooling: compilerIntegratedTooling)
@@ -185,8 +207,7 @@ public func getSingleFrontendInvocationFromDriverArgumentsV2(driverPath: String,
185207
diagnosticsEngine.emit(.error_expected_frontend_command())
186208
return true
187209
}
188-
singleFrontendTaskCommand = try executor.description(of: compileJob,
189-
forceResponseFiles: false).components(separatedBy: " ")
210+
singleFrontendTaskCommand = try executor.resolver.resolveArgumentList(for: compileJob, useResponseFiles: .disabled)
190211
} catch {
191212
print("Unexpected error: \(error).")
192213
return true

Tests/SwiftDriverTests/SwiftDriverToolingInterfaceTests.swift

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import XCTest
1616
import CToolingTestShim
1717

1818
final class SwiftDriverToolingInterfaceTests: XCTestCase {
19-
func testCreateCompilerInvocation() throws {
19+
func testCreateCompilerInvocationV2() throws {
2020
try withTemporaryDirectory { path in
2121
let inputFile = path.appending(components: "test.swift")
2222
try localFileSystem.writeFileContents(inputFile) { $0.send("public func foo()") }
@@ -93,6 +93,100 @@ final class SwiftDriverToolingInterfaceTests: XCTestCase {
9393
}
9494
}
9595

96+
func testCreateCompilerInvocationV3() throws {
97+
try withTemporaryDirectory { path in
98+
let inputFile = path.appending(components: "test.swift")
99+
try localFileSystem.writeFileContents(inputFile) { $0.send("public func foo()") }
100+
101+
let env = ProcessEnv.vars
102+
let resolver = try ArgsResolver(fileSystem: localFileSystem)
103+
let executor = SimpleExecutor(resolver: resolver, fileSystem: localFileSystem, env: env)
104+
105+
// Expected success scenarios:
106+
do {
107+
let testCommand = inputFile.description
108+
var emittedDiagnostics: [Diagnostic] = []
109+
XCTAssertFalse(getSingleFrontendInvocationFromDriverArgumentsV3(driverPath: "swiftc",
110+
argList: testCommand.components(separatedBy: " "),
111+
action: { _ in false },
112+
diagnostics: &emittedDiagnostics,
113+
diagnosticCallback: {_,_ in },
114+
env: env,
115+
executor: executor))
116+
}
117+
do {
118+
let testCommand = "-emit-executable " + inputFile.description + " main.swift lib.swift -module-name createCompilerInvocation -emit-module -emit-objc-header -o t.out"
119+
var emittedDiagnostics: [Diagnostic] = []
120+
XCTAssertFalse(getSingleFrontendInvocationFromDriverArgumentsV3(driverPath: "swiftc",
121+
argList: testCommand.components(separatedBy: " "),
122+
action: { _ in false },
123+
diagnostics: &emittedDiagnostics,
124+
diagnosticCallback: {_,_ in },
125+
env: env,
126+
executor: executor))
127+
}
128+
do {
129+
let testCommand = "-c " + inputFile.description + " main.swift lib.swift -module-name createCompilerInvocation -emit-module -emit-objc-header"
130+
var emittedDiagnostics: [Diagnostic] = []
131+
XCTAssertFalse(getSingleFrontendInvocationFromDriverArgumentsV3(driverPath: "swiftc",
132+
argList: testCommand.components(separatedBy: " "),
133+
action: { _ in false },
134+
diagnostics: &emittedDiagnostics,
135+
diagnosticCallback: {_,_ in },
136+
env: env,
137+
executor: executor))
138+
}
139+
do {
140+
let testCommand = inputFile.description + " -enable-batch-mode"
141+
var emittedDiagnostics: [Diagnostic] = []
142+
XCTAssertFalse(getSingleFrontendInvocationFromDriverArgumentsV3(driverPath: "swiftc",
143+
argList: testCommand.components(separatedBy: " "),
144+
action: { _ in false },
145+
diagnostics: &emittedDiagnostics,
146+
diagnosticCallback: {_,_ in },
147+
env: env,
148+
executor: executor))
149+
}
150+
do { // Force no outputs
151+
let testCommand = "-module-name foo -emit-module -emit-module-path /tmp/foo.swiftmodule -emit-objc-header -emit-objc-header-path /tmp/foo.h -enable-library-evolution -emit-module-interface -emit-module-interface-path /tmp/foo.swiftinterface -emit-library -emit-tbd -emit-tbd-path /tmp/foo.tbd -emit-dependencies -serialize-diagnostics " + inputFile.description
152+
var resultingFrontendArgs: [String] = []
153+
var emittedDiagnostics: [Diagnostic] = []
154+
XCTAssertFalse(getSingleFrontendInvocationFromDriverArgumentsV3(driverPath: "swiftc",
155+
argList: testCommand.components(separatedBy: " "),
156+
action: { args in
157+
resultingFrontendArgs = args
158+
return false
159+
},
160+
diagnostics: &emittedDiagnostics,
161+
diagnosticCallback: {_,_ in },
162+
env: env,
163+
executor: executor,
164+
forceNoOutputs: true))
165+
XCTAssertFalse(resultingFrontendArgs.contains("-emit-module-interface-path"))
166+
XCTAssertFalse(resultingFrontendArgs.contains("-emit-objc-header"))
167+
XCTAssertFalse(resultingFrontendArgs.contains("-emit-objc-header-path"))
168+
XCTAssertFalse(resultingFrontendArgs.contains("-emit-module-path"))
169+
XCTAssertFalse(resultingFrontendArgs.contains("-emit-tbd-path"))
170+
}
171+
172+
// Expected failure scenarios:
173+
do {
174+
let testCommand = "-v" // No inputs
175+
var emittedDiagnostics: [Diagnostic] = []
176+
XCTAssertTrue(getSingleFrontendInvocationFromDriverArgumentsV3(driverPath: "swiftc",
177+
argList: testCommand.components(separatedBy: " "),
178+
action: { _ in false },
179+
diagnostics: &emittedDiagnostics,
180+
diagnosticCallback: {_,_ in },
181+
env: env,
182+
executor: executor))
183+
let errorMessage = try XCTUnwrap(emittedDiagnostics.first?.message.text)
184+
XCTAssertEqual(errorMessage, "unable to handle compilation, expected exactly one frontend job")
185+
}
186+
}
187+
}
188+
189+
96190
func testCreateCompilerInvocationCAPI() throws {
97191
try withTemporaryDirectory { path in
98192
let inputFile = path.appending(components: "test.swift")

0 commit comments

Comments
 (0)