#pragma once #include #include #include #include #include #include #include #include class QQmlEngine; class QJSEngine; namespace ZShell::llm { class CodeHighlighter : public QObject { Q_OBJECT QML_ELEMENT QML_SINGLETON public: Q_INVOKABLE void highlight( const QString& code, const QString& language, QObject* target, int token); static CodeHighlighter* create(QQmlEngine*, QJSEngine*); struct Grammar { std::vector libs; std::vector symbols; std::vector queries; }; private: struct State { bool bad = false; // permanent failure, do not retry void* lib = nullptr; const void* lang = nullptr; // const TSLanguage* void* query = nullptr; // TSQuery* }; [[nodiscard]] static const QHash& aliases(); [[nodiscard]] static uint8_t roleFor(const char* name, uint32_t length); [[nodiscard]] static const char* roleName(uint8_t role); [[nodiscard]] static QString resolveId(const QString& language); [[nodiscard]] static QString cacheKey( const QString& id, const QString& code); [[nodiscard]] QVariantList doHighlight( const QString& code, const QString& language) const; [[nodiscard]] QVariantList lookupSpans( const QString& code, const QString& language) const; void storeSpans( const QString& code, const QString& language, const QVariantList& spans) const; struct SpanCacheEntry { QString code; // re-compared on lookup; a hash collision can // never deliver the wrong spans QVariantList spans; }; mutable QHash> m_states; mutable QMutex m_stateMutex; mutable QHash m_spanCache; mutable QStringList m_spanCacheOrder; // LRU order, oldest first mutable int m_spanCacheBytes = 0; mutable QMutex m_cacheMutex; static CodeHighlighter* s_instance; }; } // namespace ZShell::llm