@@ -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,153 @@ 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 " , frontendName: " Xfrontend " , [ . singleDash] ) ,
1275
+ . flag( " experimental-skip-non-inlinable-function-bodies " , frontendName: " Xfrontend " , [ . singleDash] ) ,
1276
+ . flag( " experimental-skip-non-exportable-decls " , frontendName: " Xfrontend " , [ . singleDash] ) ,
1277
+ . flag( " experimental-lazy-typecheck " , frontendName: " Xfrontend " , [ . singleDash] ) ,
1278
+
1279
+ . option( " clang-build-session-file " , [ . singleDash] , [ . separatedBySpace] ) ,
1280
+ . option( " emit-module-interface-path " , [ . singleDash] , [ . separatedBySpace] ) ,
1281
+ . option( " emit-module-path " , [ . singleDash] , [ . separatedBySpace] ) ,
1282
+ . option( " emit-objc-header-path " , [ . singleDash] , [ . separatedBySpace] ) ,
1283
+ . option( " emit-package-module-interface-path " , [ . singleDash] , [ . separatedBySpace] ) ,
1284
+ . option( " emit-private-module-interface-path " , [ . singleDash] , [ . separatedBySpace] ) ,
1285
+ . option( " num-threads " , [ . singleDash] , [ . separatedBySpace] ) ,
1286
+ // Technically, `-o` and the output file don't need to be separated by a space. Eg. `swiftc -oa file.swift` is
1287
+ // valid and will write to an output file named `a`.
1288
+ // We can't support that because the only way to know that `-output-file-map` is a different flag and not an option
1289
+ // to write to an output file named `utput-file-map` is to know all compiler arguments of `swiftc`, which we don't.
1290
+ . option( " o " , [ . singleDash] , [ . separatedBySpace] ) ,
1291
+ . option( " output-file-map " , [ . singleDash] , [ . separatedBySpace, . separatedByEqualSign] ) ,
1292
+ ]
1293
+
1294
+ var result : [ String ] = [ ]
1295
+ result. reserveCapacity ( compilerArguments. count)
1296
+ var iterator = compilerArguments. makeIterator ( )
1297
+ while let argument = iterator. next ( ) {
1298
+ switch optionsToRemove. firstMatch ( for: argument) {
1299
+ case . removeOption:
1300
+ continue
1301
+ case . removeOptionAndNextArgument:
1302
+ _ = iterator. next ( )
1303
+ continue
1304
+ case . removeOptionAndPreviousArgument( let name) :
1305
+ if let previousArg = result. last, previousArg. hasSuffix ( " - \( name) " ) {
1306
+ _ = result. popLast ( )
1307
+ }
1308
+ continue
1309
+ case nil :
1310
+ break
1311
+ }
1312
+ result. append ( argument)
1313
+ }
1314
+
1315
+ result += [
1316
+ // Avoid emitting the ABI descriptor, we don't need it
1317
+ " -Xfrontend " , " -empty-abi-descriptor " ,
1318
+ ]
1319
+
1320
+ result += supplementalClangIndexingArgs. flatMap { [ " -Xcc " , $0] }
1321
+
1322
+ return TextDocumentSourceKitOptionsResponse ( compilerArguments: result, workingDirectory: workingDirectory)
1323
+ }
1324
+
1325
+ /// Adjust compiler arguments that were created for building to compiler arguments that should be used for indexing
1326
+ /// or background AST builds.
1327
+ ///
1328
+ /// This removes compiler arguments that produce output files and adds arguments to eg. typecheck only.
1329
+ func adjustingArgsForSemanticClangFunctionality( ) -> TextDocumentSourceKitOptionsResponse {
1330
+ let optionsToRemove : [ CompilerCommandLineOption ] = [
1331
+ // Disable writing of a depfile
1332
+ . flag( " M " , [ . singleDash] ) ,
1333
+ . flag( " MD " , [ . singleDash] ) ,
1334
+ . flag( " MMD " , [ . singleDash] ) ,
1335
+ . flag( " MG " , [ . singleDash] ) ,
1336
+ . flag( " MM " , [ . singleDash] ) ,
1337
+ . flag( " MV " , [ . singleDash] ) ,
1338
+ // Don't create phony targets
1339
+ . flag( " MP " , [ . singleDash] ) ,
1340
+ // Don't write out compilation databases
1341
+ . flag( " MJ " , [ . singleDash] ) ,
1342
+ // Don't compile
1343
+ . flag( " c " , [ . singleDash] ) ,
1344
+
1345
+ . flag( " fmodules-validate-once-per-build-session " , [ . singleDash] ) ,
1346
+
1347
+ // Disable writing of a depfile
1348
+ . option( " MT " , [ . singleDash] , [ . noSpace, . separatedBySpace] ) ,
1349
+ . option( " MF " , [ . singleDash] , [ . noSpace, . separatedBySpace] ) ,
1350
+ . option( " MQ " , [ . singleDash] , [ . noSpace, . separatedBySpace] ) ,
1351
+
1352
+ // Don't write serialized diagnostic files
1353
+ . option( " serialize-diagnostics " , [ . singleDash, . doubleDash] , [ . separatedBySpace] ) ,
1354
+
1355
+ . option( " fbuild-session-file " , [ . singleDash] , [ . separatedByEqualSign] ) ,
1356
+ ]
1357
+
1358
+ var result : [ String ] = [ ]
1359
+ result. reserveCapacity ( compilerArguments. count)
1360
+ var iterator = compilerArguments. makeIterator ( )
1361
+ while let argument = iterator. next ( ) {
1362
+ switch optionsToRemove. firstMatch ( for: argument) {
1363
+ case . removeOption:
1364
+ continue
1365
+ case . removeOptionAndNextArgument:
1366
+ _ = iterator. next ( )
1367
+ continue
1368
+ case . removeOptionAndPreviousArgument( let name) :
1369
+ if let previousArg = result. last, previousArg. hasSuffix ( " - \( name) " ) {
1370
+ _ = result. popLast ( )
1371
+ }
1372
+ continue
1373
+ case nil :
1374
+ break
1375
+ }
1376
+ result. append ( argument)
1377
+ }
1378
+ result += supplementalClangIndexingArgs
1379
+ result. append (
1380
+ " -fsyntax-only "
1381
+ )
1382
+ return TextDocumentSourceKitOptionsResponse ( compilerArguments: result, workingDirectory: workingDirectory)
1383
+ }
1384
+ }
1385
+
1386
+ fileprivate let supplementalClangIndexingArgs : [ String ] = [
1387
+ // Retain extra information for indexing
1388
+ " -fretain-comments-from-system-headers " ,
1389
+ // Pick up macro definitions during indexing
1390
+ " -Xclang " , " -detailed-preprocessing-record " ,
1391
+
1392
+ // libclang uses 'raw' module-format. Match it so we can reuse the module cache and PCHs that libclang uses.
1393
+ " -Xclang " , " -fmodule-format=raw " ,
1394
+
1395
+ // Be less strict - we want to continue and typecheck/index as much as possible
1396
+ " -Xclang " , " -fallow-pch-with-compiler-errors " ,
1397
+ " -Xclang " , " -fallow-pcm-with-compiler-errors " ,
1398
+ " -Wno-non-modular-include-in-framework-module " ,
1399
+ " -Wno-incomplete-umbrella " ,
1400
+ ]
0 commit comments