1111//===----------------------------------------------------------------------===//
1212
1313import Dispatch
14+ import SKLogging
1415import SwiftExtensions
1516import TSCExtensions
1617
@@ -68,10 +69,14 @@ package final actor ToolchainRegistry {
6869 private let toolchainsByIdentifier : [ String : [ Toolchain ] ]
6970
7071 /// The toolchains indexed by their path.
71- ///
72- /// Note: Not all toolchains have a path.
7372 private let toolchainsByPath : [ URL : Toolchain ]
7473
74+ /// Map from compiler paths (`clang`, `swift`, `swiftc`) mapping to the toolchain that contained them.
75+ ///
76+ /// This allows us to find the toolchain that should be used for semantic functionality based on which compiler it is
77+ /// built with in the `compile_commands.json`.
78+ private let toolchainsByCompiler : [ URL : Toolchain ]
79+
7580 /// The currently selected toolchain identifier on Darwin.
7681 package let darwinToolchainOverride : String ?
7782
@@ -98,29 +103,40 @@ package final actor ToolchainRegistry {
98103 var toolchainsAndReasons : [ ( toolchain: Toolchain , reason: ToolchainRegisterReason ) ] = [ ]
99104 var toolchainsByIdentifier : [ String : [ Toolchain ] ] = [ : ]
100105 var toolchainsByPath : [ URL : Toolchain ] = [ : ]
106+ var toolchainsByCompiler : [ URL : Toolchain ] = [ : ]
101107 for (toolchain, reason) in toolchainsAndReasonsParam {
102108 // Non-XcodeDefault toolchain: disallow all duplicates.
103- if toolchain. identifier != ToolchainRegistry . darwinDefaultToolchainIdentifier {
104- guard toolchainsByIdentifier [ toolchain. identifier] == nil else {
105- continue
106- }
109+ if toolchainsByIdentifier [ toolchain. identifier] != nil ,
110+ toolchain. identifier != ToolchainRegistry . darwinDefaultToolchainIdentifier
111+ {
112+ logger. error ( " Found two toolchains with the same identifier: \( toolchain. identifier) " )
113+ continue
114+ }
115+
116+ // Toolchain should always be unique by path.
117+ if toolchainsByPath [ toolchain. path] != nil {
118+ logger. fault ( " Found two toolchains with the same path: \( toolchain. path) " )
119+ continue
107120 }
108121
109- // Toolchain should always be unique by path if it is present.
110- if let path = toolchain. path {
111- guard toolchainsByPath [ path] == nil else {
122+ toolchainsByPath [ toolchain. path] = toolchain
123+ toolchainsByIdentifier [ toolchain. identifier, default: [ ] ] . append ( toolchain)
124+
125+ for case . some( let compiler) in [ toolchain. clang, toolchain. swift, toolchain. swiftc] {
126+ guard toolchainsByCompiler [ compiler] == nil else {
127+ logger. fault ( " Found two toolchains with the same compiler: \( compiler) " )
112128 continue
113129 }
114- toolchainsByPath [ path ] = toolchain
130+ toolchainsByCompiler [ compiler ] = toolchain
115131 }
116132
117- toolchainsByIdentifier [ toolchain. identifier, default: [ ] ] . append ( toolchain)
118133 toolchainsAndReasons. append ( ( toolchain, reason) )
119134 }
120135
121136 self . toolchainsAndReasons = toolchainsAndReasons
122137 self . toolchainsByIdentifier = toolchainsByIdentifier
123138 self . toolchainsByPath = toolchainsByPath
139+ self . toolchainsByCompiler = toolchainsByCompiler
124140
125141 if let darwinToolchainOverride, !darwinToolchainOverride. isEmpty, darwinToolchainOverride != " default " {
126142 self . darwinToolchainOverride = darwinToolchainOverride
@@ -267,12 +283,7 @@ package final actor ToolchainRegistry {
267283 /// If we have a toolchain in the toolchain registry that contains the compiler with the given URL, return it.
268284 /// Otherwise, return `nil`.
269285 package func toolchain( withCompiler compiler: URL ) -> Toolchain ? {
270- for toolchain in toolchains {
271- if [ toolchain. clang, toolchain. swift, toolchain. swiftc] . contains ( compiler) {
272- return toolchain
273- }
274- }
275- return nil
286+ return toolchainsByCompiler [ compiler]
276287 }
277288}
278289
0 commit comments