 internal typealias AssertHandler = () -> Void
 private var assertHandlers = [String: AssertHandler]()
 
-private var _allDeclarationsByType = [String: [String]]()
-private var queueForRebuild = [Structure]()
+private struct RebuildQueue {
+    private let lock = NSLock()
+    private var queue = [Structure]()
+    private var allDeclarationsByType = [String: [String]]()
+
+    mutating func append(_ structure: Structure) {
+        lock.lock()
+        defer { lock.unlock() }
+        queue.append(structure)
+    }
+
+    mutating func clear() {
+        lock.lock()
+        defer { lock.unlock() }
+        queue.removeAll(keepingCapacity: false)
+        allDeclarationsByType.removeAll(keepingCapacity: false)
+    }
+
+    // Must hold lock when calling
+    private mutating func rebuildIfNecessary() {
+        guard !queue.isEmpty else { return }
+        let allDeclarationsByType = queue.flatMap { structure -> (String, [String])? in
+            guard let firstSubstructureDict = structure.dictionary.substructure.first,
+                let name = firstSubstructureDict["key.name"] as? String,
+                let kind = (firstSubstructureDict["key.kind"] as? String).flatMap(SwiftDeclarationKind.init),
+                kind == .protocol,
+                case let substructure = firstSubstructureDict.substructure,
+                !substructure.isEmpty else {
+                    return nil
+            }
+            return (name, substructure.flatMap({ $0["key.name"] as? String }))
+        }
+        allDeclarationsByType.forEach { self.allDeclarationsByType[$0.0] = $0.1 }
+        queue.removeAll(keepingCapacity: false)
+    }
+
+    mutating func getAllDeclarationsByType() -> [String: [String]] {
+        lock.lock()
+        defer { lock.unlock() }
+        rebuildIfNecessary()
+        return allDeclarationsByType
+    }
+}
+
+private var queueForRebuild = RebuildQueue()
 
 private struct Cache<T> {
-    fileprivate var values = [String: T]()
-    fileprivate var factory: (File) -> T
+    private var values = [String: T]()
+    private let factory: (File) -> T
+    private let lock = NSLock()
 
     fileprivate init(_ factory: @escaping (File) -> T) {
         self.factory = factory

        }
        set {
            if newValue {
                let value: [String: SourceKitRepresentable]? = nil
                responseCache.values[cacheKey] = value
            } else {
                responseCache.values.removeValue(forKey: cacheKey)
            }
        }
    }

    }

    internal static func clearCaches() {
        queueForRebuild.clear()
        responseCache.clear()
        assertHandlers.removeAll(keepingCapacity: false)
        structureCache.clear()
        syntaxMapCache.clear()
        syntaxTokensByLinesCache.clear()
