@@ -163,9 +163,12 @@ public struct UpdateIndexStoreTaskDescription: TaskDescriptionProtocol {
163
163
BuildSettingsLogger . log ( settings: buildSettings, for: uri)
164
164
}
165
165
case . c, . cpp, . objective_c, . objective_cpp:
166
- // TODO (indexing): Support indexing of clang files, including headers.
167
- // https://github.com/apple/sourcekit-lsp/issues/1253
168
- break
166
+ do {
167
+ try await updateIndexStore ( forClangFile: uri, buildSettings: buildSettings, toolchain: toolchain)
168
+ } catch {
169
+ logger. error ( " Updating index store for \( uri) failed: \( error. forLogging) " )
170
+ BuildSettingsLogger . log ( settings: buildSettings, for: uri)
171
+ }
169
172
default :
170
173
logger. error (
171
174
" Not updating index store for \( uri) because it is a language that is not supported by background indexing "
@@ -190,10 +193,49 @@ public struct UpdateIndexStoreTaskDescription: TaskDescriptionProtocol {
190
193
fileToIndex: uri
191
194
)
192
195
193
- let process = try Process . launch (
194
- arguments: [ swiftc. pathString] + indexingArguments,
196
+ try await runIndexingProcess (
197
+ indexFile: uri,
198
+ buildSettings: buildSettings,
199
+ processArguments: [ swiftc. pathString] + indexingArguments,
195
200
workingDirectory: buildSettings. workingDirectory. map ( AbsolutePath . init ( validating: ) )
196
201
)
202
+ }
203
+
204
+ private func updateIndexStore(
205
+ forClangFile uri: DocumentURI ,
206
+ buildSettings: FileBuildSettings ,
207
+ toolchain: Toolchain
208
+ ) async throws {
209
+ guard let clang = toolchain. clang else {
210
+ logger. error (
211
+ " Not updating index store for \( uri. forLogging) because toolchain \( toolchain. identifier) does not contain clang "
212
+ )
213
+ return
214
+ }
215
+
216
+ let indexingArguments = adjustClangCompilerArgumentsForIndexStoreUpdate (
217
+ buildSettings. compilerArguments,
218
+ fileToIndex: uri
219
+ )
220
+
221
+ try await runIndexingProcess (
222
+ indexFile: uri,
223
+ buildSettings: buildSettings,
224
+ processArguments: [ clang. pathString] + indexingArguments,
225
+ workingDirectory: buildSettings. workingDirectory. map ( AbsolutePath . init ( validating: ) )
226
+ )
227
+ }
228
+
229
+ private func runIndexingProcess(
230
+ indexFile: DocumentURI ,
231
+ buildSettings: FileBuildSettings ,
232
+ processArguments: [ String ] ,
233
+ workingDirectory: AbsolutePath ?
234
+ ) async throws {
235
+ let process = try Process . launch (
236
+ arguments: processArguments,
237
+ workingDirectory: workingDirectory
238
+ )
197
239
let result = try await process. waitUntilExitSendingSigIntOnTaskCancellation ( )
198
240
switch result. exitStatus. exhaustivelySwitchable {
199
241
case . terminated( code: 0 ) :
@@ -205,26 +247,26 @@ public struct UpdateIndexStoreTaskDescription: TaskDescriptionProtocol {
205
247
// Indexing will frequently fail if the source code is in an invalid state. Thus, log the failure at a low level.
206
248
logger. debug (
207
249
"""
208
- Updating index store for Swift file \( uri . forLogging) terminated with non-zero exit code \( code)
250
+ Updating index store for \( indexFile . forLogging) terminated with non-zero exit code \( code)
209
251
Stderr:
210
252
\( stderr)
211
253
Stdout:
212
254
\( stdout)
213
255
"""
214
256
)
215
- BuildSettingsLogger . log ( level: . debug, settings: buildSettings, for: uri )
257
+ BuildSettingsLogger . log ( level: . debug, settings: buildSettings, for: indexFile )
216
258
case . signalled( signal: let signal) :
217
259
if !Task. isCancelled {
218
260
// The indexing job finished with a signal. Could be because the compiler crashed.
219
261
// Ignore signal exit codes if this task has been cancelled because the compiler exits with SIGINT if it gets
220
262
// interrupted.
221
- logger. error ( " Updating index store for Swift file \( uri . forLogging) signaled \( signal) " )
222
- BuildSettingsLogger . log ( level: . error, settings: buildSettings, for: uri )
263
+ logger. error ( " Updating index store for \( indexFile . forLogging) signaled \( signal) " )
264
+ BuildSettingsLogger . log ( level: . error, settings: buildSettings, for: indexFile )
223
265
}
224
266
case . abnormal( exception: let exception) :
225
267
if !Task. isCancelled {
226
- logger. error ( " Updating index store for Swift file \( uri . forLogging) exited abnormally \( exception) " )
227
- BuildSettingsLogger . log ( level: . error, settings: buildSettings, for: uri )
268
+ logger. error ( " Updating index store for \( indexFile . forLogging) exited abnormally \( exception) " )
269
+ BuildSettingsLogger . log ( level: . error, settings: buildSettings, for: indexFile )
228
270
}
229
271
}
230
272
}
@@ -304,3 +346,56 @@ private func adjustSwiftCompilerArgumentsForIndexStoreUpdate(
304
346
]
305
347
return result
306
348
}
349
+
350
+ /// Adjust compiler arguments that were created for building to compiler arguments that should be used for indexing.
351
+ ///
352
+ /// This removes compiler arguments that produce output files and adds arguments to index the file.
353
+ private func adjustClangCompilerArgumentsForIndexStoreUpdate(
354
+ _ compilerArguments: [ String ] ,
355
+ fileToIndex: DocumentURI
356
+ ) -> [ String ] {
357
+ let removeFlags : Set < String > = [
358
+ // Disable writing of a depfile
359
+ " -M " ,
360
+ " -MD " ,
361
+ " -MMD " ,
362
+ " -MG " ,
363
+ " -MM " ,
364
+ " -MV " ,
365
+ // Don't create phony targets
366
+ " -MP " ,
367
+ // Don't writ out compilation databases
368
+ " -MJ " ,
369
+ // Continue in the presence of errors during indexing
370
+ " -fmodules-validate-once-per-build-session " ,
371
+ // Don't compile
372
+ " -c " ,
373
+ ]
374
+
375
+ let removeArguments : Set < String > = [
376
+ // Disable writing of a depfile
377
+ " -MT " ,
378
+ " -MF " ,
379
+ " -MQ " ,
380
+ // Don't write serialized diagnostic files
381
+ " --serialize-diagnostics " ,
382
+ ]
383
+
384
+ var result : [ String ] = [ ]
385
+ result. reserveCapacity ( compilerArguments. count)
386
+ var iterator = compilerArguments. makeIterator ( )
387
+ while let argument = iterator. next ( ) {
388
+ if removeFlags. contains ( argument) || argument. starts ( with: " -fbuild-session-file= " ) {
389
+ continue
390
+ }
391
+ if removeArguments. contains ( argument) {
392
+ _ = iterator. next ( )
393
+ continue
394
+ }
395
+ result. append ( argument)
396
+ }
397
+ result. append (
398
+ " -fsyntax-only "
399
+ )
400
+ return result
401
+ }
0 commit comments