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
19 changes: 17 additions & 2 deletions Sources/SwiftDriver/ToolingInterface/ToolingUtil.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import class TSCBasic.ProcessSet
import enum TSCBasic.ProcessEnv
import struct TSCBasic.ProcessEnvironmentBlock
import var TSCBasic.localFileSystem
import struct TSCBasic.AbsolutePath
import SwiftOptions

//typedef enum {
Expand Down Expand Up @@ -102,6 +103,18 @@ public func getSingleFrontendInvocationFromDriverArgumentsV2(driverPath: String,
return getSingleFrontendInvocationFromDriverArgumentsV3(driverPath: driverPath, argList: argList, action: action, diagnostics: &diagnostics, diagnosticCallback: diagnosticCallback, env: env, executor: executor, compilerIntegratedTooling: compilerIntegratedTooling, forceNoOutputs: forceNoOutputs)
}

public func getSingleFrontendInvocationFromDriverArgumentsV3(driverPath: String,
argList: [String],
action: ([String]) -> Bool,
diagnostics: inout [Diagnostic],
diagnosticCallback: @escaping (CInt, String) -> Void,
env: [String: String],
executor: some DriverExecutor,
compilerIntegratedTooling: Bool = false,
forceNoOutputs: Bool = false) -> Bool {
return getSingleFrontendInvocationFromDriverArgumentsV4(driverPath: driverPath, argList: argList, action: action, diagnostics: &diagnostics, diagnosticCallback: diagnosticCallback, env: env, executor: executor, compilerIntegratedTooling: compilerIntegratedTooling, compilerExecutableDir: nil, forceNoOutputs: forceNoOutputs)
}

/// Generates the list of arguments that would be passed to the compiler
/// frontend from the given driver arguments, for a single-compiler-invocation
/// context.
Expand All @@ -120,14 +133,15 @@ public func getSingleFrontendInvocationFromDriverArgumentsV2(driverPath: String,
///
/// \note This function is not intended to create invocations which are
/// suitable for use in REPL or immediate modes.
public func getSingleFrontendInvocationFromDriverArgumentsV3(driverPath: String,
public func getSingleFrontendInvocationFromDriverArgumentsV4(driverPath: String,
argList: [String],
action: ([String]) -> Bool,
diagnostics: inout [Diagnostic],
diagnosticCallback: @escaping (CInt, String) -> Void,
env: [String: String],
executor: some DriverExecutor,
compilerIntegratedTooling: Bool = false,
compilerExecutableDir: AbsolutePath? = nil,
forceNoOutputs: Bool = false) -> Bool {
/// Handler for emitting diagnostics to tooling clients.
let toolingDiagnosticsHandler: DiagnosticsEngine.DiagnosticsHandler = { diagnostic in
Expand Down Expand Up @@ -189,7 +203,8 @@ public func getSingleFrontendInvocationFromDriverArgumentsV3(driverPath: String,
env: env,
diagnosticsOutput: .engine(diagnosticsEngine),
executor: executor,
compilerIntegratedTooling: compilerIntegratedTooling)
compilerIntegratedTooling: compilerIntegratedTooling,
compilerExecutableDir: compilerExecutableDir)
if diagnosticsEngine.hasErrors {
return true
}
Expand Down
92 changes: 92 additions & 0 deletions Tests/SwiftDriverTests/SwiftDriverToolingInterfaceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,98 @@ final class SwiftDriverToolingInterfaceTests: XCTestCase {
}
}

func testCreateCompilerInvocationV4() throws {
try withTemporaryDirectory { path in
let inputFile = path.appending(components: "test.swift")
try localFileSystem.writeFileContents(inputFile) { $0.send("public func foo()") }

let env = ProcessEnv.vars
let resolver = try ArgsResolver(fileSystem: localFileSystem)
let executor = SimpleExecutor(resolver: resolver, fileSystem: localFileSystem, env: env)

// Expected success scenarios:
do {
let testCommand = inputFile.description
var emittedDiagnostics: [Diagnostic] = []
XCTAssertFalse(getSingleFrontendInvocationFromDriverArgumentsV4(driverPath: "swiftc",
argList: testCommand.components(separatedBy: " "),
action: { _ in false },
diagnostics: &emittedDiagnostics,
diagnosticCallback: {_,_ in },
env: env,
executor: executor))
}
do {
let testCommand = "-emit-executable " + inputFile.description + " main.swift lib.swift -module-name createCompilerInvocation -emit-module -emit-objc-header -o t.out"
var emittedDiagnostics: [Diagnostic] = []
XCTAssertFalse(getSingleFrontendInvocationFromDriverArgumentsV4(driverPath: "swiftc",
argList: testCommand.components(separatedBy: " "),
action: { _ in false },
diagnostics: &emittedDiagnostics,
diagnosticCallback: {_,_ in },
env: env,
executor: executor))
}
do {
let testCommand = "-c " + inputFile.description + " main.swift lib.swift -module-name createCompilerInvocation -emit-module -emit-objc-header"
var emittedDiagnostics: [Diagnostic] = []
XCTAssertFalse(getSingleFrontendInvocationFromDriverArgumentsV4(driverPath: "swiftc",
argList: testCommand.components(separatedBy: " "),
action: { _ in false },
diagnostics: &emittedDiagnostics,
diagnosticCallback: {_,_ in },
env: env,
executor: executor))
}
do {
let testCommand = inputFile.description + " -enable-batch-mode"
var emittedDiagnostics: [Diagnostic] = []
XCTAssertFalse(getSingleFrontendInvocationFromDriverArgumentsV4(driverPath: "swiftc",
argList: testCommand.components(separatedBy: " "),
action: { _ in false },
diagnostics: &emittedDiagnostics,
diagnosticCallback: {_,_ in },
env: env,
executor: executor))
}
do { // Force no outputs
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
var resultingFrontendArgs: [String] = []
var emittedDiagnostics: [Diagnostic] = []
XCTAssertFalse(getSingleFrontendInvocationFromDriverArgumentsV4(driverPath: "swiftc",
argList: testCommand.components(separatedBy: " "),
action: { args in
resultingFrontendArgs = args
return false
},
diagnostics: &emittedDiagnostics,
diagnosticCallback: {_,_ in },
env: env,
executor: executor,
forceNoOutputs: true))
XCTAssertFalse(resultingFrontendArgs.contains("-emit-module-interface-path"))
XCTAssertFalse(resultingFrontendArgs.contains("-emit-objc-header"))
XCTAssertFalse(resultingFrontendArgs.contains("-emit-objc-header-path"))
XCTAssertFalse(resultingFrontendArgs.contains("-emit-module-path"))
XCTAssertFalse(resultingFrontendArgs.contains("-emit-tbd-path"))
}

// Expected failure scenarios:
do {
let testCommand = "-v" // No inputs
var emittedDiagnostics: [Diagnostic] = []
XCTAssertTrue(getSingleFrontendInvocationFromDriverArgumentsV4(driverPath: "swiftc",
argList: testCommand.components(separatedBy: " "),
action: { _ in false },
diagnostics: &emittedDiagnostics,
diagnosticCallback: {_,_ in },
env: env,
executor: executor))
let errorMessage = try XCTUnwrap(emittedDiagnostics.first?.message.text)
XCTAssertEqual(errorMessage, "unable to handle compilation, expected exactly one frontend job")
}
}
}

func testCreateCompilerInvocationCAPI() throws {
try withTemporaryDirectory { path in
Expand Down