@@ -17,24 +17,96 @@ import enum TSCBasic.ProcessEnv
1717import var TSCBasic. localFileSystem
1818import SwiftOptions
1919
20+ //typedef enum {
21+ // SWIFTDRIVER_TOOLING_DIAGNOSTIC_ERROR = 0,
22+ // SWIFTDRIVER_TOOLING_DIAGNOSTIC_WARNING = 1,
23+ // SWIFTDRIVER_TOOLING_DIAGNOSTIC_REMARK = 2,
24+ // SWIFTDRIVER_TOOLING_DIAGNOSTIC_NOTE = 3
25+ //} swiftdriver_tooling_diagnostic_kind;
26+ public let SWIFTDRIVER_TOOLING_DIAGNOSTIC_ERROR : CInt = 0 ;
27+ public let SWIFTDRIVER_TOOLING_DIAGNOSTIC_WARNING : CInt = 1 ;
28+ public let SWIFTDRIVER_TOOLING_DIAGNOSTIC_REMARK : CInt = 2 ;
29+ public let SWIFTDRIVER_TOOLING_DIAGNOSTIC_NOTE : CInt = 3 ;
30+
31+ @_cdecl ( " swift_getSingleFrontendInvocationFromDriverArgumentsV2 " )
32+ public func getSingleFrontendInvocationFromDriverArgumentsV2( driverPath: UnsafePointer < CChar > ,
33+ argListCount: CInt ,
34+ argList: UnsafePointer < UnsafePointer < CChar > ? > ,
35+ action: @convention ( c) ( CInt , UnsafePointer < UnsafePointer < CChar > ? > ) -> Bool ,
36+ diagnosticCallback: @convention ( c) ( CInt , UnsafePointer < CChar > ) -> Void ,
37+ forceNoOutputs: Bool = false ) -> Bool {
38+ // Bridge the driver path argument
39+ let bridgedDriverPath = String ( cString: driverPath)
40+
41+ // Bridge the argv equivalent
42+ let argListBufferPtr = UnsafeBufferPointer < UnsafePointer < CChar > ? > ( start: argList, count: Int ( argListCount) )
43+ let bridgedArgList = [ bridgedDriverPath] + argListBufferPtr. map { String ( cString: $0!) }
44+
45+ // Bridge the action callback
46+ let bridgedAction : ( [ String ] ) -> Bool = { args in
47+ return withArrayOfCStrings ( args) {
48+ return action ( CInt ( args. count) , $0!)
49+ }
50+ }
51+
52+ // Bridge the diagnostic callback
53+ let bridgedDiagnosticCallback : ( CInt , String ) -> Void = { diagKind, message in
54+ diagnosticCallback ( diagKind, message)
55+ }
56+
57+ var diagnostics : [ Diagnostic ] = [ ]
58+ let result = getSingleFrontendInvocationFromDriverArgumentsV2 ( driverPath: bridgedDriverPath,
59+ argList: bridgedArgList,
60+ action: bridgedAction,
61+ diagnostics: & diagnostics,
62+ diagnosticCallback: bridgedDiagnosticCallback,
63+ forceNoOutputs: forceNoOutputs)
64+ return result
65+ }
66+
2067/// Generates the list of arguments that would be passed to the compiler
21- /// frontend from the given driver arguments.
68+ /// frontend from the given driver arguments, for a single-compiler-invocation
69+ /// context.
2270///
23- /// \param ArgList The driver arguments (i.e. normal arguments for \c swiftc).
24- /// \param ForceNoOutputs If true, override the output mode to "-typecheck" and
71+ /// \param driverPath the driver executable path
72+ /// \param argList The driver arguments (i.e. normal arguments for \c swiftc).
73+ /// \param diagnostics Contains the diagnostics emitted by the driver
74+ /// \param action invokes a user-provided action on the resulting frontend invocation command
75+ /// \param forceNoOutputs If true, override the output mode to "-typecheck" and
2576/// produce no outputs. For example, this disables "-emit-module" and "-c" and
2677/// prevents the creation of temporary files.
27- /// \param outputFrontendArgs Contains the resulting frontend invocation command
28- /// \param emittedDiagnostics Contains the diagnostics emitted by the driver
2978///
3079/// \returns true on error
3180///
3281/// \note This function is not intended to create invocations which are
3382/// suitable for use in REPL or immediate modes.
34- public func getSingleFrontendInvocationFromDriverArguments( argList: [ String ] ,
35- outputFrontendArgs: inout [ String ] ,
36- emittedDiagnostics: inout [ Diagnostic ] ,
37- forceNoOutputs: Bool = false ) -> Bool {
83+ public func getSingleFrontendInvocationFromDriverArgumentsV2( driverPath: String ,
84+ argList: [ String ] ,
85+ action: ( [ String ] ) -> Bool ,
86+ diagnostics: inout [ Diagnostic ] ,
87+ diagnosticCallback: @escaping ( CInt , String ) -> Void ,
88+ forceNoOutputs: Bool = false ) -> Bool {
89+ /// Handler for emitting diagnostics to tooling clients.
90+ let toolingDiagnosticsHandler : DiagnosticsEngine . DiagnosticsHandler = { diagnostic in
91+ let diagnosticKind : CInt
92+ switch diagnostic. message. behavior {
93+ case . error:
94+ diagnosticKind = SWIFTDRIVER_TOOLING_DIAGNOSTIC_ERROR
95+ case . warning:
96+ diagnosticKind = SWIFTDRIVER_TOOLING_DIAGNOSTIC_WARNING
97+ case . note:
98+ diagnosticKind = SWIFTDRIVER_TOOLING_DIAGNOSTIC_NOTE
99+ case . remark:
100+ diagnosticKind = SWIFTDRIVER_TOOLING_DIAGNOSTIC_REMARK
101+ default :
102+ diagnosticKind = SWIFTDRIVER_TOOLING_DIAGNOSTIC_ERROR
103+ }
104+ diagnosticCallback ( diagnosticKind, diagnostic. message. text)
105+ }
106+ let diagnosticsEngine = DiagnosticsEngine ( handlers: [ toolingDiagnosticsHandler] )
107+ defer { diagnostics = diagnosticsEngine. diagnostics }
108+
109+ var singleFrontendTaskCommand : [ String ] = [ ]
38110 var args : [ String ] = [ ]
39111 args. append ( contentsOf: argList)
40112
@@ -55,13 +127,10 @@ public func getSingleFrontendInvocationFromDriverArguments(argList: [String],
55127 args. append ( " -driver-filelist-threshold " ) ;
56128 args. append ( String ( Int . max) ) ;
57129
58- let diagnosticsEngine = DiagnosticsEngine ( )
59- defer { emittedDiagnostics = diagnosticsEngine. diagnostics }
60-
61130 do {
62- args = try [ " swiftc " ] + Driver. expandResponseFiles ( args,
63- fileSystem: localFileSystem,
64- diagnosticsEngine: diagnosticsEngine)
131+ args = try [ driverPath ] + Driver. expandResponseFiles ( args,
132+ fileSystem: localFileSystem,
133+ diagnosticsEngine: diagnosticsEngine)
65134
66135 let optionTable = OptionTable ( )
67136 var parsedOptions = try optionTable. parse ( Array ( args) , for: . batch, delayThrows: true )
@@ -84,7 +153,6 @@ public func getSingleFrontendInvocationFromDriverArguments(argList: [String],
84153 return true
85154 }
86155
87-
88156 let buildPlan = try driver. planBuild ( )
89157 if diagnosticsEngine. hasErrors {
90158 return true
@@ -98,12 +166,12 @@ public func getSingleFrontendInvocationFromDriverArguments(argList: [String],
98166 diagnosticsEngine. emit ( . error_expected_frontend_command( ) )
99167 return true
100168 }
101- outputFrontendArgs = try executor. description ( of: compileJob,
102- forceResponseFiles: false ) . components ( separatedBy: " " )
169+ singleFrontendTaskCommand = try executor. description ( of: compileJob,
170+ forceResponseFiles: false ) . components ( separatedBy: " " )
103171 } catch {
104172 print ( " Unexpected error: \( error) . " )
105173 return true
106174 }
107175
108- return false
176+ return action ( singleFrontendTaskCommand )
109177}
0 commit comments