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