         
         // use cache if the content of the whole document is the same as the last
         if let cache = self.highlightCache, cache.styleName == self.style.name, cache.string == self.textStorage.string {
-            self.apply(highlights: cache.highlights, range: wholeRange)
+            self.textStorage.apply(highlights: cache.highlights, range: wholeRange)
             completionHandler()
             return nil
         }

}


extension NSAttributedString.Key {
    
    static let syntaxType = NSAttributedString.Key("CotEditor.SyntaxType")
}

        return operation.progress
    }
    
}



private extension NSTextStorage {
    
    /// apply highlights to the document
    func apply(highlights: [SyntaxType: [NSRange]], range highlightRange: NSRange) {
        
        assert(Thread.isMainThread)
        
        guard self.length > 0 else { return }
        
        let hasHighlight = highlights.values.contains { !$0.isEmpty }
        
        for layoutManager in self.layoutManagers {
            // skip if never colorlized yet to avoid heavy `layoutManager.invalidateDisplay(forCharacterRange:)`
            guard hasHighlight || layoutManager.hasTemporaryAttribute(.syntaxType, in: highlightRange) else { continue }
            
            let theme = (layoutManager.firstTextView as? Themable)?.theme
            
            layoutManager.groupTemporaryAttributesUpdate(in: highlightRange) {
                layoutManager.removeTemporaryAttribute(.foregroundColor, forCharacterRange: highlightRange)
                layoutManager.removeTemporaryAttribute(.syntaxType, forCharacterRange: highlightRange)
                
                for type in SyntaxType.allCases {
                    guard let ranges = highlights[type], !ranges.isEmpty else { continue }
                    
                    for range in ranges {
                        layoutManager.addTemporaryAttribute(.syntaxType, value: type, forCharacterRange: range)
                    }
                    
                    if let color = theme?.style(for: type)?.color {
                        for range in ranges {
                            layoutManager.addTemporaryAttribute(.foregroundColor, value: color, forCharacterRange: range)
                        }
                    } else {
                        for range in ranges {
                            layoutManager.removeTemporaryAttribute(.foregroundColor, forCharacterRange: range)
                        }
                    }
                }
