@@ -325,7 +325,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
325
325
}
326
326
}
327
327
328
- private var cachedSourceKitOptions = RequestCache < TextDocumentSourceKitOptionsRequest > ( )
328
+ private var cachedAdjustedSourceKitOptions = RequestCache < TextDocumentSourceKitOptionsRequest > ( )
329
329
330
330
private var cachedBuildTargets = Cache < WorkspaceBuildTargetsRequest , [ BuildTargetIdentifier : BuildTargetInfo ] > ( )
331
331
@@ -529,7 +529,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
529
529
} else {
530
530
nil
531
531
}
532
- self . cachedSourceKitOptions . clear ( isolation: self ) { cacheKey in
532
+ self . cachedAdjustedSourceKitOptions . clear ( isolation: self ) { cacheKey in
533
533
guard let updatedTargets else {
534
534
// All targets might have changed
535
535
return true
@@ -758,13 +758,22 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
758
758
target: target,
759
759
language: language
760
760
)
761
-
762
- let response = try await cachedSourceKitOptions. get ( request, isolation: self ) { request in
763
- try await buildSystemAdapter. send ( request)
761
+ let response = try await cachedAdjustedSourceKitOptions. get ( request, isolation: self ) { request in
762
+ let options = try await buildSystemAdapter. send ( request)
763
+ switch language. semanticKind {
764
+ case . swift:
765
+ return options? . adjustArgsForSemanticSwiftFunctionality ( fileToIndex: document)
766
+ case . clang:
767
+ return options? . adjustingArgsForSemanticClangFunctionality ( )
768
+ default :
769
+ return options
770
+ }
764
771
}
772
+
765
773
guard let response else {
766
774
return nil
767
775
}
776
+
768
777
return FileBuildSettings (
769
778
compilerArguments: response. compilerArguments,
770
779
workingDirectory: response. workingDirectory,
@@ -1239,3 +1248,154 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
1239
1248
private func isDescendant( _ selfPathComponents: [ String ] , of otherPathComponents: [ String ] ) -> Bool {
1240
1249
return selfPathComponents. dropLast ( ) . starts ( with: otherPathComponents)
1241
1250
}
1251
+
1252
+ fileprivate extension TextDocumentSourceKitOptionsResponse {
1253
+ /// Adjust compiler arguments that were created for building to compiler arguments that should be used for indexing
1254
+ /// or background AST builds.
1255
+ ///
1256
+ /// This removes compiler arguments that produce output files and adds arguments to eg. allow errors and index the
1257
+ /// file.
1258
+ func adjustArgsForSemanticSwiftFunctionality( fileToIndex: DocumentURI ) -> TextDocumentSourceKitOptionsResponse {
1259
+ let optionsToRemove : [ CompilerCommandLineOption ] = [
1260
+ . flag( " c " , [ . singleDash] ) ,
1261
+ . flag( " disable-cmo " , [ . singleDash] ) ,
1262
+ . flag( " emit-dependencies " , [ . singleDash] ) ,
1263
+ . flag( " emit-module-interface " , [ . singleDash] ) ,
1264
+ . flag( " emit-module " , [ . singleDash] ) ,
1265
+ . flag( " emit-objc-header " , [ . singleDash] ) ,
1266
+ . flag( " incremental " , [ . singleDash] ) ,
1267
+ . flag( " no-color-diagnostics " , [ . singleDash] ) ,
1268
+ . flag( " parseable-output " , [ . singleDash] ) ,
1269
+ . flag( " save-temps " , [ . singleDash] ) ,
1270
+ . flag( " serialize-diagnostics " , [ . singleDash] ) ,
1271
+ . flag( " use-frontend-parseable-output " , [ . singleDash] ) ,
1272
+ . flag( " validate-clang-modules-once " , [ . singleDash] ) ,
1273
+ . flag( " whole-module-optimization " , [ . singleDash] ) ,
1274
+ . flag( " experimental-skip-all-function-bodies " , isFrontend: true , [ . singleDash] ) ,
1275
+ . flag( " experimental-skip-non-inlinable-function-bodies " , isFrontend: true , [ . singleDash] ) ,
1276
+ . flag( " experimental-skip-non-exportable-decls " , isFrontend: true , [ . singleDash] ) ,
1277
+
1278
+ . option( " clang-build-session-file " , [ . singleDash] , [ . separatedBySpace] ) ,
1279
+ . option( " emit-module-interface-path " , [ . singleDash] , [ . separatedBySpace] ) ,
1280
+ . option( " emit-module-path " , [ . singleDash] , [ . separatedBySpace] ) ,
1281
+ . option( " emit-objc-header-path " , [ . singleDash] , [ . separatedBySpace] ) ,
1282
+ . option( " emit-package-module-interface-path " , [ . singleDash] , [ . separatedBySpace] ) ,
1283
+ . option( " emit-private-module-interface-path " , [ . singleDash] , [ . separatedBySpace] ) ,
1284
+ . option( " num-threads " , [ . singleDash] , [ . separatedBySpace] ) ,
1285
+ // Technically, `-o` and the output file don't need to be separated by a space. Eg. `swiftc -oa file.swift` is
1286
+ // valid and will write to an output file named `a`.
1287
+ // We can't support that because the only way to know that `-output-file-map` is a different flag and not an option
1288
+ // to write to an output file named `utput-file-map` is to know all compiler arguments of `swiftc`, which we don't.
1289
+ . option( " o " , [ . singleDash] , [ . separatedBySpace] ) ,
1290
+ . option( " output-file-map " , [ . singleDash] , [ . separatedBySpace, . separatedByEqualSign] ) ,
1291
+ ]
1292
+
1293
+ var result : [ String ] = [ ]
1294
+ result. reserveCapacity ( compilerArguments. count)
1295
+ var iterator = compilerArguments. makeIterator ( )
1296
+ while let argument = iterator. next ( ) {
1297
+ switch optionsToRemove. firstMatch ( for: argument) {
1298
+ case . removeOption:
1299
+ continue
1300
+ case . removeOptionAndNextArgument:
1301
+ _ = iterator. next ( )
1302
+ continue
1303
+ case . removeOptionAndPreviousArgument:
1304
+ _ = result. popLast ( )
1305
+ continue
1306
+ case nil :
1307
+ break
1308
+ }
1309
+ result. append ( argument)
1310
+ }
1311
+
1312
+ result += [
1313
+ // Avoid emitting the ABI descriptor, we don't need it
1314
+ " -Xfrontend " , " -empty-abi-descriptor " ,
1315
+ " -index-file " ,
1316
+ " -index-file-path " , fileToIndex. pseudoPath,
1317
+ // batch mode is not compatible with -index-file
1318
+ " -disable-batch-mode " ,
1319
+ // Fake an output path so that we get a different unit file for every Swift file we background index
1320
+ " -index-unit-output-path " , fileToIndex. pseudoPath + " .o " ,
1321
+ ]
1322
+
1323
+ result += supplementalClangIndexingArgs. flatMap { [ " -Xcc " , $0] }
1324
+
1325
+ return TextDocumentSourceKitOptionsResponse ( compilerArguments: result, workingDirectory: workingDirectory)
1326
+ }
1327
+
1328
+ /// Adjust compiler arguments that were created for building to compiler arguments that should be used for indexing
1329
+ /// or background AST builds.
1330
+ ///
1331
+ /// This removes compiler arguments that produce output files and adds arguments to eg. typecheck only.
1332
+ func adjustingArgsForSemanticClangFunctionality( ) -> TextDocumentSourceKitOptionsResponse {
1333
+ let optionsToRemove : [ CompilerCommandLineOption ] = [
1334
+ // Disable writing of a depfile
1335
+ . flag( " M " , [ . singleDash] ) ,
1336
+ . flag( " MD " , [ . singleDash] ) ,
1337
+ . flag( " MMD " , [ . singleDash] ) ,
1338
+ . flag( " MG " , [ . singleDash] ) ,
1339
+ . flag( " MM " , [ . singleDash] ) ,
1340
+ . flag( " MV " , [ . singleDash] ) ,
1341
+ // Don't create phony targets
1342
+ . flag( " MP " , [ . singleDash] ) ,
1343
+ // Don't write out compilation databases
1344
+ . flag( " MJ " , [ . singleDash] ) ,
1345
+ // Don't compile
1346
+ . flag( " c " , [ . singleDash] ) ,
1347
+
1348
+ . flag( " fmodules-validate-once-per-build-session " , [ . singleDash] ) ,
1349
+
1350
+ // Disable writing of a depfile
1351
+ . option( " MT " , [ . singleDash] , [ . noSpace, . separatedBySpace] ) ,
1352
+ . option( " MF " , [ . singleDash] , [ . noSpace, . separatedBySpace] ) ,
1353
+ . option( " MQ " , [ . singleDash] , [ . noSpace, . separatedBySpace] ) ,
1354
+
1355
+ // Don't write serialized diagnostic files
1356
+ . option( " serialize-diagnostics " , [ . singleDash, . doubleDash] , [ . separatedBySpace] ) ,
1357
+
1358
+ . option( " fbuild-session-file " , [ . singleDash] , [ . separatedByEqualSign] ) ,
1359
+ ]
1360
+
1361
+ var result : [ String ] = [ ]
1362
+ result. reserveCapacity ( compilerArguments. count)
1363
+ var iterator = compilerArguments. makeIterator ( )
1364
+ while let argument = iterator. next ( ) {
1365
+ switch optionsToRemove. firstMatch ( for: argument) {
1366
+ case . removeOption:
1367
+ continue
1368
+ case . removeOptionAndNextArgument:
1369
+ _ = iterator. next ( )
1370
+ continue
1371
+ case . removeOptionAndPreviousArgument:
1372
+ _ = result. popLast ( )
1373
+ continue
1374
+ case nil :
1375
+ break
1376
+ }
1377
+ result. append ( argument)
1378
+ }
1379
+ result += supplementalClangIndexingArgs
1380
+ result. append (
1381
+ " -fsyntax-only "
1382
+ )
1383
+ return TextDocumentSourceKitOptionsResponse ( compilerArguments: result, workingDirectory: workingDirectory)
1384
+ }
1385
+ }
1386
+
1387
+ fileprivate let supplementalClangIndexingArgs : [ String ] = [
1388
+ // Retain extra information for indexing
1389
+ " -fretain-comments-from-system-headers " ,
1390
+ // Pick up macro definitions during indexing
1391
+ " -Xclang " , " -detailed-preprocessing-record " ,
1392
+
1393
+ // libclang uses 'raw' module-format. Match it so we can reuse the module cache and PCHs that libclang uses.
1394
+ " -Xclang " , " -fmodule-format=raw " ,
1395
+
1396
+ // Be less strict - we want to continue and typecheck/index as much as possible
1397
+ " -Xclang " , " -fallow-pch-with-compiler-errors " ,
1398
+ " -Xclang " , " -fallow-pcm-with-compiler-errors " ,
1399
+ " -Wno-non-modular-include-in-framework-module " ,
1400
+ " -Wno-incomplete-umbrella " ,
1401
+ ]
0 commit comments