@@ -17,24 +17,96 @@ import enum TSCBasic.ProcessEnv
17
17
import var TSCBasic. localFileSystem
18
18
import SwiftOptions
19
19
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
+
20
67
/// 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.
22
70
///
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
25
76
/// produce no outputs. For example, this disables "-emit-module" and "-c" and
26
77
/// 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
29
78
///
30
79
/// \returns true on error
31
80
///
32
81
/// \note This function is not intended to create invocations which are
33
82
/// 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 ] = [ ]
38
110
var args : [ String ] = [ ]
39
111
args. append ( contentsOf: argList)
40
112
@@ -55,13 +127,10 @@ public func getSingleFrontendInvocationFromDriverArguments(argList: [String],
55
127
args. append ( " -driver-filelist-threshold " ) ;
56
128
args. append ( String ( Int . max) ) ;
57
129
58
- let diagnosticsEngine = DiagnosticsEngine ( )
59
- defer { emittedDiagnostics = diagnosticsEngine. diagnostics }
60
-
61
130
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)
65
134
66
135
let optionTable = OptionTable ( )
67
136
var parsedOptions = try optionTable. parse ( Array ( args) , for: . batch, delayThrows: true )
@@ -84,7 +153,6 @@ public func getSingleFrontendInvocationFromDriverArguments(argList: [String],
84
153
return true
85
154
}
86
155
87
-
88
156
let buildPlan = try driver. planBuild ( )
89
157
if diagnosticsEngine. hasErrors {
90
158
return true
@@ -98,12 +166,12 @@ public func getSingleFrontendInvocationFromDriverArguments(argList: [String],
98
166
diagnosticsEngine. emit ( . error_expected_frontend_command( ) )
99
167
return true
100
168
}
101
- outputFrontendArgs = try executor. description ( of: compileJob,
102
- forceResponseFiles: false ) . components ( separatedBy: " " )
169
+ singleFrontendTaskCommand = try executor. description ( of: compileJob,
170
+ forceResponseFiles: false ) . components ( separatedBy: " " )
103
171
} catch {
104
172
print ( " Unexpected error: \( error) . " )
105
173
return true
106
174
}
107
175
108
- return false
176
+ return action ( singleFrontendTaskCommand )
109
177
}
0 commit comments