@@ -325,7 +325,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
325325 }
326326 }
327327
328- private var cachedSourceKitOptions = RequestCache < TextDocumentSourceKitOptionsRequest > ( )
328+ private var cachedAdjustedSourceKitOptions = RequestCache < TextDocumentSourceKitOptionsRequest > ( )
329329
330330 private var cachedBuildTargets = Cache < WorkspaceBuildTargetsRequest , [ BuildTargetIdentifier : BuildTargetInfo ] > ( )
331331
@@ -529,7 +529,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
529529 } else {
530530 nil
531531 }
532- self . cachedSourceKitOptions . clear ( isolation: self ) { cacheKey in
532+ self . cachedAdjustedSourceKitOptions . clear ( isolation: self ) { cacheKey in
533533 guard let updatedTargets else {
534534 // All targets might have changed
535535 return true
@@ -758,13 +758,22 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
758758 target: target,
759759 language: language
760760 )
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+ }
764771 }
772+
765773 guard let response else {
766774 return nil
767775 }
776+
768777 return FileBuildSettings (
769778 compilerArguments: response. compilerArguments,
770779 workingDirectory: response. workingDirectory,
@@ -1239,3 +1248,153 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
12391248private func isDescendant( _ selfPathComponents: [ String ] , of otherPathComponents: [ String ] ) -> Bool {
12401249 return selfPathComponents. dropLast ( ) . starts ( with: otherPathComponents)
12411250}
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