diff options
author | David Schulz <david.schulz@qt.io> | 2018-11-08 11:39:48 +0100 |
---|---|---|
committer | David Schulz <david.schulz@qt.io> | 2019-01-28 11:37:08 +0000 |
commit | 14834e6b0a4e7c1272ec3a1838b0634dd66e72ea (patch) | |
tree | 23caed8a748c0d38c59e1f92b448551122d11df2 /src/plugins | |
parent | 1c77d7e1a79f59485eb90c066d17ec7436f46a93 (diff) |
TextEditor: replace generic highlighter with ksyntaxhighlighting
Fixes: QTCREATORBUG-21029
Change-Id: I9894c4384e0e47da6bf030b7b8e07c3ad4737ff3
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
Diffstat (limited to 'src/plugins')
54 files changed, 477 insertions, 5997 deletions
diff --git a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp index c5c0fe5b74..6342535361 100644 --- a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp @@ -41,7 +41,6 @@ #include <projectexplorer/projectexplorer.h> #include <projectexplorer/session.h> -#include <texteditor/highlighterutils.h> #include <texteditor/texteditoractionhandler.h> #include <texteditor/texteditorconstants.h> diff --git a/src/plugins/texteditor/codeassist/codeassistant.cpp b/src/plugins/texteditor/codeassist/codeassistant.cpp index 1290199a54..b531f44c80 100644 --- a/src/plugins/texteditor/codeassist/codeassistant.cpp +++ b/src/plugins/texteditor/codeassist/codeassistant.cpp @@ -26,7 +26,6 @@ #include "codeassistant.h" #include "completionassistprovider.h" #include "iassistprocessor.h" -#include "textdocument.h" #include "iassistproposal.h" #include "iassistproposalmodel.h" #include "iassistproposalwidget.h" @@ -35,6 +34,7 @@ #include "runner.h" #include "textdocumentmanipulator.h" +#include <texteditor/textdocument.h> #include <texteditor/texteditor.h> #include <texteditor/texteditorsettings.h> #include <texteditor/completionsettings.h> diff --git a/src/plugins/texteditor/generichighlighter/context.cpp b/src/plugins/texteditor/generichighlighter/context.cpp deleted file mode 100644 index 59681af6ec..0000000000 --- a/src/plugins/texteditor/generichighlighter/context.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "context.h" -#include "rule.h" -#include "reuse.h" -#include "dynamicrule.h" -#include "highlightdefinition.h" - -using namespace TextEditor; -using namespace Internal; - -Context::Context() : m_fallthrough(false), m_dynamic(false) -{} - -Context::Context(const Context &context) : - m_id(context.m_id), m_name(context.m_name), m_lineBeginContext(context.m_lineBeginContext), - m_lineEndContext(context.m_lineEndContext), m_lineEmptyContext(context.m_lineEmptyContext), - m_fallthroughContext(context.m_fallthroughContext), - m_itemData(context.m_itemData), m_fallthrough(context.m_fallthrough), - m_dynamic(context.m_dynamic), m_instructions(context.m_instructions), - m_definition(context.m_definition) -{ - // Rules need to be deeply copied because of dynamic contexts. - foreach (const QSharedPointer<Rule> &rule, context.m_rules) - m_rules.append(QSharedPointer<Rule>(rule->clone())); -} - -const Context &Context::operator=(Context copy) -{ - swap(copy); - return *this; -} - -Context::~Context() = default; - -void Context::swap(Context &context) -{ - qSwap(m_id, context.m_id); - qSwap(m_name, context.m_name); - qSwap(m_lineBeginContext, context.m_lineBeginContext); - qSwap(m_lineEndContext, context.m_lineEndContext); - qSwap(m_lineEmptyContext, context.m_lineEmptyContext); - qSwap(m_fallthroughContext, context.m_fallthroughContext); - qSwap(m_itemData, context.m_itemData); - qSwap(m_fallthrough, context.m_fallthrough); - qSwap(m_dynamic, context.m_dynamic); - qSwap(m_rules, context.m_rules); - qSwap(m_instructions, context.m_instructions); - qSwap(m_definition, context.m_definition); -} - -void Context::configureId(const int unique) -{ m_id.append(QString::number(unique)); } - -const QString &Context::id() const -{ return m_id; } - -void Context::setName(const QString &name) -{ - m_name = name; - m_id = name; -} - -const QString &Context::name() const -{ return m_name; } - -void Context::setLineBeginContext(const QString &context) -{ m_lineBeginContext = context; } - -const QString &Context::lineBeginContext() const -{ return m_lineBeginContext; } - -void Context::setLineEndContext(const QString &context) -{ m_lineEndContext = context; } - -const QString &Context::lineEndContext() const -{ return m_lineEndContext; } - -void Context::setLineEmptyContext(const QString &context) -{ m_lineEmptyContext = context; } - -const QString &Context::lineEmptyContext() const -{ return m_lineEmptyContext; } - -void Context::setFallthroughContext(const QString &context) -{ m_fallthroughContext = context; } - -const QString &Context::fallthroughContext() const -{ return m_fallthroughContext; } - -void Context::setItemData(const QString &itemData) -{ m_itemData = itemData; } - -const QString &Context::itemData() const -{ return m_itemData; } - -void Context::setFallthrough(const QString &fallthrough) -{ m_fallthrough = toBool(fallthrough); } - -bool Context::isFallthrough() const -{ return m_fallthrough; } - -void Context::setDynamic(const QString &dynamic) -{ m_dynamic = toBool(dynamic); } - -bool Context::isDynamic() const -{ return m_dynamic; } - -void Context::updateDynamicRules(const QStringList &captures) const -{ - Internal::updateDynamicRules(m_rules, captures); -} - -void Context::addRule(const QSharedPointer<Rule> &rule) -{ m_rules.append(rule); } - -void Context::addRule(const QSharedPointer<Rule> &rule, int index) -{ m_rules.insert(index, rule); } - -const QList<QSharedPointer<Rule> > & Context::rules() const -{ return m_rules; } - -void Context::addIncludeRulesInstruction(const IncludeRulesInstruction &instruction) -{ m_instructions.append(instruction); } - -const QList<IncludeRulesInstruction> &Context::includeRulesInstructions() const -{ return m_instructions; } - -void Context::clearIncludeRulesInstructions() -{ m_instructions.clear(); } - -void Context::setDefinition(const QSharedPointer<HighlightDefinition> &definition) -{ m_definition = definition; } - -const QSharedPointer<HighlightDefinition> &Context::definition() const -{ return m_definition; } diff --git a/src/plugins/texteditor/generichighlighter/context.h b/src/plugins/texteditor/generichighlighter/context.h deleted file mode 100644 index c2358f2d04..0000000000 --- a/src/plugins/texteditor/generichighlighter/context.h +++ /dev/null @@ -1,107 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include "includerulesinstruction.h" - -#include <QString> -#include <QList> -#include <QSharedPointer> - -namespace TextEditor { -namespace Internal { - -class Rule; -class HighlightDefinition; - -class Context -{ -public: - Context(); - Context(const Context &context); - const Context &operator=(Context copy); - ~Context(); - - void configureId(const int unique); - const QString &id() const; - - void setName(const QString &name); - const QString &name() const; - - void setLineBeginContext(const QString &context); - const QString &lineBeginContext() const; - - void setLineEndContext(const QString &context); - const QString &lineEndContext() const; - - void setLineEmptyContext(const QString &context); - const QString &lineEmptyContext() const; - - void setFallthroughContext(const QString &context); - const QString &fallthroughContext() const; - - void setItemData(const QString &itemData); - const QString &itemData() const; - - void setFallthrough(const QString &fallthrough); - bool isFallthrough() const; - - void setDynamic(const QString &dynamic); - bool isDynamic() const; - void updateDynamicRules(const QStringList &captures) const; - - void addRule(const QSharedPointer<Rule> &rule); - void addRule(const QSharedPointer<Rule> &rule, int index); - const QList<QSharedPointer<Rule> > &rules() const; - - void addIncludeRulesInstruction(const IncludeRulesInstruction &instruction); - const QList<IncludeRulesInstruction> &includeRulesInstructions() const; - void clearIncludeRulesInstructions(); - - void setDefinition(const QSharedPointer<HighlightDefinition> &definition); - const QSharedPointer<HighlightDefinition> &definition() const; - - void swap(Context &context); - -private: - QString m_id; - QString m_name; - QString m_lineBeginContext; - QString m_lineEndContext; - QString m_lineEmptyContext; - QString m_fallthroughContext; - QString m_itemData; - bool m_fallthrough; - bool m_dynamic; - - QList<QSharedPointer<Rule> > m_rules; - QList<IncludeRulesInstruction> m_instructions; - - QSharedPointer<HighlightDefinition> m_definition; -}; - -} // namespace Internal -} // namespace TextEditor diff --git a/src/plugins/texteditor/generichighlighter/definitiondownloader.cpp b/src/plugins/texteditor/generichighlighter/definitiondownloader.cpp deleted file mode 100644 index 680d811148..0000000000 --- a/src/plugins/texteditor/generichighlighter/definitiondownloader.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "definitiondownloader.h" - -#include <utils/fileutils.h> - -#include <QLatin1Char> -#include <QEventLoop> -#include <QScopedPointer> -#include <QNetworkRequest> -#include <QNetworkReply> -#include <QRegExp> - -#include <utils/networkaccessmanager.h> - -namespace TextEditor { -namespace Internal { - -static QNetworkReply *getData(QNetworkAccessManager *manager, const QUrl &url) -{ - QNetworkRequest request(url); - QNetworkReply *reply = manager->get(request); - - QEventLoop eventLoop; - QObject::connect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit); - eventLoop.exec(); - - return reply; -} - -DefinitionDownloader::DefinitionDownloader(const QUrl &url, const QString &localPath) : - m_url(url), m_localPath(localPath), m_status(Unknown) -{} - -void DefinitionDownloader::run() -{ - Utils::NetworkAccessManager manager; - - int currentAttempt = 0; - const int maxAttempts = 5; - while (currentAttempt < maxAttempts) { - QScopedPointer<QNetworkReply> reply(getData(&manager, m_url)); - if (reply->error() != QNetworkReply::NoError) { - m_status = NetworkError; - return; - } - - ++currentAttempt; - QVariant variant = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); - if (variant.isValid() && currentAttempt < maxAttempts) { - m_url = variant.toUrl(); - } else if (!variant.isValid()) { - saveData(reply.data()); - return; - } - } -} - -void DefinitionDownloader::saveData(QNetworkReply *reply) -{ - const QString &urlPath = m_url.path(); - const QString &fileName = - urlPath.right(urlPath.length() - urlPath.lastIndexOf(QLatin1Char('/')) - 1); - Utils::FileSaver saver(m_localPath + fileName, QIODevice::Text); - const QByteArray data = reply->readAll(); - saver.write(data); - m_status = saver.finalize() ? Ok: WriteError; - QString content = QString::fromUtf8(data); - QRegExp reference(QLatin1String("context\\s*=\\s*\"[^\"]*##([^\"]+)\"")); - int index = -1; - forever { - index = reference.indexIn(content, index + 1); - if (index == -1) - break; - emit foundReferencedDefinition(reference.cap(1)); - } -} - -DefinitionDownloader::Status DefinitionDownloader::status() const -{ return m_status; } - -} // namespace Internal -} // namespace TextEditor diff --git a/src/plugins/texteditor/generichighlighter/definitiondownloader.h b/src/plugins/texteditor/generichighlighter/definitiondownloader.h deleted file mode 100644 index 95ab812114..0000000000 --- a/src/plugins/texteditor/generichighlighter/definitiondownloader.h +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include <QObject> -#include <QString> -#include <QUrl> - -QT_BEGIN_NAMESPACE -class QNetworkReply; -QT_END_NAMESPACE - -namespace TextEditor { -namespace Internal { - -class DefinitionDownloader : public QObject -{ - Q_OBJECT -public: - DefinitionDownloader(const QUrl &url, const QString &localPath); - - enum Status { - NetworkError, - WriteError, - Ok, - Unknown - }; - - void run(); - Status status() const; - -signals: - void foundReferencedDefinition(const QString &name); - -private: - void saveData(QNetworkReply *reply); - - QUrl m_url; - QString m_localPath; - Status m_status; -}; - -} // namespace Internal -} // namespace TextEditor diff --git a/src/plugins/texteditor/generichighlighter/dynamicrule.cpp b/src/plugins/texteditor/generichighlighter/dynamicrule.cpp deleted file mode 100644 index abb4b73faa..0000000000 --- a/src/plugins/texteditor/generichighlighter/dynamicrule.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "dynamicrule.h" -#include "reuse.h" - -using namespace TextEditor; -using namespace Internal; - -DynamicRule::DynamicRule() : m_active(false) -{} - -DynamicRule::~DynamicRule() = default; - -void DynamicRule::setActive(const QString &active) -{ m_active = toBool(active); } - -bool DynamicRule::isActive() const -{ return m_active; } - -void DynamicRule::replaceExpressions(const QStringList &captures) -{ - doReplaceExpressions(captures); - updateDynamicRules(children(), captures); -} - -namespace TextEditor { -namespace Internal { - -void updateDynamicRules(const QList<QSharedPointer<Rule> > &rules, const QStringList &captures) -{ - foreach (QSharedPointer<Rule> rule, rules) { - auto dynamicRule = dynamic_cast<DynamicRule *>(rule.data()); - if (dynamicRule && dynamicRule->isActive()) - dynamicRule->replaceExpressions(captures); - } -} - -} // namespace Internal -} // namespace TextEditor diff --git a/src/plugins/texteditor/generichighlighter/highlightdefinition.cpp b/src/plugins/texteditor/generichighlighter/highlightdefinition.cpp deleted file mode 100644 index 66e3cb2712..0000000000 --- a/src/plugins/texteditor/generichighlighter/highlightdefinition.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "highlightdefinition.h" -#include "highlighterexception.h" -#include "context.h" -#include "keywordlist.h" -#include "itemdata.h" -#include "reuse.h" - -#include <QCoreApplication> -#include <QString> - -using namespace TextEditor; -using namespace Internal; - -namespace { - -template <class Element, class Container> -QSharedPointer<Element> createHelper(const QString &name, Container &container) -{ - if (name.isEmpty()) { - throw HighlighterException( - QCoreApplication::translate("GenericHighlighter", "Element name is empty.")); - } - - if (container.contains(name)) { - throw HighlighterException( - QCoreApplication::translate("GenericHighlighter", - "Duplicate element name \"%1\".").arg(name)); - } - - return container.insert(name, QSharedPointer<Element>(new Element)).value(); -} - -template <class Element, class Container> -QSharedPointer<Element> -findHelper(const QString &name, const Container &container) -{ - typename Container::const_iterator it = container.find(name); - if (it == container.end()) { - throw HighlighterException( - QCoreApplication::translate("GenericHighlighter", - "Name \"%1\" not found.").arg(name)); - } - - return it.value(); -} - -} // anon namespace - -HighlightDefinition::HighlightDefinition() : - m_keywordCaseSensitivity(Qt::CaseSensitive), - m_singleLineCommentAfterWhiteSpaces(false), - m_indentationBasedFolding(false) -{ - const QString s(QLatin1String(".():!+,-<=>%&/;?[]^{|}~\\*, \t")); - for (auto &c : s) - m_delimiters.insert(c); -} - -HighlightDefinition::~HighlightDefinition() = default; - -bool HighlightDefinition::isValid() const -{ - return !m_initialContext.isEmpty(); -} - -QSharedPointer<KeywordList> HighlightDefinition::createKeywordList(const QString &list) -{ - return createHelper<KeywordList>(list, m_lists); -} - -QSharedPointer<KeywordList> HighlightDefinition::keywordList(const QString &list) -{ - return findHelper<KeywordList>(list, m_lists); -} - -QSharedPointer<Context> HighlightDefinition::createContext(const QString &context, bool initial) -{ - if (initial) - m_initialContext = context; - - QSharedPointer<Context> newContext = createHelper<Context>(context, m_contexts); - newContext->setName(context); - return newContext; -} - -QSharedPointer<Context> HighlightDefinition::initialContext() const -{ - return findHelper<Context>(m_initialContext, m_contexts); -} - -QSharedPointer<Context> HighlightDefinition::context(const QString &context) const -{ - return findHelper<Context>(context, m_contexts); -} - -const QHash<QString, QSharedPointer<Context> > &HighlightDefinition::contexts() const -{ - return m_contexts; -} - -QSharedPointer<ItemData> HighlightDefinition::createItemData(const QString &itemData) -{ - return createHelper<ItemData>(itemData, m_itemsData); -} - -QSharedPointer<ItemData> HighlightDefinition::itemData(const QString &itemData) const -{ - return findHelper<ItemData>(itemData, m_itemsData); -} - -void HighlightDefinition::setSingleLineComment(const QString &start) -{ m_singleLineComment = start; } - -const QString &HighlightDefinition::singleLineComment() const -{ return m_singleLineComment; } - -void HighlightDefinition::setCommentAfterWhitespaces(const QString &after) -{ - if (after == QLatin1String("afterwhitespace")) - m_singleLineCommentAfterWhiteSpaces = true; -} - -bool HighlightDefinition::isCommentAfterWhiteSpaces() const -{ return m_singleLineCommentAfterWhiteSpaces; } - -void HighlightDefinition::setMultiLineCommentStart(const QString &start) -{ m_multiLineCommentStart = start; } - -const QString &HighlightDefinition::multiLineCommentStart() const -{ return m_multiLineCommentStart; } - -void HighlightDefinition::setMultiLineCommentEnd(const QString &end) -{ m_multiLineCommentEnd = end; } - -const QString &HighlightDefinition::multiLineCommentEnd() const -{ return m_multiLineCommentEnd; } - -void HighlightDefinition::setMultiLineCommentRegion(const QString ®ion) -{ m_multiLineCommentRegion = region; } - -const QString &HighlightDefinition::multiLineCommentRegion() const -{ return m_multiLineCommentRegion; } - -void HighlightDefinition::removeDelimiters(const QString &characters) -{ - for (QChar character : characters) - m_delimiters.remove(character); -} - -void HighlightDefinition::addDelimiters(const QString &characters) -{ - for (QChar character : characters) { - if (!m_delimiters.contains(character)) - m_delimiters.insert(character); - } -} - -bool HighlightDefinition::isDelimiter(const QChar &character) const -{ - if (m_delimiters.contains(character)) - return true; - return false; -} - -void HighlightDefinition::setKeywordsSensitive(const QString &sensitivity) -{ - if (!sensitivity.isEmpty()) - m_keywordCaseSensitivity = toCaseSensitivity(toBool(sensitivity)); -} - -Qt::CaseSensitivity HighlightDefinition::keywordsSensitive() const -{ return m_keywordCaseSensitivity; } - -void HighlightDefinition::setIndentationBasedFolding(const QString &indentationBasedFolding) -{ m_indentationBasedFolding = toBool(indentationBasedFolding); } - -bool HighlightDefinition::isIndentationBasedFolding() const -{ return m_indentationBasedFolding; } diff --git a/src/plugins/texteditor/generichighlighter/highlightdefinition.h b/src/plugins/texteditor/generichighlighter/highlightdefinition.h deleted file mode 100644 index f39373df18..0000000000 --- a/src/plugins/texteditor/generichighlighter/highlightdefinition.h +++ /dev/null @@ -1,108 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include <QString> -#include <QHash> -#include <QSet> -#include <QSharedPointer> - -namespace TextEditor { -namespace Internal { - -class KeywordList; -class Context; -class ItemData; - -class HighlightDefinition -{ -public: - HighlightDefinition(); - ~HighlightDefinition(); - - bool isValid() const; - - QSharedPointer<KeywordList> createKeywordList(const QString &list); - QSharedPointer<KeywordList> keywordList(const QString &list); - - QSharedPointer<Context> createContext(const QString &context, bool initial); - QSharedPointer<Context> initialContext() const; - QSharedPointer<Context> context(const QString &context) const; - const QHash<QString, QSharedPointer<Context> > &contexts() const; - - QSharedPointer<ItemData> createItemData(const QString &itemData); - QSharedPointer<ItemData> itemData(const QString &itemData) const; - - void setKeywordsSensitive(const QString &sensitivity); - Qt::CaseSensitivity keywordsSensitive() const; - - void addDelimiters(const QString &characters); - void removeDelimiters(const QString &characters); - bool isDelimiter(const QChar &character) const; - - void setSingleLineComment(const QString &start); - const QString &singleLineComment() const; - - void setCommentAfterWhitespaces(const QString &after); - bool isCommentAfterWhiteSpaces() const; - - void setMultiLineCommentStart(const QString &start); - const QString &multiLineCommentStart() const; - - void setMultiLineCommentEnd(const QString &end); - const QString &multiLineCommentEnd() const; - - void setMultiLineCommentRegion(const QString ®ion); - const QString &multiLineCommentRegion() const; - - void setIndentationBasedFolding(const QString &indentationBasedFolding); - bool isIndentationBasedFolding() const; - -private: - Q_DISABLE_COPY(HighlightDefinition) - - QHash<QString, QSharedPointer<KeywordList> > m_lists; - QHash<QString, QSharedPointer<Context> > m_contexts; - QHash<QString, QSharedPointer<ItemData> > m_itemsData; - - QString m_initialContext; - - QString m_singleLineComment; - - QString m_multiLineCommentStart; - QString m_multiLineCommentEnd; - QString m_multiLineCommentRegion; - - Qt::CaseSensitivity m_keywordCaseSensitivity; - - bool m_singleLineCommentAfterWhiteSpaces; - bool m_indentationBasedFolding; - - QSet<QChar> m_delimiters; -}; - -} // namespace Internal -} // namespace TextEditor diff --git a/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.cpp b/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.cpp deleted file mode 100644 index 56b1626414..0000000000 --- a/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.cpp +++ /dev/null @@ -1,502 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "highlightdefinitionhandler.h" -#include "highlightdefinition.h" -#include "highlighterexception.h" -#include "specificrules.h" -#include "itemdata.h" -#include "keywordlist.h" -#include "context.h" -#include "manager.h" - -#include <coreplugin/messagemanager.h> - -#include <QCoreApplication> -#include <QLatin1String> - -using namespace TextEditor; -using namespace Internal; - -namespace { - static const QLatin1String kName("name"); - static const QLatin1String kList("list"); - static const QLatin1String kItem("item"); - static const QLatin1String kContext("context"); - static const QLatin1String kAttribute("attribute"); - static const QLatin1String kDynamic("dynamic"); - static const QLatin1String kFallthrough("fallthrough"); - static const QLatin1String kLineEndContext("lineEndContext"); - static const QLatin1String kLineEmptyContext("lineEmptyContext"); - static const QLatin1String kLineBeginContext("lineBeginContext"); - static const QLatin1String kFallthroughContext("fallthroughContext"); - static const QLatin1String kBeginRegion("beginRegion"); - static const QLatin1String kEndRegion("endRegion"); - static const QLatin1String kLookAhead("lookAhead"); - static const QLatin1String kFirstNonSpace("firstNonSpace"); - static const QLatin1String kColumn("column"); - static const QLatin1String kItemData("itemData"); - static const QLatin1String kDefStyleNum("defStyleNum"); - static const QLatin1String kColor("color"); - static const QLatin1String kSelColor("selColor"); - static const QLatin1String kItalic("italic"); - static const QLatin1String kBold("bold"); - static const QLatin1String kUnderline("underline"); - static const QLatin1String kStrikeout("strikeout"); - static const QLatin1String kChar("char"); - static const QLatin1String kChar1("char1"); - static const QLatin1String kString("String"); - static const QLatin1String kInsensitive("insensitive"); - static const QLatin1String kMinimal("minimal"); - static const QLatin1String kKeywords("keywords"); - static const QLatin1String kCaseSensitive("casesensitive"); - static const QLatin1String kWeakDeliminator("weakDeliminator"); - static const QLatin1String kAdditionalDeliminator("additionalDeliminator"); - static const QLatin1String kComment("comment"); - static const QLatin1String kPosition("position"); - static const QLatin1String kSingleLine("singleline"); - static const QLatin1String kMultiLine("multiline"); - static const QLatin1String kStart("start"); - static const QLatin1String kEnd("end"); - static const QLatin1String kRegion("region"); - static const QLatin1String kDetectChar("DetectChar"); - static const QLatin1String kDetect2Chars("Detect2Chars"); - static const QLatin1String kAnyChar("AnyChar"); - static const QLatin1String kStringDetect("StringDetect"); - static const QLatin1String kWordDetect("WordDetect"); - static const QLatin1String kRegExpr("RegExpr"); - static const QLatin1String kKeyword("keyword"); - static const QLatin1String kInt("Int"); - static const QLatin1String kFloat("Float"); - static const QLatin1String kHlCOct("HlCOct"); - static const QLatin1String kHlCHex("HlCHex"); - static const QLatin1String kHlCStringChar("HlCStringChar"); - static const QLatin1String kHlCChar("HlCChar"); - static const QLatin1String kRangeDetect("RangeDetect"); - static const QLatin1String kLineContinue("LineContinue"); - static const QLatin1String kIncludeRules("IncludeRules"); - static const QLatin1String kDetectSpaces("DetectSpaces"); - static const QLatin1String kDetectIdentifier("DetectIdentifier"); - static const QLatin1String kIncludeAttrib("includeAttrib"); - static const QLatin1String kFolding("folding"); - static const QLatin1String kIndentationSensitive("indentationsensitive"); - static const QLatin1String kHash("#"); - static const QLatin1String kDoubleHash("##"); -} - -HighlightDefinitionHandler:: -HighlightDefinitionHandler(const QSharedPointer<HighlightDefinition> &definition) : - m_definition(definition), - m_processingKeyword(false), - m_initialContext(true) -{} - -HighlightDefinitionHandler::~HighlightDefinitionHandler() = default; - -bool HighlightDefinitionHandler::startDocument() -{ - return true; -} - -bool HighlightDefinitionHandler::endDocument() -{ - processIncludeRules(); - return true; -} - -bool HighlightDefinitionHandler::startElement(const QString &, - const QString &, - const QString &qName, - const QXmlAttributes &atts) -{ - if (qName == kList) - listElementStarted(atts); - else if (qName == kItem) - itemElementStarted(); - else if (qName == kContext) - contextElementStarted(atts); - else if (qName == kItemData) - itemDataElementStarted(atts); - else if (qName == kComment) - commentElementStarted(atts); - else if (qName == kKeywords) - keywordsElementStarted(atts); - else if (qName == kFolding) - foldingElementStarted(atts); - else if (qName == kDetectChar) - detectCharStarted(atts); - else if (qName == kDetect2Chars) - detect2CharsStarted(atts); - else if (qName == kAnyChar) - anyCharStarted(atts); - else if (qName == kStringDetect) - stringDetectedStarted(atts); - else if (qName == kWordDetect) - wordDetectStarted(atts); - else if (qName == kRegExpr) - regExprStarted(atts); - else if (qName == kKeyword) - keywordStarted(atts); - else if (qName == kInt) - intStarted(atts); - else if (qName == kFloat) - floatStarted(atts); - else if (qName == kHlCOct) - hlCOctStarted(atts); - else if (qName == kHlCHex) - hlCHexStarted(atts); - else if (qName == kHlCStringChar) - hlCStringCharStarted(atts); - else if (qName == kHlCChar) - hlCCharStarted(atts); - else if (qName == kRangeDetect) - rangeDetectStarted(atts); - else if (qName == kLineContinue) - lineContinue(atts); - else if (qName == kIncludeRules) - includeRulesStarted(atts); - else if (qName == kDetectSpaces) - detectSpacesStarted(atts); - else if (qName == kDetectIdentifier) - detectIdentifier(atts); - - return true; -} - -bool HighlightDefinitionHandler::endElement(const QString &, const QString &, const QString &qName) -{ - if (qName == kItem) { - m_currentList->addKeyword(m_currentKeyword.trimmed()); - m_processingKeyword = false; - } else if (qName == kDetectChar || qName == kDetect2Chars || qName == kAnyChar || - qName == kStringDetect || qName == kWordDetect || qName == kRegExpr || - qName == kKeyword || qName == kInt || - qName == kFloat || qName == kHlCOct || qName == kHlCHex || qName == kHlCStringChar || - qName == kHlCChar || qName == kRangeDetect || qName == kLineContinue || - qName == kDetectSpaces || qName == kDetectIdentifier) { - m_currentRule.pop(); - } - - return true; -} - -bool HighlightDefinitionHandler::characters(const QString& ch) -{ - // Character data of an element may be reported in more than one chunk. - if (m_processingKeyword) - m_currentKeyword.append(ch); - - return true; -} - -void HighlightDefinitionHandler::listElementStarted(const QXmlAttributes &atts) -{ - m_currentList = m_definition->createKeywordList(atts.value(kName)); -} - -void HighlightDefinitionHandler::itemElementStarted() -{ - m_currentKeyword.clear(); - m_processingKeyword = true; -} - -void HighlightDefinitionHandler::contextElementStarted(const QXmlAttributes &atts) -{ - m_currentContext = m_definition->createContext(atts.value(kName), m_initialContext); - m_currentContext->setDefinition(m_definition); - m_currentContext->setItemData(atts.value(kAttribute)); - m_currentContext->setDynamic(atts.value(kDynamic)); - m_currentContext->setFallthrough(atts.value(kFallthrough)); - m_currentContext->setFallthroughContext(atts.value(kFallthroughContext)); - m_currentContext->setLineBeginContext(atts.value(kLineBeginContext)); - m_currentContext->setLineEndContext(atts.value(kLineEndContext)); - m_currentContext->setLineEmptyContext(atts.value(kLineEmptyContext)); - - m_initialContext = false; -} - -void HighlightDefinitionHandler::ruleElementStarted(const QXmlAttributes &atts, - const QSharedPointer<Rule> &rule) -{ - const QString context = atts.value(kContext); - // The definition of a rule is not necessarily the same of its enclosing context because of - // externally included rules. - rule->setDefinition(m_definition); - rule->setItemData(atts.value(kAttribute)); - rule->setContext(context); - rule->setBeginRegion(atts.value(kBeginRegion)); - rule->setEndRegion(atts.value(kEndRegion)); - rule->setLookAhead(atts.value(kLookAhead)); - rule->setFirstNonSpace(atts.value(kFirstNonSpace)); - rule->setColumn(atts.value(kColumn)); - - if (context.contains(kDoubleHash)) { - IncludeRulesInstruction includeInstruction(context, m_currentContext->rules().size(), QString()); - m_currentContext->addIncludeRulesInstruction(includeInstruction); - } - if (m_currentRule.isEmpty()) - m_currentContext->addRule(rule); - else - m_currentRule.top()->addChild(rule); - - m_currentRule.push(rule); -} - -void HighlightDefinitionHandler::itemDataElementStarted(const QXmlAttributes &atts) const -{ - QSharedPointer<ItemData> itemData = m_definition->createItemData(atts.value(kName)); - itemData->setStyle(atts.value(kDefStyleNum)); - itemData->setColor(atts.value(kColor)); - itemData->setSelectionColor(atts.value(kSelColor)); - itemData->setItalic(atts.value(kItalic)); - itemData->setBold(atts.value(kBold)); - itemData->setUnderlined(atts.value(kUnderline)); - itemData->setStrikeOut(atts.value(kStrikeout)); -} - -void HighlightDefinitionHandler::commentElementStarted(const QXmlAttributes &atts) const -{ - const QString &commentType = atts.value(kName); - if (commentType.compare(kSingleLine, Qt::CaseInsensitive) == 0) { - m_definition->setSingleLineComment(atts.value(kStart)); - m_definition->setCommentAfterWhitespaces(atts.value(kPosition)); - } else if (commentType.compare(kMultiLine, Qt::CaseInsensitive) == 0) { - m_definition->setMultiLineCommentStart(atts.value(kStart)); - m_definition->setMultiLineCommentEnd(atts.value(kEnd)); - m_definition->setMultiLineCommentRegion(atts.value(kRegion)); - } -} - -void HighlightDefinitionHandler::keywordsElementStarted(const QXmlAttributes &atts) const -{ - // Global case sensitivity appears last in the document (required by dtd) and is set here. - m_definition->setKeywordsSensitive(atts.value(kCaseSensitive)); - m_definition->removeDelimiters(atts.value(kWeakDeliminator)); - m_definition->addDelimiters(atts.value(kAdditionalDeliminator)); - //@todo: wordWrapDelimiters? -} - -void HighlightDefinitionHandler::foldingElementStarted(const QXmlAttributes &atts) const -{ - m_definition->setIndentationBasedFolding(atts.value(kIndentationSensitive)); -} - -void HighlightDefinitionHandler::detectCharStarted(const QXmlAttributes &atts) -{ - auto rule = new DetectCharRule; - rule->setChar(atts.value(kChar)); - rule->setActive(atts.value(kDynamic)); - ruleElementStarted(atts, QSharedPointer<Rule>(rule)); -} - -void HighlightDefinitionHandler::detect2CharsStarted(const QXmlAttributes &atts) -{ - auto rule = new Detect2CharsRule; - rule->setChar(atts.value(kChar)); - rule->setChar1(atts.value(kChar1)); - rule->setActive(atts.value(kDynamic)); - ruleElementStarted(atts, QSharedPointer<Rule>(rule)); -} - -void HighlightDefinitionHandler::anyCharStarted(const QXmlAttributes &atts) -{ - auto rule = new AnyCharRule; - rule->setCharacterSet(atts.value(kString)); - ruleElementStarted(atts, QSharedPointer<Rule>(rule)); -} - -void HighlightDefinitionHandler::stringDetectedStarted(const QXmlAttributes &atts) -{ - auto rule = new StringDetectRule; - rule->setString(atts.value(kString)); - rule->setInsensitive(atts.value(kInsensitive)); - rule->setActive(atts.value(kDynamic)); - ruleElementStarted(atts, QSharedPointer<Rule>(rule)); -} - -void HighlightDefinitionHandler::wordDetectStarted(const QXmlAttributes &atts) -{ - auto rule = new WordDetectRule; - rule->setString(atts.value(kString)); - rule->setInsensitive(atts.value(kInsensitive)); - rule->setActive(atts.value(kDynamic)); - ruleElementStarted(atts, QSharedPointer<Rule>(rule)); -} - -void HighlightDefinitionHandler::regExprStarted(const QXmlAttributes &atts) -{ - auto rule = new RegExprRule; - rule->setPattern(atts.value(kString)); - rule->setMinimal(atts.value(kMinimal)); - rule->setInsensitive(atts.value(kInsensitive)); - rule->setActive(atts.value(kDynamic)); - ruleElementStarted(atts, QSharedPointer<Rule>(rule)); -} - -void HighlightDefinitionHandler::keywordStarted(const QXmlAttributes &atts) -{ - auto rule = new KeywordRule(m_definition); - try { - rule->setList(atts.value(kString)); - } catch (const HighlighterException &e) { - // Handle broken files. makefile.xml references an invalid list. - Core::MessageManager::write( - QCoreApplication::translate("GenericHighlighter", - "Generic highlighter warning: %1") - .arg(e.message())); - } - rule->setInsensitive(atts.value(kInsensitive)); - ruleElementStarted(atts, QSharedPointer<Rule>(rule)); -} - -void HighlightDefinitionHandler::intStarted(const QXmlAttributes &atts) -{ - ruleElementStarted(atts, QSharedPointer<Rule>(new IntRule)); -} - -void HighlightDefinitionHandler::floatStarted(const QXmlAttributes &atts) -{ - ruleElementStarted(atts, QSharedPointer<Rule>(new FloatRule)); -} - -void HighlightDefinitionHandler::hlCOctStarted(const QXmlAttributes &atts) -{ - ruleElementStarted(atts, QSharedPointer<Rule>(new HlCOctRule)); -} - -void HighlightDefinitionHandler::hlCHexStarted(const QXmlAttributes &atts) -{ - ruleElementStarted(atts, QSharedPointer<Rule>(new HlCHexRule)); -} - -void HighlightDefinitionHandler::hlCStringCharStarted(const QXmlAttributes &atts) -{ - ruleElementStarted(atts, QSharedPointer<Rule>(new HlCStringCharRule)); -} - -void HighlightDefinitionHandler::hlCCharStarted(const QXmlAttributes &atts) -{ - ruleElementStarted(atts, QSharedPointer<Rule>(new HlCCharRule)); -} - -void HighlightDefinitionHandler::rangeDetectStarted(const QXmlAttributes &atts) -{ - auto rule = new RangeDetectRule; - rule->setChar(atts.value(kChar)); - rule->setChar1(atts.value(kChar1)); - ruleElementStarted(atts, QSharedPointer<Rule>(rule)); -} - -void HighlightDefinitionHandler::lineContinue(const QXmlAttributes &atts) -{ - ruleElementStarted(atts, QSharedPointer<Rule>(new LineContinueRule)); -} - -void HighlightDefinitionHandler::includeRulesStarted(const QXmlAttributes &atts) -{ - // Include rules are treated as instructions for latter processing. - IncludeRulesInstruction instruction(atts.value(kContext), m_currentContext->rules().size(), - atts.value(kIncludeAttrib)); - - // Include rules (as many others) are not allowed as a child. - m_currentContext->addIncludeRulesInstruction(instruction); -} - -void HighlightDefinitionHandler::detectSpacesStarted(const QXmlAttributes &atts) -{ - ruleElementStarted(atts, QSharedPointer<Rule>(new DetectSpacesRule)); -} - -void HighlightDefinitionHandler::detectIdentifier(const QXmlAttributes &atts) -{ - ruleElementStarted(atts, QSharedPointer<Rule>(new DetectIdentifierRule)); -} - -void HighlightDefinitionHandler::processIncludeRules() const -{ - const QHash<QString, QSharedPointer<Context> > &allContexts = m_definition->contexts(); - foreach (const QSharedPointer<Context> &context, allContexts) - processIncludeRules(context); -} - -void HighlightDefinitionHandler::processIncludeRules(const QSharedPointer<Context> &context) const -{ - if (context->includeRulesInstructions().isEmpty()) - return; - - int rulesIncluded = 0; - const QList<IncludeRulesInstruction> &instructions = context->includeRulesInstructions(); - foreach (const IncludeRulesInstruction &instruction, instructions) { - - QSharedPointer<Context> sourceContext; - const QString &sourceName = instruction.sourceContext(); - if (sourceName.contains(kDoubleHash)) { - // This refers to an external definition. Context can be specified before the double - // hash (e.g. Normal##Javascript). If it isn't, the rules included are the ones from its - // initial context. Others contexts and rules from the external definition will work - // transparently to the highlighter. This is because contexts and rules know the - // definition they are from. - const QStringList values = sourceName.split(kDoubleHash); - if (values.count() != 2) - return; - const QString externalContext = values.at(0); - const QString externalName = values.at(1); - const QString &id = Manager::instance()->definitionIdByName(externalName); - - // If there is an incorrect circular dependency among definitions this is skipped. - if (Manager::instance()->isBuildingDefinition(id)) - continue; - - const QSharedPointer<HighlightDefinition> &externalDefinition = - Manager::instance()->definition(id); - if (externalDefinition.isNull() || !externalDefinition->isValid()) - continue; - - if (externalContext.isEmpty()) - sourceContext = externalDefinition->initialContext(); - else - sourceContext = externalDefinition->context(externalContext); - } else if (!sourceName.startsWith(kHash)) { - sourceContext = m_definition->context(sourceName); - - // Recursion is done only for context direct rules. Child rules are not processed - // because they cannot be include rules. - processIncludeRules(sourceContext); - } else { - continue; - } - - if (instruction.replaceItemData()) { - context->setItemData(sourceContext->itemData()); - context->setDefinition(sourceContext->definition()); - } - - foreach (QSharedPointer<Rule> rule, sourceContext->rules()) { - context->addRule(rule, instruction.indexHint() + rulesIncluded); - ++rulesIncluded; - } - } - context->clearIncludeRulesInstructions(); -} diff --git a/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.h b/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.h deleted file mode 100644 index bb7317ec51..0000000000 --- a/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.h +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include <QString> -#include <QSharedPointer> -#include <QStack> - -#include <QXmlDefaultHandler> - -namespace TextEditor { -namespace Internal { - -class KeywordList; -class Context; -class Rule; -class HighlightDefinition; - -class HighlightDefinitionHandler : public QXmlDefaultHandler -{ -public: - HighlightDefinitionHandler(const QSharedPointer<HighlightDefinition> &definition); - ~HighlightDefinitionHandler() override; - - bool startDocument() override; - bool endDocument() override; - bool startElement(const QString &namespaceURI, const QString &localName, - const QString &qName, const QXmlAttributes &atts) override; - bool endElement(const QString &namespaceURI, const QString &localName, - const QString &qName) override; - bool characters(const QString &ch) override; - -private: - void listElementStarted(const QXmlAttributes &atts); - void itemElementStarted(); - void contextElementStarted(const QXmlAttributes &atts); - void itemDataElementStarted(const QXmlAttributes &atts) const; - void commentElementStarted(const QXmlAttributes &atts) const; - void keywordsElementStarted(const QXmlAttributes &atts) const; - void foldingElementStarted(const QXmlAttributes &atts) const; - void ruleElementStarted(const QXmlAttributes &atts, const QSharedPointer<Rule> &rule); - - // Specific rules. - void detectCharStarted(const QXmlAttributes &atts); - void detect2CharsStarted(const QXmlAttributes &atts); - void anyCharStarted(const QXmlAttributes &atts); - void stringDetectedStarted(const QXmlAttributes &atts); - void wordDetectStarted(const QXmlAttributes &atts); - void regExprStarted(const QXmlAttributes &atts); - void keywordStarted(const QXmlAttributes &atts); - void intStarted(const QXmlAttributes &atts); - void floatStarted(const QXmlAttributes &atts); - void hlCOctStarted(const QXmlAttributes &atts); - void hlCHexStarted(const QXmlAttributes &atts); - void hlCStringCharStarted(const QXmlAttributes &atts); - void hlCCharStarted(const QXmlAttributes &atts); - void rangeDetectStarted(const QXmlAttributes &atts); - void lineContinue(const QXmlAttributes &atts); - void includeRulesStarted(const QXmlAttributes &atts); - void detectSpacesStarted(const QXmlAttributes &atts); - void detectIdentifier(const QXmlAttributes &atts); - - void processIncludeRules() const; - void processIncludeRules(const QSharedPointer<Context> &context) const; - - QSharedPointer<HighlightDefinition> m_definition; - - bool m_processingKeyword; - QString m_currentKeyword; - QSharedPointer<KeywordList> m_currentList; - QSharedPointer<Context> m_currentContext; - QStack<QSharedPointer<Rule> > m_currentRule; - - bool m_initialContext; -}; - -} // namespace Internal -} // namespace TextEditor diff --git a/src/plugins/texteditor/generichighlighter/highlightdefinitionmetadata.h b/src/plugins/texteditor/generichighlighter/highlightdefinitionmetadata.h deleted file mode 100644 index f201d3c189..0000000000 --- a/src/plugins/texteditor/generichighlighter/highlightdefinitionmetadata.h +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include <QSharedPointer> -#include <QStringList> -#include <QUrl> - -namespace TextEditor { -namespace Internal { - -class HighlightDefinitionMetaData -{ -public: - HighlightDefinitionMetaData() = default; - -public: - int priority = 0; - QString id; - QString name; - QString version; - QString fileName; - QStringList patterns; - QStringList mimeTypes; - QUrl url; -}; - -using DefinitionMetaDataPtr = QSharedPointer<HighlightDefinitionMetaData>; - -} // namespace Internal -} // namespace TextEditor diff --git a/src/plugins/texteditor/generichighlighter/highlighter.cpp b/src/plugins/texteditor/generichighlighter/highlighter.cpp deleted file mode 100644 index 8ea7dbbda3..0000000000 --- a/src/plugins/texteditor/generichighlighter/highlighter.cpp +++ /dev/null @@ -1,740 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "context.h" -#include "highlightdefinition.h" -#include "highlighter.h" -#include "highlighterexception.h" -#include "itemdata.h" -#include "progressdata.h" -#include "reuse.h" -#include "rule.h" -#include "tabsettings.h" - -#include <coreplugin/messagemanager.h> -#include <texteditor/fontsettings.h> -#include <texteditor/texteditorsettings.h> -#include <utils/qtcassert.h> - -#include <QCoreApplication> - -#include <cmath> - -using namespace TextEditor; -using namespace Internal; - -namespace { - static const QLatin1String kStay("#stay"); - static const QLatin1String kPop("#pop"); - static const QLatin1Char kBackSlash('\\'); - static const QLatin1Char kHash('#'); - static const QLatin1Char kExclamationMark('!'); -} - -class HighlighterCodeFormatterData : public CodeFormatterData -{ -public: - ~HighlighterCodeFormatterData() override = default; - int m_foldingIndentDelta = 0; - int m_originalObservableState = -1; - QStack<QString> m_foldingRegions; - int m_continueObservableState = -1; -}; - -HighlighterCodeFormatterData *formatterData(const QTextBlock &block) -{ - HighlighterCodeFormatterData *data = nullptr; - if (TextBlockUserData *userData = TextDocumentLayout::userData(block)) { - data = static_cast<HighlighterCodeFormatterData *>(userData->codeFormatterData()); - if (!data) { - data = new HighlighterCodeFormatterData; - userData->setCodeFormatterData(data); - } - } - return data; -} - -static TextStyle styleForFormat(int format) -{ - const auto f = Highlighter::TextFormatId(format); - switch (f) { - case Highlighter::Normal: return C_TEXT; - case Highlighter::Keyword: return C_KEYWORD; - case Highlighter::DataType: return C_TYPE; - case Highlighter::Comment: return C_COMMENT; - case Highlighter::Decimal: return C_NUMBER; - case Highlighter::BaseN: return C_NUMBER; - case Highlighter::Float: return C_NUMBER; - case Highlighter::Char: return C_STRING; - case Highlighter::SpecialChar: return C_STRING; - case Highlighter::String: return C_STRING; - case Highlighter::Alert: return C_WARNING; - case Highlighter::Information: return C_TEXT; - case Highlighter::Warning: return C_WARNING; - case Highlighter::Error: return C_ERROR; - case Highlighter::Function: return C_FUNCTION; - case Highlighter::RegionMarker: return C_TEXT; - case Highlighter::BuiltIn: return C_PREPROCESSOR; - case Highlighter::Extension: return C_PRIMITIVE_TYPE; - case Highlighter::Operator: return C_OPERATOR; - case Highlighter::Variable: return C_LOCAL; - case Highlighter::Attribute: return C_LABEL; - case Highlighter::Annotation: return C_TEXT; - case Highlighter::CommentVar: return C_COMMENT; - case Highlighter::Import: return C_PREPROCESSOR; - case Highlighter::Others: return C_TEXT; - case Highlighter::Identifier: return C_LOCAL; - case Highlighter::Documentation: return C_DOXYGEN_COMMENT; - case Highlighter::ControlFlow: return C_KEYWORD; - case Highlighter::Preprocessor: return C_PREPROCESSOR; - case Highlighter::VerbatimString: return C_STRING; - case Highlighter::SpecialString: return C_STRING; - case Highlighter::Constant: return C_KEYWORD; - case Highlighter::TextFormatIdCount: - QTC_CHECK(false); // should never get here - return C_TEXT; - } - QTC_CHECK(false); // should never get here - return C_TEXT; -} - -Highlighter::Highlighter(QTextDocument *parent) : - SyntaxHighlighter(parent) -{ - setTextFormatCategories(TextFormatIdCount, styleForFormat); -} - -Highlighter::~Highlighter() = default; - -// Mapping from Kate format strings to format ids. -struct KateFormatMap -{ - KateFormatMap(); - QHash<QString, Highlighter::TextFormatId> m_ids; -}; - -KateFormatMap::KateFormatMap() -{ - m_ids.insert(QLatin1String("dsNormal"), Highlighter::Normal); - m_ids.insert(QLatin1String("dsKeyword"), Highlighter::Keyword); - m_ids.insert(QLatin1String("dsDataType"), Highlighter::DataType); - m_ids.insert(QLatin1String("dsComment"), Highlighter::Comment); - m_ids.insert(QLatin1String("dsDecVal"), Highlighter::Decimal); - m_ids.insert(QLatin1String("dsBaseN"), Highlighter::BaseN); - m_ids.insert(QLatin1String("dsFloat"), Highlighter::Float); - m_ids.insert(QLatin1String("dsChar"), Highlighter::Char); - m_ids.insert(QLatin1String("dsSpecialChar"), Highlighter::SpecialChar); - m_ids.insert(QLatin1String("dsString"), Highlighter::String); - m_ids.insert(QLatin1String("dsAlert"), Highlighter::Alert); - m_ids.insert(QLatin1String("dsInformation"), Highlighter::Information); - m_ids.insert(QLatin1String("dsWarning"), Highlighter::Warning); - m_ids.insert(QLatin1String("dsError"), Highlighter::Error); - m_ids.insert(QLatin1String("dsFunction"), Highlighter::Function); - m_ids.insert(QLatin1String("dsRegionMarker"), Highlighter::RegionMarker); - m_ids.insert(QLatin1String("dsBuiltIn"), Highlighter::BuiltIn); - m_ids.insert(QLatin1String("dsExtension"), Highlighter::Extension); - m_ids.insert(QLatin1String("dsOperator"), Highlighter::Operator); - m_ids.insert(QLatin1String("dsVariable"), Highlighter::Variable); - m_ids.insert(QLatin1String("dsAttribute"), Highlighter::Attribute); - m_ids.insert(QLatin1String("dsAnnotation"), Highlighter::Annotation); - m_ids.insert(QLatin1String("dsCommentVar"), Highlighter::CommentVar); - m_ids.insert(QLatin1String("dsImport"), Highlighter::Import); - m_ids.insert(QLatin1String("dsOthers"), Highlighter::Others); - m_ids.insert(QLatin1String("dsIdentifier"), Highlighter::Identifier); - m_ids.insert(QLatin1String("dsDocumentation"), Highlighter::Documentation); - m_ids.insert(QLatin1String("dsControlFlow"), Highlighter::ControlFlow); - m_ids.insert(QLatin1String("dsPreprocessor"), Highlighter::Preprocessor); - m_ids.insert(QLatin1String("dsVerbatimString"), Highlighter::VerbatimString); - m_ids.insert(QLatin1String("dsSpecialString"), Highlighter::SpecialString); - m_ids.insert(QLatin1String("dsConstant"), Highlighter::Constant); -} - -Q_GLOBAL_STATIC(KateFormatMap, kateFormatMap) - -void Highlighter::setDefaultContext(const QSharedPointer<Context> &defaultContext) -{ - m_defaultContext = defaultContext; - m_persistentObservableStates.insert(m_defaultContext->name(), Default); - m_indentationBasedFolding = defaultContext->definition()->isIndentationBasedFolding(); -} - -void Highlighter::setTabSettings(const TabSettings &ts) -{ - m_tabSettings = &ts; -} - -static bool isOpeningParenthesis(QChar c) -{ - return c == QLatin1Char('{') || c == QLatin1Char('[') || c == QLatin1Char('('); -} - -static bool isClosingParenthesis(QChar c) -{ - return c == QLatin1Char('}') || c == QLatin1Char(']') || c == QLatin1Char(')'); -} - -void Highlighter::highlightBlock(const QString &text) -{ - if (!m_defaultContext.isNull() && !m_isBroken) { - try { - setupDataForBlock(text); - - handleContextChange(m_currentContext->lineBeginContext(), - m_currentContext->definition()); - - auto progress = new ProgressData; - const int length = text.length(); - while (progress->offset() < length) - iterateThroughRules(text, length, progress, false, m_currentContext->rules()); - - if (extractObservableState(currentBlockState()) != WillContinue) { - handleContextChange(m_currentContext->lineEndContext(), - m_currentContext->definition(), - false); - } - if (length == 0) { - handleContextChange(m_currentContext->lineEmptyContext(), - m_currentContext->definition(), - false); - } - delete progress; - m_contexts.clear(); - - if (m_indentationBasedFolding) { - applyIndentationBasedFolding(text); - } else { - applyRegionBasedFolding(); - - // In the case region depth has changed since the last time the state was set. - setCurrentBlockState(computeState(extractObservableState(currentBlockState()))); - } - - Parentheses parentheses; - for (int pos = 0; pos < length; ++pos) { - const QChar c = text.at(pos); - if (isOpeningParenthesis(c)) - parentheses.push_back(Parenthesis(Parenthesis::Opened, c, pos)); - else if (isClosingParenthesis(c)) - parentheses.push_back(Parenthesis(Parenthesis::Closed, c, pos)); - } - TextDocumentLayout::setParentheses(currentBlock(), parentheses); - - } catch (const HighlighterException &e) { - Core::MessageManager::write( - QCoreApplication::translate("GenericHighlighter", - "Generic highlighter error: %1") - .arg(e.message()), - Core::MessageManager::WithFocus); - m_isBroken = true; - } - } - - formatSpaces(text); -} - -void Highlighter::setupDataForBlock(const QString &text) -{ - if (extractObservableState(currentBlockState()) == WillContinue) - analyseConsistencyOfWillContinueBlock(text); - - if (previousBlockState() == -1) { - m_regionDepth = 0; - setupDefault(); - } else { - m_regionDepth = extractRegionDepth(previousBlockState()); - const int observablePreviousState = extractObservableState(previousBlockState()); - if (observablePreviousState == Default) - setupDefault(); - else if (observablePreviousState == WillContinue) - setupFromWillContinue(); - else if (observablePreviousState == Continued) - setupFromContinued(); - else - setupFromPersistent(); - - formatterData(currentBlock())->m_foldingRegions = - formatterData(currentBlock().previous())->m_foldingRegions; - } - - assignCurrentContext(); -} - -void Highlighter::setupDefault() -{ - m_contexts.push_back(m_defaultContext); - - setCurrentBlockState(computeState(Default)); -} - -void Highlighter::setupFromWillContinue() -{ - HighlighterCodeFormatterData *previousData = formatterData(currentBlock().previous()); - pushContextSequence(previousData->m_continueObservableState); - - HighlighterCodeFormatterData *data = formatterData(currentBlock()); - data->m_originalObservableState = previousData->m_originalObservableState; - - if (currentBlockState() == -1 || extractObservableState(currentBlockState()) == Default) - setCurrentBlockState(computeState(Continued)); -} - -void Highlighter::setupFromContinued() -{ - HighlighterCodeFormatterData *previousData = formatterData(currentBlock().previous()); - - Q_ASSERT(previousData->m_originalObservableState != WillContinue && - previousData->m_originalObservableState != Continued); - - if (previousData->m_originalObservableState == Default || - previousData->m_originalObservableState == -1) { - m_contexts.push_back(m_defaultContext); - } else { - pushContextSequence(previousData->m_originalObservableState); - } - - setCurrentBlockState(computeState(previousData->m_originalObservableState)); -} - -void Highlighter::setupFromPersistent() -{ - pushContextSequence(extractObservableState(previousBlockState())); - - setCurrentBlockState(previousBlockState()); -} - -void Highlighter::iterateThroughRules(const QString &text, - const int length, - ProgressData *progress, - const bool childRule, - const QList<QSharedPointer<Rule> > &rules) -{ - if (!childRule) { - if (progress->detectRecursion(m_currentContext->id())) { - progress->setOffset(length); - return; - } - } - - using RuleIterator = QList<QSharedPointer<Rule> >::const_iterator; - - bool contextChanged = false; - bool atLeastOneMatch = false; - - RuleIterator it = rules.begin(); - RuleIterator endIt = rules.end(); - while (it != endIt && progress->offset() < length) { - int startOffset = progress->offset(); - const QSharedPointer<Rule> &rule = *it; - if (rule->matchSucceed(text, length, progress)) { - atLeastOneMatch = true; - - if (!m_indentationBasedFolding) { - if (!rule->beginRegion().isEmpty()) { - formatterData(currentBlock())->m_foldingRegions.push(rule->beginRegion()); - ++m_regionDepth; - if (progress->isOpeningBraceMatchAtFirstNonSpace()) - ++formatterData(currentBlock())->m_foldingIndentDelta; - } - if (!rule->endRegion().isEmpty()) { - QStack<QString> *currentRegions = - &formatterData(currentBlock())->m_foldingRegions; - if (!currentRegions->isEmpty() && rule->endRegion() == currentRegions->top()) { - currentRegions->pop(); - --m_regionDepth; - if (progress->isClosingBraceMatchAtNonEnd()) - --formatterData(currentBlock())->m_foldingIndentDelta; - } - } - progress->clearBracesMatches(); - } - - const QString itemData = rule->itemData(); - const QSharedPointer<HighlightDefinition> definition = rule->definition(); - const bool lookAhead = rule->isLookAhead(); - if (progress->isWillContinueLine()) { - createWillContinueBlock(); - progress->setWillContinueLine(false); - } else { - if (rule->hasChildren()) - iterateThroughRules(text, length, progress, true, rule->children()); - if (!rule->context().isEmpty() && contextChangeRequired(rule->context())) { - m_currentCaptures = progress->captures(); - changeContext(rule->context(), definition); - contextChanged = true; - } - } - - // Do NOT access rule frome here on, because a context change might delete rule - - // Format is not applied to child rules directly (but relative to the offset of their - // parent) nor to look ahead rules. - if (!childRule && !lookAhead) { - if (itemData.isEmpty()) - applyFormat(startOffset, progress->offset() - startOffset, - m_currentContext->itemData(), m_currentContext->definition()); - else - applyFormat(startOffset, progress->offset() - startOffset, itemData, - definition); - } - - // When there is a match of one child rule the others should be skipped. Otherwise - // the highlighting would be incorret in a case like 9ULLLULLLUULLULLUL, for example. - if (contextChanged || childRule) { - break; - } else { - it = rules.begin(); - continue; - } - } - ++it; - } - - if (!childRule && !atLeastOneMatch) { - if (m_currentContext->isFallthrough()) { - handleContextChange(m_currentContext->fallthroughContext(), - m_currentContext->definition()); - iterateThroughRules(text, length, progress, false, m_currentContext->rules()); - } else { - applyFormat(progress->offset(), 1, m_currentContext->itemData(), - m_currentContext->definition()); - if (progress->isOnlySpacesSoFar() && !text.at(progress->offset()).isSpace()) - progress->setOnlySpacesSoFar(false); - progress->incrementOffset(); - } - } -} - -bool Highlighter::contextChangeRequired(const QString &contextName) const -{ - if (contextName == kStay) - return false; - return true; -} - -void Highlighter::changeContext(const QString &contextName, - const QSharedPointer<HighlightDefinition> &definition, - const bool assignCurrent) -{ - QString identifier = contextName; - if (identifier.startsWith(kPop)) { - const QStringList complexOrder = contextName.split(kExclamationMark); - const QString orders = complexOrder.first(); - identifier = complexOrder.size() > 1 ? complexOrder[1] : QString(); - - const int count = orders.splitRef(kHash, QString::SkipEmptyParts).size(); - for (int i = 0; i < count; ++i) { - if (m_contexts.isEmpty()) { - throw HighlighterException( - QCoreApplication::translate("GenericHighlighter", "Reached empty context.")); - } - m_contexts.pop_back(); - } - - if (extractObservableState(currentBlockState()) >= PersistentsStart) { - // One or more contexts were popped during during a persistent state. - const QString ¤tSequence = currentContextSequence(); - if (m_persistentObservableStates.contains(currentSequence)) - setCurrentBlockState( - computeState(m_persistentObservableStates.value(currentSequence))); - else - setCurrentBlockState( - computeState(m_leadingObservableStates.value(currentSequence))); - } - } - if (!identifier.isEmpty()) { - const QSharedPointer<Context> &context = definition->context(identifier); - - if (context->isDynamic()) - pushDynamicContext(context); - else - m_contexts.push_back(context); - - if (m_contexts.back()->lineEndContext() == kStay || - extractObservableState(currentBlockState()) >= PersistentsStart) { - const QString ¤tSequence = currentContextSequence(); - mapLeadingSequence(currentSequence); - if (m_contexts.back()->lineEndContext() == kStay) { - // A persistent context was pushed. - mapPersistentSequence(currentSequence); - setCurrentBlockState( - computeState(m_persistentObservableStates.value(currentSequence))); - } - } - } - - if (assignCurrent) - assignCurrentContext(); -} - -void Highlighter::handleContextChange(const QString &contextName, - const QSharedPointer<HighlightDefinition> &definition, - const bool setCurrent) -{ - if (!contextName.isEmpty() && contextChangeRequired(contextName)) - changeContext(contextName, definition, setCurrent); -} - - -static double luminance(const QColor &color) -{ - // calculate the luminance based on - // https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef - auto val = [](const double &colorVal) { - return colorVal < 0.03928 ? colorVal / 12.92 : std::pow((colorVal + 0.055) / 1.055, 2.4); - }; - - static QHash<QRgb, double> cache; - QHash<QRgb, double>::iterator it = cache.find(color.rgb()); - if (it == cache.end()) { - it = cache.insert(color.rgb(), 0.2126 * val(color.redF()) - + 0.7152 * val(color.greenF()) - + 0.0722 * val(color.blueF())); - } - return it.value(); -} - -static float contrastRatio(const QColor &color1, const QColor &color2) -{ - // calculate the contrast ratio based on - // https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef - auto contrast = (luminance(color1) + 0.05) / (luminance(color2) + 0.05); - if (contrast < 1) - return 1 / contrast; - return contrast; -} - - -static bool isReadableOn(const QColor &background, const QColor &foreground) -{ - // following the W3C Recommendation on contrast for large Text - // https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef - return contrastRatio(background, foreground) > 3; -} - -void Highlighter::applyFormat(int offset, - int count, - const QString &itemDataName, - const QSharedPointer<HighlightDefinition> &definition) -{ - if (count == 0) - return; - - QSharedPointer<ItemData> itemData; - try { - itemData = definition->itemData(itemDataName); - } catch (const HighlighterException &) { - // There are some broken files. For instance, the Printf context in java.xml points to an - // inexistent Printf item data. These cases are considered to have normal text style. - return; - } - - TextFormatId formatId = kateFormatMap()->m_ids.value(itemData->style(), Normal); - if (formatId != Normal) { - QTextCharFormat format = formatForCategory(formatId); - if (itemData->isCustomized()) { - // Please notice that the following are applied every time for item data which have - // customizations. The configureFormats function could be used to provide a "one time" - // configuration, but it would probably require to traverse all item data from all - // definitions available/loaded (either to set the values or for some "notifying" - // strategy). This is because the highlighter does not really know on which - // definition(s) it is working. Since not many item data specify customizations I - // think this approach would fit better. If there are other ideas... - QBrush bg = format.background(); - if (bg.style() == Qt::NoBrush) - bg = fontSettings().toTextCharFormat(C_TEXT).background(); - if (itemData->color().isValid() && isReadableOn(bg.color(), itemData->color())) - format.setForeground(itemData->color()); - if (itemData->isItalicSpecified()) - format.setFontItalic(itemData->isItalic()); - if (itemData->isBoldSpecified()) - format.setFontWeight(toFontWeight(itemData->isBold())); - if (itemData->isUnderlinedSpecified()) - format.setFontUnderline(itemData->isUnderlined()); - if (itemData->isStrikeOutSpecified()) - format.setFontStrikeOut(itemData->isStrikeOut()); - } - - setFormat(offset, count, format); - } -} - -void Highlighter::createWillContinueBlock() -{ - HighlighterCodeFormatterData *data = formatterData(currentBlock()); - const int currentObservableState = extractObservableState(currentBlockState()); - if (currentObservableState == Continued) { - HighlighterCodeFormatterData *previousData = formatterData(currentBlock().previous()); - data->m_originalObservableState = previousData->m_originalObservableState; - } else if (currentObservableState != WillContinue) { - data->m_originalObservableState = currentObservableState; - } - const QString currentSequence = currentContextSequence(); - mapPersistentSequence(currentSequence); - data->m_continueObservableState = m_persistentObservableStates.value(currentSequence); - m_persistentContexts.insert(data->m_continueObservableState, m_contexts); - - setCurrentBlockState(computeState(WillContinue)); -} - -void Highlighter::analyseConsistencyOfWillContinueBlock(const QString &text) -{ - if (currentBlock().next().isValid() && ( - text.length() == 0 || text.at(text.length() - 1) != kBackSlash) && - extractObservableState(currentBlock().next().userState()) != Continued) { - currentBlock().next().setUserState(computeState(Continued)); - } - - if (text.length() == 0 || text.at(text.length() - 1) != kBackSlash) { - HighlighterCodeFormatterData *data = formatterData(currentBlock()); - setCurrentBlockState(computeState(data->m_originalObservableState)); - } -} - -void Highlighter::mapPersistentSequence(const QString &contextSequence) -{ - if (!m_persistentObservableStates.contains(contextSequence)) { - int newState = m_persistentObservableStatesCounter; - m_persistentObservableStates.insert(contextSequence, newState); - m_persistentContexts.insert(newState, m_contexts); - ++m_persistentObservableStatesCounter; - } -} - -void Highlighter::mapLeadingSequence(const QString &contextSequence) -{ - if (!m_leadingObservableStates.contains(contextSequence)) - m_leadingObservableStates.insert(contextSequence, - extractObservableState(currentBlockState())); -} - -void Highlighter::pushContextSequence(int state) -{ - const QVector<QSharedPointer<Context> > &contexts = m_persistentContexts.value(state); - for (const auto &context : contexts) - m_contexts.push_back(context); -} - -QString Highlighter::currentContextSequence() const -{ - QString sequence; - for (int i = 0; i < m_contexts.size(); ++i) - sequence.append(m_contexts.at(i)->id()); - - return sequence; -} - -void Highlighter::pushDynamicContext(const QSharedPointer<Context> &baseContext) -{ - // A dynamic context is created from another context which serves as its basis. Then, - // its rules are updated according to the captures from the calling regular expression which - // triggered the push of the dynamic context. - QSharedPointer<Context> context(new Context(*baseContext)); - context->configureId(m_dynamicContextsCounter); - context->updateDynamicRules(m_currentCaptures); - m_contexts.push_back(context); - ++m_dynamicContextsCounter; -} - -void Highlighter::assignCurrentContext() -{ - if (m_contexts.isEmpty()) { - // This is not supposed to happen. However, there are broken files (for example, php.xml) - // which will cause this behaviour. In such cases pushing the default context is enough to - // keep highlighter working. - m_contexts.push_back(m_defaultContext); - } - m_currentContext = m_contexts.back(); -} - -int Highlighter::extractRegionDepth(const int state) -{ - return state >> 12; -} - -int Highlighter::extractObservableState(const int state) -{ - return state & 0xFFF; -} - -int Highlighter::computeState(const int observableState) const -{ - return m_regionDepth << 12 | observableState; -} - -void Highlighter::applyRegionBasedFolding() const -{ - int folding = 0; - TextBlockUserData *currentBlockUserData = TextDocumentLayout::userData(currentBlock()); - HighlighterCodeFormatterData *data = formatterData(currentBlock()); - HighlighterCodeFormatterData *previousData = formatterData(currentBlock().previous()); - if (previousData) { - folding = extractRegionDepth(previousBlockState()); - if (data->m_foldingIndentDelta != 0) { - folding += data->m_foldingIndentDelta; - if (data->m_foldingIndentDelta > 0) - currentBlockUserData->setFoldingStartIncluded(true); - else - TextDocumentLayout::userData(currentBlock().previous())->setFoldingEndIncluded(false); - data->m_foldingIndentDelta = 0; - } - } - currentBlockUserData->setFoldingEndIncluded(true); - currentBlockUserData->setFoldingIndent(folding); -} - -void Highlighter::applyIndentationBasedFolding(const QString &text) const -{ - TextBlockUserData *data = TextDocumentLayout::userData(currentBlock()); - data->setFoldingEndIncluded(true); - - // If this line is empty, check its neighbours. They all might be part of the same block. - if (text.trimmed().isEmpty()) { - data->setFoldingIndent(0); - const int previousIndent = neighbouringNonEmptyBlockIndent(currentBlock().previous(), true); - if (previousIndent > 0) { - const int nextIndent = neighbouringNonEmptyBlockIndent(currentBlock().next(), false); - if (previousIndent == nextIndent) - data->setFoldingIndent(previousIndent); - } - } else { - data->setFoldingIndent(m_tabSettings->indentationColumn(text)); - } -} - -int Highlighter::neighbouringNonEmptyBlockIndent(QTextBlock block, const bool previous) const -{ - while (true) { - if (!block.isValid()) - return 0; - if (block.text().trimmed().isEmpty()) { - if (previous) - block = block.previous(); - else - block = block.next(); - } else { - return m_tabSettings->indentationColumn(block.text()); - } - } -} diff --git a/src/plugins/texteditor/generichighlighter/highlighter.h b/src/plugins/texteditor/generichighlighter/highlighter.h deleted file mode 100644 index f814496600..0000000000 --- a/src/plugins/texteditor/generichighlighter/highlighter.h +++ /dev/null @@ -1,199 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include "context.h" - -// Yes, this is correct. These are found somewhere else when building the autotest. -#include <textdocumentlayout.h> -#include <syntaxhighlighter.h> - -#include <QString> -#include <QVector> -#include <QStack> -#include <QSharedPointer> -#include <QStringList> - -#include <QTextCharFormat> - -namespace TextEditor { - -class TabSettings; -namespace Internal { - -class Rule; -class HighlightDefinition; -class ProgressData; - -} // namespace Internal - -/* - Warning: Due to a very ugly hack with generichighlighter test - you can't export this class, so that it would be used from - other plugins. That's why highlighterutils.h was introduced. -*/ -class Highlighter : public TextEditor::SyntaxHighlighter -{ - Q_OBJECT - -public: - Highlighter(QTextDocument *parent = nullptr); - ~Highlighter() override; - - enum TextFormatId { - Normal, - Keyword, - DataType, - Comment, - Decimal, - BaseN, - Float, - Char, - SpecialChar, - String, - Alert, - Information, - Warning, - Error, - Function, - RegionMarker, - BuiltIn, - Extension, - Operator, - Variable, - Attribute, - Annotation, - CommentVar, - Import, - Others, - Identifier, - Documentation, - ControlFlow, - Preprocessor, - VerbatimString, - SpecialString, - Constant, - TextFormatIdCount - }; - - void setTabSettings(const TabSettings &ts); - void setDefaultContext(const QSharedPointer<Internal::Context> &defaultContext); - -protected: - void highlightBlock(const QString &text) override; - -private: - - void setupDataForBlock(const QString &text); - void setupDefault(); - void setupFromWillContinue(); - void setupFromContinued(); - void setupFromPersistent(); - - void iterateThroughRules(const QString &text, - const int length, - Internal::ProgressData *progress, - const bool childRule, - const QList<QSharedPointer<Internal::Rule> > &rules); - - void assignCurrentContext(); - bool contextChangeRequired(const QString &contextName) const; - void handleContextChange(const QString &contextName, - const QSharedPointer<Internal::HighlightDefinition> &definition, - const bool setCurrent = true); - void changeContext(const QString &contextName, - const QSharedPointer<Internal::HighlightDefinition> &definition, - const bool assignCurrent = true); - - QString currentContextSequence() const; - void mapPersistentSequence(const QString &contextSequence); - void mapLeadingSequence(const QString &contextSequence); - void pushContextSequence(int state); - - void pushDynamicContext(const QSharedPointer<Internal::Context> &baseContext); - - void createWillContinueBlock(); - void analyseConsistencyOfWillContinueBlock(const QString &text); - - void applyFormat(int offset, - int count, - const QString &itemDataName, - const QSharedPointer<Internal::HighlightDefinition> &definition); - - void applyRegionBasedFolding() const; - void applyIndentationBasedFolding(const QString &text) const; - int neighbouringNonEmptyBlockIndent(QTextBlock block, const bool previous) const; - - static TextBlockUserData *blockData(QTextBlockUserData *userData); - - // Block states are composed by the region depth (used for code folding) and what I call - // observable states. Observable states occupy the 12 least significant bits. They might have - // the following values: - // - Default [0]: Nothing special. - // - WillContinue [1]: When there is match of the LineContinue rule (backslash as the last - // character). - // - Continued [2]: Blocks that happen after a WillContinue block and continue from their - // context until the next line end. - // - Persistent(s) [Anything >= 3]: Correspond to persistent contexts which last until a pop - // occurs due to a matching rule. Every sequence of persistent contexts seen so far is - // associated with a number (incremented by a unit each time). - // Region depths occupy the remaining bits. - enum ObservableBlockState { - Default = 0, - WillContinue, - Continued, - PersistentsStart - }; - int computeState(const int observableState) const; - - static int extractRegionDepth(const int state); - static int extractObservableState(const int state); - - int m_regionDepth = 0; - bool m_indentationBasedFolding = false; - const TabSettings *m_tabSettings = nullptr; - - int m_persistentObservableStatesCounter = PersistentsStart; - int m_dynamicContextsCounter = 0; - - bool m_isBroken = false; - - QSharedPointer<Internal::Context> m_defaultContext; - QSharedPointer<Internal::Context> m_currentContext; - QVector<QSharedPointer<Internal::Context> > m_contexts; - - // Mapping from context sequences to the observable persistent state they represent. - QHash<QString, int> m_persistentObservableStates; - // Mapping from context sequences to the non-persistent observable state that led to them. - QHash<QString, int> m_leadingObservableStates; - // Mapping from observable persistent states to context sequences (the actual "stack"). - QHash<int, QVector<QSharedPointer<Internal::Context> > > m_persistentContexts; - - // Captures used in dynamic rules. - QStringList m_currentCaptures; -}; - -} // namespace TextEditor diff --git a/src/plugins/texteditor/generichighlighter/highlighterexception.h b/src/plugins/texteditor/generichighlighter/highlighterexception.h deleted file mode 100644 index 0850656966..0000000000 --- a/src/plugins/texteditor/generichighlighter/highlighterexception.h +++ /dev/null @@ -1,42 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include <QString> - -namespace TextEditor { -namespace Internal { -class HighlighterException -{ -public: - HighlighterException(const QString &msg) : m_message(msg) {} - QString message() const { return m_message; } - -private: - QString m_message; -}; -} -} // namespace TextEditor diff --git a/src/plugins/texteditor/generichighlighter/highlightersettingspage.cpp b/src/plugins/texteditor/generichighlighter/highlightersettingspage.cpp deleted file mode 100644 index d43c528e08..0000000000 --- a/src/plugins/texteditor/generichighlighter/highlightersettingspage.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "highlightersettingspage.h" -#include "highlightersettings.h" -#include "manager.h" -#include "managedefinitionsdialog.h" -#include "ui_highlightersettingspage.h" - -#include <coreplugin/icore.h> - -#include <QMessageBox> -#include <QPointer> - -using namespace TextEditor; -using namespace Internal; - -struct HighlighterSettingsPage::HighlighterSettingsPagePrivate -{ - explicit HighlighterSettingsPagePrivate(Core::Id id); - void ensureInitialized(); - - bool m_initialized; - const Core::Id m_id; - const QString m_displayName; - const QString m_settingsPrefix; - - HighlighterSettings m_settings; - - QPointer<QWidget> m_widget; - Ui::HighlighterSettingsPage *m_page; -}; - -HighlighterSettingsPage::HighlighterSettingsPagePrivate:: -HighlighterSettingsPagePrivate(Core::Id id) : - m_initialized(false), - m_id(id), - m_displayName(tr("Generic Highlighter")), - m_settingsPrefix(QLatin1String("Text")), - m_page(nullptr) -{} - -void HighlighterSettingsPage::HighlighterSettingsPagePrivate::ensureInitialized() -{ - if (m_initialized) - return; - m_initialized = true; - m_settings.fromSettings(m_settingsPrefix, Core::ICore::settings()); -} - -HighlighterSettingsPage::HighlighterSettingsPage(Core::Id id, QObject *parent) : - TextEditorOptionsPage(parent), - m_requestHighlightFileRegistration(false), - m_d(new HighlighterSettingsPagePrivate(id)) -{ - setId(m_d->m_id); - setDisplayName(m_d->m_displayName); -} - -HighlighterSettingsPage::~HighlighterSettingsPage() -{ - delete m_d; -} - -QWidget *HighlighterSettingsPage::widget() -{ - if (!m_d->m_widget) { - m_d->m_widget = new QWidget; - m_d->m_page = new Ui::HighlighterSettingsPage; - m_d->m_page->setupUi(m_d->m_widget); - m_d->m_page->definitionFilesPath->setExpectedKind(Utils::PathChooser::ExistingDirectory); - m_d->m_page->definitionFilesPath->setHistoryCompleter(QLatin1String("TextEditor.Highlighter.History")); - m_d->m_page->definitionFilesPath->addButton(tr("Download Definitions..."), this, - [this] { requestAvailableDefinitionsMetaData(); }); - m_d->m_page->fallbackDefinitionFilesPath->setExpectedKind(Utils::PathChooser::ExistingDirectory); - m_d->m_page->fallbackDefinitionFilesPath->setHistoryCompleter(QLatin1String("TextEditor.Highlighter.History")); - m_d->m_page->fallbackDefinitionFilesPath->addButton(tr("Autodetect"), this, - [this] { resetDefinitionsLocation(); }); - - settingsToUI(); - - connect(m_d->m_page->useFallbackLocation, &QAbstractButton::clicked, - this, &HighlighterSettingsPage::setFallbackLocationState); - connect(m_d->m_page->definitionFilesPath, &Utils::PathChooser::validChanged, - this, &HighlighterSettingsPage::setDownloadDefinitionsState); - connect(m_d->m_widget.data(), &QObject::destroyed, - this, &HighlighterSettingsPage::ignoreDownloadReply); - } - return m_d->m_widget; -} - -void HighlighterSettingsPage::apply() -{ - if (!m_d->m_page) // page was not shown - return; - if (settingsChanged()) - settingsFromUI(); - - if (m_requestHighlightFileRegistration) { - Manager::instance()->registerHighlightingFiles(); - m_requestHighlightFileRegistration = false; - } -} - -void HighlighterSettingsPage::finish() -{ - delete m_d->m_widget; - if (!m_d->m_page) // page was not shown - return; - delete m_d->m_page; - m_d->m_page = nullptr; -} - -const HighlighterSettings &HighlighterSettingsPage::highlighterSettings() const -{ - m_d->ensureInitialized(); - return m_d->m_settings; -} - -void HighlighterSettingsPage::settingsFromUI() -{ - m_d->ensureInitialized(); - if (!m_requestHighlightFileRegistration && ( - m_d->m_settings.definitionFilesPath() != m_d->m_page->definitionFilesPath->path() || - m_d->m_settings.fallbackDefinitionFilesPath() != - m_d->m_page->fallbackDefinitionFilesPath->path() || - m_d->m_settings.useFallbackLocation() != m_d->m_page->useFallbackLocation->isChecked())) { - m_requestHighlightFileRegistration = true; - } - - m_d->m_settings.setDefinitionFilesPath(m_d->m_page->definitionFilesPath->path()); - m_d->m_settings.setFallbackDefinitionFilesPath(m_d->m_page->fallbackDefinitionFilesPath->path()); - m_d->m_settings.setUseFallbackLocation(m_d->m_page->useFallbackLocation->isChecked()); - m_d->m_settings.setIgnoredFilesPatterns(m_d->m_page->ignoreEdit->text()); - m_d->m_settings.toSettings(m_d->m_settingsPrefix, Core::ICore::settings()); -} - -void HighlighterSettingsPage::settingsToUI() -{ - m_d->ensureInitialized(); - m_d->m_page->definitionFilesPath->setPath(m_d->m_settings.definitionFilesPath()); - m_d->m_page->fallbackDefinitionFilesPath->setPath(m_d->m_settings.fallbackDefinitionFilesPath()); - m_d->m_page->useFallbackLocation->setChecked(m_d->m_settings.useFallbackLocation()); - m_d->m_page->ignoreEdit->setText(m_d->m_settings.ignoredFilesPatterns()); - - setFallbackLocationState(m_d->m_page->useFallbackLocation->isChecked()); - setDownloadDefinitionsState(m_d->m_page->definitionFilesPath->isValid()); -} - -void HighlighterSettingsPage::resetDefinitionsLocation() -{ - const QString &location = findFallbackDefinitionsLocation(); - if (location.isEmpty()) { - QMessageBox::information(Core::ICore::dialogParent(), tr("Autodetect Definitions"), - tr("No pre-installed definitions could be found.")); - } else { - m_d->m_page->fallbackDefinitionFilesPath->setPath(location); - } -} - -void HighlighterSettingsPage::requestAvailableDefinitionsMetaData() -{ - setDownloadDefinitionsState(false); - - connect(Manager::instance(), &Manager::definitionsMetaDataReady, - this, &HighlighterSettingsPage::manageDefinitions, Qt::UniqueConnection); - connect(Manager::instance(), &Manager::errorDownloadingDefinitionsMetaData, - this, &HighlighterSettingsPage::showError, Qt::UniqueConnection); - Manager::instance()->downloadAvailableDefinitionsMetaData(); -} - -void HighlighterSettingsPage::ignoreDownloadReply() -{ - disconnect(Manager::instance(), &Manager::definitionsMetaDataReady, - this, &HighlighterSettingsPage::manageDefinitions); - disconnect(Manager::instance(), &Manager::errorDownloadingDefinitionsMetaData, - this, &HighlighterSettingsPage::showError); -} - -void HighlighterSettingsPage::manageDefinitions(const QList<DefinitionMetaDataPtr> &metaData) -{ - ManageDefinitionsDialog dialog(metaData, - m_d->m_page->definitionFilesPath->path() + QLatin1Char('/'), - m_d->m_page->definitionFilesPath->buttonAtIndex(1)->window()); - if (dialog.exec() && !m_requestHighlightFileRegistration) - m_requestHighlightFileRegistration = true; - setDownloadDefinitionsState(m_d->m_page->definitionFilesPath->isValid()); -} - -void HighlighterSettingsPage::showError() -{ - QMessageBox::critical(m_d->m_page->definitionFilesPath->buttonAtIndex(1)->window(), - tr("Error connecting to server."), - tr("Not possible to retrieve data.")); - setDownloadDefinitionsState(m_d->m_page->definitionFilesPath->isValid()); -} - -void HighlighterSettingsPage::setFallbackLocationState(bool checked) -{ - m_d->m_page->fallbackDefinitionFilesPath->setEnabled(checked); -} - -void HighlighterSettingsPage::setDownloadDefinitionsState(bool valid) -{ - m_d->m_page->definitionFilesPath->buttonAtIndex(1)->setEnabled(valid); -} - -bool HighlighterSettingsPage::settingsChanged() const -{ - m_d->ensureInitialized(); - if (m_d->m_settings.definitionFilesPath() != m_d->m_page->definitionFilesPath->path()) - return true; - if (m_d->m_settings.fallbackDefinitionFilesPath() != - m_d->m_page->fallbackDefinitionFilesPath->path()) - return true; - if (m_d->m_settings.useFallbackLocation() != m_d->m_page->useFallbackLocation->isChecked()) - return true; - if (m_d->m_settings.ignoredFilesPatterns() != m_d->m_page->ignoreEdit->text()) - return true; - return false; -} diff --git a/src/plugins/texteditor/generichighlighter/includerulesinstruction.cpp b/src/plugins/texteditor/generichighlighter/includerulesinstruction.cpp deleted file mode 100644 index b9e30319ab..0000000000 --- a/src/plugins/texteditor/generichighlighter/includerulesinstruction.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "includerulesinstruction.h" -#include "reuse.h" - -using namespace TextEditor; -using namespace Internal; - -IncludeRulesInstruction::IncludeRulesInstruction(const QString &context, - int hint, - const QString &replaceItemData) : - m_sourceContext(context), m_indexHint(hint), m_replaceItemData(toBool(replaceItemData)) -{ -} - -const QString &IncludeRulesInstruction::sourceContext() const -{ return m_sourceContext; } - -int IncludeRulesInstruction::indexHint() const -{ return m_indexHint; } - -bool IncludeRulesInstruction::replaceItemData() const -{ return m_replaceItemData; } diff --git a/src/plugins/texteditor/generichighlighter/includerulesinstruction.h b/src/plugins/texteditor/generichighlighter/includerulesinstruction.h deleted file mode 100644 index aefdc42bb7..0000000000 --- a/src/plugins/texteditor/generichighlighter/includerulesinstruction.h +++ /dev/null @@ -1,49 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include <QString> - -namespace TextEditor { -namespace Internal { - -class IncludeRulesInstruction -{ -public: - IncludeRulesInstruction(const QString &context, int hint, const QString &replaceItemData); - - const QString &sourceContext() const; - int indexHint() const; - bool replaceItemData() const; - -private: - QString m_sourceContext; - int m_indexHint; - bool m_replaceItemData; -}; - -} // namespace Internal -} // namespace TextEditor diff --git a/src/plugins/texteditor/generichighlighter/itemdata.cpp b/src/plugins/texteditor/generichighlighter/itemdata.cpp deleted file mode 100644 index e7ae9b9533..0000000000 --- a/src/plugins/texteditor/generichighlighter/itemdata.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "itemdata.h" -#include "reuse.h" - -using namespace TextEditor; -using namespace Internal; - -ItemData::ItemData() : - m_italic(false), - m_italicSpecified(false), - m_bold(false), - m_boldSpecified(false), - m_underlined(false), - m_underlinedSpecified(false), - m_strikedOut(false), - m_strikeOutSpecified(false), - m_isCustomized(false) -{} - -void ItemData::setStyle(const QString &style) -{ m_style = style; } - -const QString &ItemData::style() const -{ return m_style; } - -void ItemData::setColor(const QString &color) -{ - if (!color.isEmpty()) { - m_color.setNamedColor(color); - m_isCustomized = true; - } -} - -const QColor &ItemData::color() const -{ return m_color; } - -void ItemData::setSelectionColor(const QString &color) -{ - if (!color.isEmpty()) { - m_selectionColor.setNamedColor(color); - m_isCustomized = true; - } -} - -const QColor &ItemData::selectionColor() const -{ return m_selectionColor; } - -void ItemData::setItalic(const QString &italic) -{ - if (!italic.isEmpty()) { - m_italic = toBool(italic); - m_italicSpecified = true; - m_isCustomized = true; - } -} - -bool ItemData::isItalic() const -{ return m_italic; } - -bool ItemData::isItalicSpecified() const -{ return m_italicSpecified; } - -void ItemData::setBold(const QString &bold) -{ - if (!bold.isEmpty()) { - m_bold = toBool(bold); - m_boldSpecified = true; - m_isCustomized = true; - } -} - -bool ItemData::isBold() const -{ return m_bold; } - -bool ItemData::isBoldSpecified() const -{ return m_boldSpecified; } - -void ItemData::setUnderlined(const QString &underlined) -{ - if (!underlined.isEmpty()) { - m_underlined = toBool(underlined); - m_underlinedSpecified = true; - m_isCustomized = true; - } -} - -bool ItemData::isUnderlined() const -{ return m_underlined; } - -bool ItemData::isUnderlinedSpecified() const -{ return m_underlinedSpecified; } - -void ItemData::setStrikeOut(const QString &strike) -{ - if (!strike.isEmpty()) { - m_strikedOut = toBool(strike); - m_strikeOutSpecified = true; - m_isCustomized = true; - } -} - -bool ItemData::isStrikeOut() const -{ return m_strikedOut; } - -bool ItemData::isStrikeOutSpecified() const -{ return m_strikeOutSpecified; } - -bool ItemData::isCustomized() const -{ return m_isCustomized; } diff --git a/src/plugins/texteditor/generichighlighter/itemdata.h b/src/plugins/texteditor/generichighlighter/itemdata.h deleted file mode 100644 index 538d61ebde..0000000000 --- a/src/plugins/texteditor/generichighlighter/itemdata.h +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include <QString> -#include <QColor> - -namespace TextEditor { -namespace Internal { - -class ItemData -{ -public: - ItemData(); - - void setStyle(const QString &style); - const QString &style() const; - - void setColor(const QString &color); - const QColor &color() const; - - void setSelectionColor(const QString &color); - const QColor &selectionColor() const; - - void setItalic(const QString &italic); - bool isItalic() const; - bool isItalicSpecified() const; - - void setBold(const QString &bold); - bool isBold() const; - bool isBoldSpecified() const; - - void setUnderlined(const QString &underlined); - bool isUnderlined() const; - bool isUnderlinedSpecified() const; - - void setStrikeOut(const QString &strike); - bool isStrikeOut() const; - bool isStrikeOutSpecified() const; - - bool isCustomized() const; - -private: - bool m_italic; - bool m_italicSpecified; - bool m_bold; - bool m_boldSpecified; - bool m_underlined; - bool m_underlinedSpecified; - bool m_strikedOut; - bool m_strikeOutSpecified; - bool m_isCustomized; - QString m_style; - QColor m_color; - QColor m_selectionColor; -}; - -} // namespace Internal -} // namespace TextEditor diff --git a/src/plugins/texteditor/generichighlighter/keywordlist.cpp b/src/plugins/texteditor/generichighlighter/keywordlist.cpp deleted file mode 100644 index 86e7403f85..0000000000 --- a/src/plugins/texteditor/generichighlighter/keywordlist.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "keywordlist.h" - -using namespace TextEditor; -using namespace Internal; - -void KeywordList::addKeyword(const QString &keyword) -{ - if (keyword.isEmpty()) - return; - - m_keywords.insert(keyword); -} - -bool KeywordList::isKeyword(const QString &keyword, Qt::CaseSensitivity sensitivity) const -{ - if (keyword.isEmpty()) - return false; - - // Case sensitivity could be implemented, for example, by converting all keywords to lower - // if the global sensitivity attribute is insensitive, then always checking for containment - // (with a conversion to lower in the necessary cases). But the code below is one alternative - // to support the existence of local sensitivity attributes (which override the global one - - // currently not documented). - if (sensitivity == Qt::CaseSensitive) { - return m_keywords.contains(keyword); - } else { - foreach (const QString &s, m_keywords) - if (keyword.compare(s, Qt::CaseInsensitive) == 0) - return true; - return false; - } -} diff --git a/src/plugins/texteditor/generichighlighter/keywordlist.h b/src/plugins/texteditor/generichighlighter/keywordlist.h deleted file mode 100644 index f111afa4e0..0000000000 --- a/src/plugins/texteditor/generichighlighter/keywordlist.h +++ /dev/null @@ -1,46 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include <QString> -#include <QSet> - -namespace TextEditor { -namespace Internal { - -class KeywordList -{ -public: - - void addKeyword(const QString &keyword); - bool isKeyword(const QString &keyword, Qt::CaseSensitivity sensitivity) const; - -private: - QSet<QString> m_keywords; -}; - -} // namespace Internal -} // namespace TextEditor diff --git a/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.cpp b/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.cpp deleted file mode 100644 index 1a6aa42ce0..0000000000 --- a/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "managedefinitionsdialog.h" -#include "manager.h" - -#include <QUrl> -#include <QIODevice> -#include <QFile> -#include <QFileInfo> -#include <QMessageBox> - -using namespace TextEditor; -using namespace Internal; - -ManageDefinitionsDialog::ManageDefinitionsDialog( - const QList<DefinitionMetaDataPtr> &metaDataList, - const QString &path, - QWidget *parent) : - QDialog(parent), - m_path(path) -{ - ui.setupUi(this); - ui.definitionsTable->setHorizontalHeaderLabels( - QStringList() << tr("Name") << tr("Installed") << tr("Available")); - ui.definitionsTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); - - setWindowTitle(tr("Download Definitions")); - - populateDefinitionsWidget(metaDataList); - ui.definitionsTable->sortItems(0); - - connect(ui.downloadButton, &QPushButton::clicked, this, &ManageDefinitionsDialog::downloadDefinitions); - connect(ui.allButton, &QPushButton::clicked, this, &ManageDefinitionsDialog::selectAll); - connect(ui.clearButton, &QPushButton::clicked, this, &ManageDefinitionsDialog::clearSelection); - connect(ui.invertButton, &QPushButton::clicked, this, &ManageDefinitionsDialog::invertSelection); -} - -void ManageDefinitionsDialog::populateDefinitionsWidget(const QList<DefinitionMetaDataPtr> &definitionsMetaData) -{ - const int size = definitionsMetaData.size(); - ui.definitionsTable->setRowCount(size); - for (int i = 0; i < size; ++i) { - const HighlightDefinitionMetaData &downloadData = *definitionsMetaData.at(i); - - // Look for this definition in the current path specified by the user, not the one - // stored in the settings. So the manager should not be queried for this information. - QString dirVersion; - QFileInfo fi(m_path + downloadData.fileName); - QFile definitionFile(fi.absoluteFilePath()); - if (definitionFile.open(QIODevice::ReadOnly | QIODevice::Text)) { - const DefinitionMetaDataPtr data = Manager::parseMetadata(fi); - if (!data.isNull()) - dirVersion = data->version; - } - - for (int j = 0; j < 3; ++j) { - auto item = new QTableWidgetItem; - if (j == 0) { - item->setText(downloadData.name); - item->setData(Qt::UserRole, downloadData.url); - } else if (j == 1) { - item->setText(dirVersion); - item->setTextAlignment(Qt::AlignCenter); - } else if (j == 2) { - item->setText(downloadData.version); - item->setTextAlignment(Qt::AlignCenter); - } - ui.definitionsTable->setItem(i, j, item); - } - } -} - -void ManageDefinitionsDialog::downloadDefinitions() -{ - if (Manager::instance()->isDownloadingDefinitions()) { - QMessageBox::information( - this, - tr("Download Information"), - tr("There is already one download in progress. Please wait until it is finished.")); - return; - } - - QList<QUrl> urls; - foreach (const QModelIndex &index, ui.definitionsTable->selectionModel()->selectedRows()) { - const QVariant url = ui.definitionsTable->item(index.row(), 0)->data(Qt::UserRole); - urls.append(url.toUrl()); - } - Manager::instance()->downloadDefinitions(urls, m_path); - accept(); -} - -void ManageDefinitionsDialog::selectAll() -{ - ui.definitionsTable->selectAll(); - ui.definitionsTable->setFocus(); -} - -void ManageDefinitionsDialog::clearSelection() -{ - ui.definitionsTable->clearSelection(); -} - -void ManageDefinitionsDialog::invertSelection() -{ - const QModelIndex &topLeft = ui.definitionsTable->model()->index(0, 0); - const QModelIndex &bottomRight = - ui.definitionsTable->model()->index(ui.definitionsTable->rowCount() - 1, - ui.definitionsTable->columnCount() - 1); - QItemSelection itemSelection(topLeft, bottomRight); - ui.definitionsTable->selectionModel()->select(itemSelection, QItemSelectionModel::Toggle); - ui.definitionsTable->setFocus(); -} diff --git a/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.h b/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.h deleted file mode 100644 index 3a5512dcec..0000000000 --- a/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.h +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include "ui_managedefinitionsdialog.h" -#include "highlightdefinitionmetadata.h" - -namespace TextEditor { -namespace Internal { - -class ManageDefinitionsDialog : public QDialog -{ - Q_OBJECT - -public: - explicit ManageDefinitionsDialog(const QList<DefinitionMetaDataPtr> &metaDataList, - const QString &path, - QWidget *parent = nullptr); - -private: - void downloadDefinitions(); - void selectAll(); - void clearSelection(); - void invertSelection(); - void populateDefinitionsWidget(const QList<DefinitionMetaDataPtr> &definitionsMetaData); - - QString m_path; - Ui::ManageDefinitionsDialog ui; -}; - -} // namespace Internal -} // namespace TextEditor diff --git a/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.ui b/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.ui deleted file mode 100644 index adab90f7d2..0000000000 --- a/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.ui +++ /dev/null @@ -1,158 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>TextEditor::Internal::ManageDefinitionsDialog</class> - <widget class="QDialog" name="TextEditor::Internal::ManageDefinitionsDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>586</width> - <height>280</height> - </rect> - </property> - <property name="windowTitle"> - <string>Dialog</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QGroupBox" name="definitionsGroupBox"> - <property name="title"> - <string>Definitions</string> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0" rowspan="4"> - <widget class="QTableWidget" name="definitionsTable"> - <property name="editTriggers"> - <set>QAbstractItemView::NoEditTriggers</set> - </property> - <property name="alternatingRowColors"> - <bool>false</bool> - </property> - <property name="selectionMode"> - <enum>QAbstractItemView::ExtendedSelection</enum> - </property> - <property name="selectionBehavior"> - <enum>QAbstractItemView::SelectRows</enum> - </property> - <property name="showGrid"> - <bool>false</bool> - </property> - <property name="gridStyle"> - <enum>Qt::NoPen</enum> - </property> - <property name="sortingEnabled"> - <bool>true</bool> - </property> - <property name="columnCount"> - <number>3</number> - </property> - <attribute name="horizontalHeaderHighlightSections"> - <bool>false</bool> - </attribute> - <attribute name="horizontalHeaderShowSortIndicator" stdset="0"> - <bool>true</bool> - </attribute> - <attribute name="verticalHeaderVisible"> - <bool>false</bool> - </attribute> - <attribute name="verticalHeaderDefaultSectionSize"> - <number>20</number> - </attribute> - <attribute name="verticalHeaderHighlightSections"> - <bool>false</bool> - </attribute> - <column/> - <column/> - <column/> - </widget> - </item> - <item row="0" column="1"> - <widget class="QPushButton" name="allButton"> - <property name="text"> - <string>Select All</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QPushButton" name="clearButton"> - <property name="text"> - <string>Clear Selection</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QPushButton" name="invertButton"> - <property name="text"> - <string>Invert Selection</string> - </property> - </widget> - </item> - <item row="3" column="1"> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>244</height> - </size> - </property> - </spacer> - </item> - <item row="4" column="0" colspan="2"> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QPushButton" name="downloadButton"> - <property name="text"> - <string>Download Selected Definitions</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>188</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="standardButtons"> - <set>QDialogButtonBox::Close</set> - </property> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>TextEditor::Internal::ManageDefinitionsDialog</receiver> - <slot>close()</slot> - <hints> - <hint type="sourcelabel"> - <x>385</x> - <y>420</y> - </hint> - <hint type="destinationlabel"> - <x>223</x> - <y>222</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/src/plugins/texteditor/generichighlighter/manager.cpp b/src/plugins/texteditor/generichighlighter/manager.cpp deleted file mode 100644 index 32da7ca4e5..0000000000 --- a/src/plugins/texteditor/generichighlighter/manager.cpp +++ /dev/null @@ -1,507 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "manager.h" -#include "highlightdefinition.h" -#include "highlightdefinitionhandler.h" -#include "highlighterexception.h" -#include "definitiondownloader.h" -#include "highlightersettings.h" -#include <texteditor/plaintexteditorfactory.h> -#include <texteditor/texteditorconstants.h> -#include <texteditor/texteditorsettings.h> - -#include <coreplugin/icore.h> -#include <coreplugin/messagemanager.h> -#include <coreplugin/progressmanager/progressmanager.h> -#include <utils/algorithm.h> -#include <utils/mapreduce.h> -#include <utils/mimetypes/mimedatabase.h> -#include <utils/networkaccessmanager.h> - -#include <QCoreApplication> -#include <QString> -#include <QStringList> -#include <QFile> -#include <QFileInfo> -#include <QDir> -#include <QRegExp> -#include <QFuture> -#include <QtConcurrentMap> -#include <QUrl> -#include <QSet> -#include <QXmlStreamReader> -#include <QXmlStreamAttributes> -#include <QMessageBox> -#include <QXmlSimpleReader> -#include <QXmlInputSource> -#include <QNetworkRequest> -#include <QNetworkReply> - -using namespace Core; - -namespace TextEditor { -namespace Internal { - -const char kPriority[] = "priority"; -const char kName[] = "name"; -const char kExtensions[] = "extensions"; -const char kMimeType[] = "mimetype"; -const char kVersion[] = "version"; -const char kUrl[] = "url"; - -class MultiDefinitionDownloader : public QObject -{ - Q_OBJECT - -public: - MultiDefinitionDownloader(const QString &savePath, const QList<QString> &installedDefinitions) : - m_installedDefinitions(installedDefinitions), - m_downloadPath(savePath) - { - connect(&m_downloadWatcher, &QFutureWatcherBase::finished, - this, &MultiDefinitionDownloader::downloadDefinitionsFinished); - } - - ~MultiDefinitionDownloader() override - { - if (m_downloadWatcher.isRunning()) - m_downloadWatcher.cancel(); - } - - void downloadDefinitions(const QList<QUrl> &urls); - -signals: - void finished(); - -private: - void downloadReferencedDefinition(const QString &name); - void downloadDefinitionsFinished(); - - QFutureWatcher<void> m_downloadWatcher; - QList<DefinitionDownloader *> m_downloaders; - QList<QString> m_installedDefinitions; - QSet<QString> m_referencedDefinitions; - QString m_downloadPath; -}; - -Manager::Manager() -{ - connect(&m_registeringWatcher, &QFutureWatcherBase::finished, - this, &Manager::registerHighlightingFilesFinished); -} - -Manager::~Manager() -{ - disconnect(&m_registeringWatcher); - disconnect(m_multiDownloader); - if (m_registeringWatcher.isRunning()) - m_registeringWatcher.cancel(); - delete m_multiDownloader; -} - -Manager *Manager::instance() -{ - static Manager manager; - return &manager; -} - -QString Manager::definitionIdByName(const QString &name) const -{ - return m_register.m_idByName.value(name); -} - -static bool matchesPattern(const QString &fileName, DefinitionMetaDataPtr metaData) -{ - if (metaData.isNull()) - return false; - foreach (const QString &pattern, metaData->patterns) { - QRegExp reg(pattern, Qt::CaseSensitive, QRegExp::Wildcard); - if (reg.exactMatch(fileName)) - return true; - } - return false; -} - -QString Manager::definitionIdByMimeType(const Utils::MimeType &mimeType) const -{ - QList<Utils::MimeType> queue; - queue.append(mimeType); - while (!queue.isEmpty()) { - const Utils::MimeType mt = queue.takeFirst(); - const QString id = m_register.m_idByMimeType.value(mt.name()); - if (!id.isEmpty()) - return id; - foreach (const QString &parent, mt.parentMimeTypes()) { - const Utils::MimeType parentMt = Utils::mimeTypeForName(parent); - if (parentMt.isValid()) - queue.append(parentMt); - } - } - return QString(); -} - -QString Manager::definitionIdByFile(const QString &filePath) const -{ - const QString fileName = QFileInfo(filePath).fileName(); - // find best match - QString bestId; - int bestPriority = -1; - auto it = m_register.m_definitionsMetaData.constBegin(); - while (it != m_register.m_definitionsMetaData.constEnd()) { - DefinitionMetaDataPtr metaData = it.value(); - if (metaData->priority > bestPriority && matchesPattern(fileName, metaData)) { - bestId = metaData->id; - bestPriority = metaData->priority; - } - ++it; - } - return bestId; -} - -QString Manager::definitionIdByMimeTypeAndFile(const Utils::MimeType &mimeType, - const QString &filePath) const -{ - QString id = definitionIdByMimeType(mimeType); - if (!filePath.isEmpty()) { - QString idByFile; - const QString fileName = QFileInfo(filePath).fileName(); - // if mime type check returned no result, or doesn't match the patterns, - // prefer a match by pattern - if (id.isEmpty() || !matchesPattern(fileName, m_register.m_definitionsMetaData.value(id))) - idByFile = definitionIdByFile(filePath); - if (!idByFile.isEmpty()) - id = idByFile; - } - return id; -} - -DefinitionMetaDataPtr Manager::availableDefinitionByName(const QString &name) const -{ - return m_availableDefinitions.value(name); -} - -QSharedPointer<HighlightDefinition> Manager::definition(const QString &id) -{ - if (!id.isEmpty() && !m_definitions.contains(id)) { - QFile definitionFile(id); - if (!definitionFile.open(QIODevice::ReadOnly | QIODevice::Text)) - return QSharedPointer<HighlightDefinition>(); - - QSharedPointer<HighlightDefinition> definition(new HighlightDefinition); - HighlightDefinitionHandler handler(definition); - - QXmlInputSource source(&definitionFile); - QXmlSimpleReader reader; - reader.setContentHandler(&handler); - m_isBuildingDefinition.insert(id); - try { - reader.parse(source); - } catch (const HighlighterException &e) { - MessageManager::write( - QCoreApplication::translate("GenericHighlighter", - "Generic highlighter error: ") + e.message(), - MessageManager::WithFocus); - definition.clear(); - } - m_isBuildingDefinition.remove(id); - definitionFile.close(); - - m_definitions.insert(id, definition); - } - - return m_definitions.value(id); -} - -DefinitionMetaDataPtr Manager::definitionMetaData(const QString &id) const -{ - return m_register.m_definitionsMetaData.value(id); -} - -bool Manager::isBuildingDefinition(const QString &id) const -{ - return m_isBuildingDefinition.contains(id); -} - -static const int kMaxProgress = 200; - -static void processHighlightingFiles(QFutureInterface<Manager::RegisterData> &future, - QStringList definitionPaths) -{ - future.setProgressRange(0, kMaxProgress); - - Manager::RegisterData data; - // iterate through paths in order, high priority > low priority - foreach (const QString &path, definitionPaths) { - if (path.isEmpty()) - continue; - - QDir definitionsDir(path); - QStringList filter(QLatin1String("*.xml")); - definitionsDir.setNameFilters(filter); - foreach (const QFileInfo &fileInfo, definitionsDir.entryInfoList()) { - if (future.isCanceled()) - return; - if (future.progressValue() < kMaxProgress - 1) - future.setProgressValue(future.progressValue() + 1); - - const DefinitionMetaDataPtr &metaData = - Manager::parseMetadata(fileInfo); - // skip failing or already existing definitions - if (!metaData.isNull() && !data.m_idByName.contains(metaData->name)) { - const QString id = metaData->id; - data.m_idByName.insert(metaData->name, id); - data.m_definitionsMetaData.insert(id, metaData); - foreach (const QString &mt, metaData->mimeTypes) { - bool insert = true; - // check if there is already a definition registered with higher priority - const QString existingDefinition = data.m_idByMimeType.value(mt); - if (!existingDefinition.isEmpty()) { - // check priorities - DefinitionMetaDataPtr existingMetaData = - data.m_definitionsMetaData.value(existingDefinition); - if (!existingMetaData.isNull() && existingMetaData->priority > metaData->priority) - insert = false; - } - if (insert) - data.m_idByMimeType.insert(mt, id); - } - } - } - } - - future.reportResult(data); -} - -void Manager::registerHighlightingFiles() -{ - if (!m_registeringWatcher.isRunning()) { - clear(); - - QStringList definitionsPaths; - const HighlighterSettings &settings = TextEditorSettings::highlighterSettings(); - definitionsPaths.append(settings.definitionFilesPath()); - if (settings.useFallbackLocation()) - definitionsPaths.append(settings.fallbackDefinitionFilesPath()); - - QFuture<RegisterData> future = Utils::runAsync(processHighlightingFiles, definitionsPaths); - m_registeringWatcher.setFuture(future); - } else { - m_hasQueuedRegistration = true; - m_registeringWatcher.cancel(); - } -} - -void Manager::registerHighlightingFilesFinished() -{ - if (m_hasQueuedRegistration) { - m_hasQueuedRegistration = false; - registerHighlightingFiles(); - } else if (!m_registeringWatcher.isCanceled()) { - m_register = m_registeringWatcher.result(); - - emit highlightingFilesRegistered(); - } -} - -DefinitionMetaDataPtr Manager::parseMetadata(const QFileInfo &fileInfo) -{ - static const QLatin1Char kSemiColon(';'); - static const QLatin1String kLanguage("language"); - - QFile definitionFile(fileInfo.absoluteFilePath()); - if (!definitionFile.open(QIODevice::ReadOnly | QIODevice::Text)) - return DefinitionMetaDataPtr(); - - DefinitionMetaDataPtr metaData(new HighlightDefinitionMetaData); - - QXmlStreamReader reader(&definitionFile); - while (!reader.atEnd() && !reader.hasError()) { - if (reader.readNext() == QXmlStreamReader::StartElement && reader.name() == kLanguage) { - const QXmlStreamAttributes &atts = reader.attributes(); - - metaData->fileName = fileInfo.fileName(); - metaData->id = fileInfo.absoluteFilePath(); - metaData->name = atts.value(QLatin1String(kName)).toString(); - metaData->version = atts.value(QLatin1String(kVersion)).toString(); - metaData->priority = atts.value(QLatin1String(kPriority)).toString().toInt(); - metaData->patterns = atts.value(QLatin1String(kExtensions)) - .toString().split(kSemiColon, QString::SkipEmptyParts); - - metaData->mimeTypes = atts.value(QLatin1String(kMimeType)). - toString().split(kSemiColon, QString::SkipEmptyParts); - break; - } - } - reader.clear(); - definitionFile.close(); - - return metaData; -} - -QList<DefinitionMetaDataPtr> Manager::parseAvailableDefinitionsList(QIODevice *device) -{ - static const QLatin1Char kSlash('/'); - static const QLatin1String kDefinition("Definition"); - - m_availableDefinitions.clear(); - QXmlStreamReader reader(device); - while (!reader.atEnd() && !reader.hasError()) { - if (reader.readNext() == QXmlStreamReader::StartElement && - reader.name() == kDefinition) { - const QXmlStreamAttributes &atts = reader.attributes(); - - DefinitionMetaDataPtr metaData(new HighlightDefinitionMetaData); - metaData->name = atts.value(QLatin1String(kName)).toString(); - metaData->version = atts.value(QLatin1String(kVersion)).toString(); - QString url = atts.value(QLatin1String(kUrl)).toString(); - metaData->url = QUrl(url); - const int slash = url.lastIndexOf(kSlash); - if (slash != -1) - metaData->fileName = url.right(url.length() - slash - 1); - - m_availableDefinitions.insert(metaData->name, metaData); - } - } - reader.clear(); - - return m_availableDefinitions.values(); -} - -void Manager::downloadAvailableDefinitionsMetaData() -{ - QUrl url(QLatin1String("https://www.kate-editor.org/syntax/update-5.60.xml")); - QNetworkRequest request(url); - // Currently this takes a couple of seconds on Windows 7: QTBUG-10106. - QNetworkReply *reply = Utils::NetworkAccessManager::instance()->get(request); - connect(reply, &QNetworkReply::finished, - this, &Manager::downloadAvailableDefinitionsListFinished); -} - -void Manager::downloadAvailableDefinitionsListFinished() -{ - if (auto reply = qobject_cast<QNetworkReply *>(sender())) { - if (reply->error() == QNetworkReply::NoError) - emit definitionsMetaDataReady(parseAvailableDefinitionsList(reply)); - else - emit errorDownloadingDefinitionsMetaData(); - reply->deleteLater(); - } -} - -void Manager::downloadDefinitions(const QList<QUrl> &urls, const QString &savePath) -{ - m_multiDownloader = new MultiDefinitionDownloader(savePath, m_register.m_idByName.keys()); - connect(m_multiDownloader, &MultiDefinitionDownloader::finished, - this, &Manager::downloadDefinitionsFinished); - m_multiDownloader->downloadDefinitions(urls); -} - -void MultiDefinitionDownloader::downloadDefinitions(const QList<QUrl> &urls) -{ - m_downloaders.clear(); - foreach (const QUrl &url, urls) { - auto downloader = new DefinitionDownloader(url, m_downloadPath); - connect(downloader, &DefinitionDownloader::foundReferencedDefinition, - this, &MultiDefinitionDownloader::downloadReferencedDefinition); - m_downloaders.append(downloader); - } - - QFuture<void> future = Utils::map(m_downloaders, &DefinitionDownloader::run); - m_downloadWatcher.setFuture(future); - ProgressManager::addTask(future, tr("Downloading Highlighting Definitions"), - "TextEditor.Task.Download"); -} - -void MultiDefinitionDownloader::downloadDefinitionsFinished() -{ - int errors = 0; - bool writeError = false; - foreach (DefinitionDownloader *downloader, m_downloaders) { - DefinitionDownloader::Status status = downloader->status(); - if (status != DefinitionDownloader::Ok) { - ++errors; - if (status == DefinitionDownloader::WriteError && !writeError) - writeError = true; - } - delete downloader; - } - - if (errors > 0) { - QString text; - if (errors == m_downloaders.size()) - text = tr("Error downloading selected definition(s)."); - else - text = tr("Error downloading one or more definitions."); - if (writeError) - text.append(QLatin1Char('\n') + tr("Please check the directory's access rights.")); - QMessageBox::critical(Core::ICore::dialogParent(), tr("Download Error"), text); - } - - QList<QUrl> urls; - foreach (const QString &definition, m_referencedDefinitions) { - if (DefinitionMetaDataPtr metaData = - Manager::instance()->availableDefinitionByName(definition)) { - urls << metaData->url; - } - } - m_referencedDefinitions.clear(); - if (urls.isEmpty()) - emit finished(); - else - downloadDefinitions(urls); -} - -void Manager::downloadDefinitionsFinished() -{ - delete m_multiDownloader; - m_multiDownloader = nullptr; -} - -void MultiDefinitionDownloader::downloadReferencedDefinition(const QString &name) -{ - if (m_installedDefinitions.contains(name)) - return; - m_referencedDefinitions.insert(name); - m_installedDefinitions.append(name); -} - -bool Manager::isDownloadingDefinitions() const -{ - return m_multiDownloader != nullptr; -} - -void Manager::clear() -{ - m_register.m_idByName.clear(); - m_register.m_idByMimeType.clear(); - m_register.m_definitionsMetaData.clear(); - m_definitions.clear(); -} - -} // namespace Internal -} // namespace TextEditor - -#include "manager.moc" diff --git a/src/plugins/texteditor/generichighlighter/manager.h b/src/plugins/texteditor/generichighlighter/manager.h deleted file mode 100644 index 18a6c3016f..0000000000 --- a/src/plugins/texteditor/generichighlighter/manager.h +++ /dev/null @@ -1,118 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include "highlightdefinitionmetadata.h" - -#include <QString> -#include <QHash> -#include <QSet> -#include <QUrl> -#include <QList> -#include <QPair> -#include <QSharedPointer> -#include <QFutureWatcher> - -QT_BEGIN_NAMESPACE -class QFileInfo; -class QIODevice; -template <class> class QFutureInterface; -QT_END_NAMESPACE - -namespace Utils { class MimeType; } - -namespace TextEditor { -namespace Internal { - -class HighlightDefinition; -class ManagerProcessor; -class MultiDefinitionDownloader; - -// This is the generic highlighter manager. It is not thread-safe. - -class Manager : public QObject -{ - Q_OBJECT -public: - ~Manager() override; - static Manager *instance(); - - QString definitionIdByName(const QString &name) const; - QString definitionIdByMimeType(const Utils::MimeType &mimeType) const; - QString definitionIdByFile(const QString &filePath) const; - QString definitionIdByMimeTypeAndFile(const Utils::MimeType &mimeType, - const QString &filePath) const; - DefinitionMetaDataPtr availableDefinitionByName(const QString &name) const; - - bool isBuildingDefinition(const QString &id) const; - QSharedPointer<HighlightDefinition> definition(const QString &id); - DefinitionMetaDataPtr definitionMetaData(const QString &id) const; - - void downloadAvailableDefinitionsMetaData(); - void downloadDefinitions(const QList<QUrl> &urls, const QString &savePath); - bool isDownloadingDefinitions() const; - void registerHighlightingFiles(); - - static DefinitionMetaDataPtr parseMetadata(const QFileInfo &fileInfo); - - struct RegisterData - { - QHash<QString, QString> m_idByName; - QHash<QString, QString> m_idByMimeType; - QHash<QString, DefinitionMetaDataPtr> m_definitionsMetaData; - }; -private: - void registerHighlightingFilesFinished(); - void downloadAvailableDefinitionsListFinished(); - void downloadDefinitionsFinished(); - -signals: - void highlightingFilesRegistered(); - -private: - Manager(); - - void clear(); - - MultiDefinitionDownloader *m_multiDownloader = nullptr; - QList<DefinitionMetaDataPtr> parseAvailableDefinitionsList(QIODevice *device); - - QSet<QString> m_isBuildingDefinition; - QHash<QString, QSharedPointer<HighlightDefinition> > m_definitions; - QHash<QString, DefinitionMetaDataPtr> m_availableDefinitions; - - RegisterData m_register; - bool m_hasQueuedRegistration = false; - QFutureWatcher<RegisterData> m_registeringWatcher; - friend class ManagerProcessor; - -signals: - void definitionsMetaDataReady(const QList<Internal::DefinitionMetaDataPtr>&); - void errorDownloadingDefinitionsMetaData(); -}; - -} // namespace Internal -} // namespace TextEditor diff --git a/src/plugins/texteditor/generichighlighter/progressdata.cpp b/src/plugins/texteditor/generichighlighter/progressdata.cpp deleted file mode 100644 index a6453c8399..0000000000 --- a/src/plugins/texteditor/generichighlighter/progressdata.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "progressdata.h" -#include "rule.h" - -using namespace TextEditor; -using namespace Internal; - -ProgressData::ProgressData() : - m_offset(0), - m_savedOffset(-1), - m_onlySpacesSoFar(true), - m_openingBraceMatchAtFirstNonSpace(false), - m_closingBraceMatchAtNonEnd(false), - m_willContinueLine(false) -{} - -ProgressData::~ProgressData() -{ - foreach (Rule *rule, m_trackedRules) - rule->progressFinished(); -} - -void ProgressData::setOffset(const int offset) -{ m_offset = offset; } - -int ProgressData::offset() const -{ return m_offset; } - -void ProgressData::incrementOffset() -{ ++m_offset; } - -void ProgressData::incrementOffset(const int increment) -{ m_offset += increment; } - -void ProgressData::saveOffset() -{ m_savedOffset = m_offset; } - -void ProgressData::restoreOffset() -{ - Q_ASSERT(m_savedOffset != -1); - m_offset = m_savedOffset; - m_savedOffset = -1; -} - -void ProgressData::setOnlySpacesSoFar(const bool onlySpaces) -{ m_onlySpacesSoFar = onlySpaces; } - -bool ProgressData::isOnlySpacesSoFar() const -{ return m_onlySpacesSoFar; } - -void ProgressData::setOpeningBraceMatchAtFirstNonSpace(const bool match) -{ m_openingBraceMatchAtFirstNonSpace = match; } - -bool ProgressData::isOpeningBraceMatchAtFirstNonSpace() const -{ return m_openingBraceMatchAtFirstNonSpace; } - -void ProgressData::setClosingBraceMatchAtNonEnd(const bool match) -{ m_closingBraceMatchAtNonEnd = match; } - -bool ProgressData::isClosingBraceMatchAtNonEnd() const -{ return m_closingBraceMatchAtNonEnd; } - -void ProgressData::clearBracesMatches() -{ - if (m_openingBraceMatchAtFirstNonSpace) - m_openingBraceMatchAtFirstNonSpace = false; - if (m_closingBraceMatchAtNonEnd) - m_closingBraceMatchAtNonEnd = false; -} - -void ProgressData::setWillContinueLine(const bool willContinue) -{ m_willContinueLine = willContinue; } - -bool ProgressData::isWillContinueLine() const -{ return m_willContinueLine; } - -void ProgressData::setCaptures(const QStringList &captures) -{ m_captures = captures; } - -const QStringList &ProgressData::captures() const -{ return m_captures; } - -void ProgressData::trackRule(Rule *rule) -{ - m_trackedRules.append(rule); -} - -void ProgressData::unTrackRule(Rule *rule) -{ - m_trackedRules.removeAll(rule); -} - -bool ProgressData::detectRecursion(const QString &contextId) -{ - if (m_offset != m_iterationOffset) { - m_iterationOffset = m_offset; - m_iterationContextIds.clear(); - } - - if (m_iterationContextIds.contains(contextId)) - return true; - - m_iterationContextIds.append(contextId); - - return false; -} diff --git a/src/plugins/texteditor/generichighlighter/progressdata.h b/src/plugins/texteditor/generichighlighter/progressdata.h deleted file mode 100644 index 7350eb0d04..0000000000 --- a/src/plugins/texteditor/generichighlighter/progressdata.h +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include <QStringList> - -namespace TextEditor { -namespace Internal { - -class Rule; - -class ProgressData -{ -public: - ProgressData(); - ~ProgressData(); - - void setOffset(const int offset); - int offset() const; - - void incrementOffset(); - void incrementOffset(const int increment); - - void saveOffset(); - void restoreOffset(); - - void setOnlySpacesSoFar(const bool onlySpaces); - bool isOnlySpacesSoFar() const; - - void setOpeningBraceMatchAtFirstNonSpace(const bool match); - bool isOpeningBraceMatchAtFirstNonSpace() const; - - void setClosingBraceMatchAtNonEnd(const bool match); - bool isClosingBraceMatchAtNonEnd() const; - - void clearBracesMatches(); - - void setWillContinueLine(const bool willContinue); - bool isWillContinueLine() const; - - void setCaptures(const QStringList &captures); - const QStringList &captures() const; - - void trackRule(Rule *rule); - void unTrackRule(Rule *rule); - - bool detectRecursion(const QString &contextId); - -private: - int m_offset; - int m_savedOffset; - bool m_onlySpacesSoFar; - bool m_openingBraceMatchAtFirstNonSpace; - bool m_closingBraceMatchAtNonEnd; - bool m_willContinueLine; - QStringList m_captures; - QList<Rule *> m_trackedRules; - int m_iterationOffset = -1; - QStringList m_iterationContextIds; -}; - -} // namespace Internal -} // namespace TextEditor diff --git a/src/plugins/texteditor/generichighlighter/reuse.h b/src/plugins/texteditor/generichighlighter/reuse.h deleted file mode 100644 index d8d21f35c6..0000000000 --- a/src/plugins/texteditor/generichighlighter/reuse.h +++ /dev/null @@ -1,93 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include <Qt> -#include <QString> -#include <QLatin1String> -#include <QChar> -#include <QFont> - -namespace TextEditor { -namespace Internal { - -inline bool toBool(const QString &s) -{ - static const QLatin1String kTrue("true"); - static const QLatin1String k1("1"); - - if (s.toLower() == kTrue || s == k1) - return true; - return false; -} - - -inline Qt::CaseSensitivity toCaseSensitivity(const bool sensitive) -{ - if (sensitive) - return Qt::CaseSensitive; - return Qt::CaseInsensitive; -} - -inline QFont::Weight toFontWeight(const bool bold) -{ - if (bold) - return QFont::Bold; - else - return QFont::Normal; -} - -inline bool isOctalDigit(const QChar &c) -{ - static const QLatin1Char k0('0'); - static const QLatin1Char k7('7'); - - return c >= k0 && c <= k7; -} - -inline bool isHexDigit(const QChar &c) -{ - static const QLatin1Char k0('0'); - static const QLatin1Char k9('9'); - static const QLatin1Char kA('A'); - static const QLatin1Char kF('F'); - static const QLatin1Char ka('a'); - static const QLatin1Char kf('f'); - - if ((c >= k0 && c <= k9) || (c >= kA && c <= kF) || (c >= ka && c <= kf)) - return true; - - return false; -} - -inline void setStartCharacter(QChar *c, const QString &character) -{ - if (!character.isEmpty()) - *c = character.at(0); -} - -} // namespace Internal -} // namespace TextEditor diff --git a/src/plugins/texteditor/generichighlighter/rule.cpp b/src/plugins/texteditor/generichighlighter/rule.cpp deleted file mode 100644 index 24e16267a2..0000000000 --- a/src/plugins/texteditor/generichighlighter/rule.cpp +++ /dev/null @@ -1,292 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "rule.h" -#include "progressdata.h" -#include "highlightdefinition.h" -#include "reuse.h" - -#include <functional> - -using namespace TextEditor; -using namespace Internal; - -const QLatin1Char Rule::kBackSlash('\\'); -const QLatin1Char Rule::kUnderscore('_'); -const QLatin1Char Rule::kDot('.'); -const QLatin1Char Rule::kPlus('+'); -const QLatin1Char Rule::kMinus('-'); -const QLatin1Char Rule::kZero('0'); -const QLatin1Char Rule::kQuote('\"'); -const QLatin1Char Rule::kSingleQuote('\''); -const QLatin1Char Rule::kQuestion('?'); -const QLatin1Char Rule::kX('x'); -const QLatin1Char Rule::kA('a'); -const QLatin1Char Rule::kB('b'); -const QLatin1Char Rule::kE('e'); -const QLatin1Char Rule::kF('f'); -const QLatin1Char Rule::kN('n'); -const QLatin1Char Rule::kR('r'); -const QLatin1Char Rule::kT('t'); -const QLatin1Char Rule::kV('v'); -const QLatin1Char Rule::kOpeningBrace('{'); -const QLatin1Char Rule::kClosingBrace('}'); - -Rule::Rule(bool consumesNonSpace) : - m_lookAhead(false), m_firstNonSpace(false), m_column(-1), m_consumesNonSpace(consumesNonSpace) -{} - -Rule::~Rule() = default; - -void Rule::setContext(const QString &context) -{ m_context = context; } - -const QString &Rule::context() const -{ return m_context; } - -void Rule::setItemData(const QString &itemData) -{ m_itemData = itemData; } - -const QString &Rule::itemData() const -{ return m_itemData; } - -void Rule::setBeginRegion(const QString &begin) -{ m_beginRegion = begin; } - -const QString &Rule::beginRegion() const -{ return m_beginRegion; } - -void Rule::setEndRegion(const QString &end) -{ m_endRegion = end; } - -const QString &Rule::endRegion() const -{ return m_endRegion; } - -void Rule::setLookAhead(const QString &lookAhead) -{ m_lookAhead = toBool(lookAhead); } - -bool Rule::isLookAhead() const -{ return m_lookAhead; } - -void Rule::setFirstNonSpace(const QString &firstNonSpace) -{ m_firstNonSpace = toBool(firstNonSpace); } - -bool Rule::isFirstNonSpace() const -{ return m_firstNonSpace; } - -void Rule::setColumn(const QString &column) -{ - bool ok; - m_column = column.toInt(&ok); - if (!ok) - m_column = -1; -} - -int Rule::column() const -{ return m_column; } - -void Rule::addChild(const QSharedPointer<Rule> &rule) -{ m_children.append(rule); } - -bool Rule::hasChildren() const -{ return !m_children.isEmpty(); } - -const QList<QSharedPointer<Rule> > &Rule::children() const -{ return m_children; } - -void Rule::setDefinition(const QSharedPointer<HighlightDefinition> &definition) -{ m_definition = definition; } - -const QSharedPointer<HighlightDefinition> &Rule::definition() const -{ return m_definition; } - -template <class predicate_t> -bool Rule::predicateMatchSucceed(const QString &text, - const int length, - ProgressData *progress, - const predicate_t &p) const -{ - int original = progress->offset(); - while (progress->offset() < length && p(text.at(progress->offset()))) - progress->incrementOffset(); - - if (original != progress->offset()) - return true; - - return false; -} - -bool Rule::charPredicateMatchSucceed(const QString &text, - const int length, - ProgressData *progress, - bool (QChar::* predicate)() const) const -{ - return predicateMatchSucceed(text, length, progress, [predicate](const QChar &c) { - return (c.*predicate)(); - }); -} - -bool Rule::charPredicateMatchSucceed(const QString &text, - const int length, - ProgressData *progress, - bool (*predicate)(const QChar &)) const -{ - return predicateMatchSucceed(text, length, progress, [predicate](const QChar &c) { - return predicate(c); - }); -} - -bool Rule::matchSucceed(const QString &text, const int length, ProgressData *progress) -{ - if (m_firstNonSpace && !progress->isOnlySpacesSoFar()) - return false; - - if (m_column != -1 && m_column != progress->offset()) - return false; - - int original = progress->offset(); - if (doMatchSucceed(text, length, progress)) { - if (progress->isOnlySpacesSoFar() && !m_lookAhead && m_consumesNonSpace) - progress->setOnlySpacesSoFar(false); - - if (m_lookAhead) - progress->setOffset(original); - - return true; - } - - return false; -} - -Rule *Rule::clone() const -{ return doClone(); } - -void Rule::progressFinished() -{ doProgressFinished(); } - -bool Rule::matchCharacter(const QString &text, - const int length, - ProgressData *progress, - const QChar &c, - bool saveRestoreOffset) const -{ - Q_UNUSED(length) - Q_ASSERT(progress->offset() < length); - - if (text.at(progress->offset()) == c) { - if (saveRestoreOffset) - progress->saveOffset(); - progress->incrementOffset(); - return true; - } - - return false; -} - -bool Rule::matchEscapeSequence(const QString &text, - const int length, - ProgressData *progress, - bool saveRestoreOffset) const -{ - if (matchCharacter(text, length, progress, kBackSlash, saveRestoreOffset)) { - - if (progress->offset() < length) { - const QChar &c = text.at(progress->offset()); - if (c == kA || c == kB || c == kE || c == kF || c == kN || c == kR || c == kT || - c == kV || c == kQuestion || c == kSingleQuote || c == kQuote || c == kBackSlash) { - progress->incrementOffset(); - return true; - } else if (saveRestoreOffset) { - progress->restoreOffset(); - } - } else if (saveRestoreOffset) { - progress->restoreOffset(); - } - } - - return false; -} - -bool Rule::matchOctalSequence(const QString &text, - const int length, - ProgressData *progress, - bool saveRestoreOffset) const -{ - // An octal sequence is identified as in the C++ Standard. - // octal-escape-sequence: - // \ octal-digit - // \ octal-digit octal-digit - // \ octal-digit octal-digit octal-digit - - if (matchCharacter(text, length, progress, kBackSlash, saveRestoreOffset)) { - - int count = 0; - while (progress->offset() < length && - count < 3 && - isOctalDigit(text.at(progress->offset()))) { - ++count; - progress->incrementOffset(); - } - - if (count > 0) - return true; - else if (saveRestoreOffset) - progress->restoreOffset(); - } - - return false; -} - -bool Rule::matchHexSequence(const QString &text, - const int length, - ProgressData *progress, - bool saveRestoreOffset) const -{ - // An hex sequence is identified as in the C++ Standard. - // hexadecimal-escape-sequence: - // \x hexadecimal-digit - // hexadecimal-escape-sequence hexadecimal-digit - - if (matchCharacter(text, length, progress, kBackSlash, saveRestoreOffset)) { - - if (progress->offset() < length && matchCharacter(text, length, progress, kX, false)) { - bool found = false; - while (progress->offset() < length && isHexDigit(text.at(progress->offset()))) { - if (!found) - found = true; - progress->incrementOffset(); - } - - if (found) - return true; - else if (saveRestoreOffset) - progress->restoreOffset(); - } else if (saveRestoreOffset) { - progress->restoreOffset(); - } - } - - return false; -} diff --git a/src/plugins/texteditor/generichighlighter/rule.h b/src/plugins/texteditor/generichighlighter/rule.h deleted file mode 100644 index 4e25bef11a..0000000000 --- a/src/plugins/texteditor/generichighlighter/rule.h +++ /dev/null @@ -1,157 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include <QString> -#include <QList> -#include <QSharedPointer> - -namespace TextEditor { -namespace Internal { - -class ProgressData; -class HighlightDefinition; - -class Rule -{ -public: - Rule(bool consumesNonSpace = true); - virtual ~Rule(); - - void setContext(const QString &context); - const QString &context() const; - - void setItemData(const QString &itemData); - const QString &itemData() const; - - void setBeginRegion(const QString &begin); - const QString &beginRegion() const; - - void setEndRegion(const QString &end); - const QString &endRegion() const; - - void setLookAhead(const QString &lookAhead); - bool isLookAhead() const; - - void setFirstNonSpace(const QString &firstNonSpace); - bool isFirstNonSpace() const; - - void setColumn(const QString &column); - int column() const; - - void addChild(const QSharedPointer<Rule> &rule); - const QList<QSharedPointer<Rule> > &children() const; - bool hasChildren() const; - - void setDefinition(const QSharedPointer<HighlightDefinition> &definition); - const QSharedPointer<HighlightDefinition> &definition() const; - - bool matchSucceed(const QString &text, const int length, ProgressData *progress); - - Rule *clone() const; - - void progressFinished(); - -protected: - bool charPredicateMatchSucceed(const QString &text, - const int length, - ProgressData *progress, - bool (QChar::* predicate)() const) const; - bool charPredicateMatchSucceed(const QString &text, - const int length, - ProgressData *progress, - bool (*predicate)(const QChar &)) const; - - bool matchCharacter(const QString &text, - const int length, - ProgressData *progress, - const QChar &c, - bool saveRestoreOffset = true) const; - bool matchEscapeSequence(const QString &text, - const int length, - ProgressData *progress, - bool saveRestoreOffset = true) const; - bool matchOctalSequence(const QString &text, - const int length, - ProgressData *progress, - bool saveRestoreOffset = true) const; - bool matchHexSequence(const QString &text, - const int length, - ProgressData *progress, - bool saveRestoreOffset = true) const; - - static const QLatin1Char kBackSlash; - static const QLatin1Char kUnderscore; - static const QLatin1Char kDot; - static const QLatin1Char kPlus; - static const QLatin1Char kMinus; - static const QLatin1Char kZero; - static const QLatin1Char kQuote; - static const QLatin1Char kSingleQuote; - static const QLatin1Char kQuestion; - static const QLatin1Char kX; - static const QLatin1Char kA; - static const QLatin1Char kB; - static const QLatin1Char kE; - static const QLatin1Char kF; - static const QLatin1Char kN; - static const QLatin1Char kR; - static const QLatin1Char kT; - static const QLatin1Char kV; - static const QLatin1Char kOpeningBrace; - static const QLatin1Char kClosingBrace; - -private: - virtual bool doMatchSucceed(const QString &text, const int length, ProgressData *progress) = 0; - - virtual Rule *doClone() const = 0; - - virtual void doProgressFinished() {} - - template <class predicate_t> - bool predicateMatchSucceed(const QString &text, - const int length, - ProgressData *progress, - const predicate_t &p) const; - - QString m_context; - QString m_itemData; - QString m_beginRegion; - QString m_endRegion; - bool m_lookAhead; - bool m_firstNonSpace; - int m_column; - bool m_consumesNonSpace; - - QList<QSharedPointer<Rule> > m_children; - - // Rules are represented within contexts. However, they have their own definition because - // of externally included rules. - QSharedPointer<HighlightDefinition> m_definition; -}; - -} // namespace Internal -} // namespace TextEditor diff --git a/src/plugins/texteditor/generichighlighter/specificrules.cpp b/src/plugins/texteditor/generichighlighter/specificrules.cpp deleted file mode 100644 index 1c52986b0c..0000000000 --- a/src/plugins/texteditor/generichighlighter/specificrules.cpp +++ /dev/null @@ -1,542 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "specificrules.h" -#include "highlightdefinition.h" -#include "keywordlist.h" -#include "progressdata.h" -#include "reuse.h" - -#include <QLatin1Char> - -using namespace TextEditor; -using namespace Internal; - -namespace { - -void replaceByCaptures(QChar *c, const QStringList &captures) -{ - int index = c->digitValue(); - if (index > 0) { - const QString &capture = captures.at(index); - if (!capture.isEmpty()) - *c = capture.at(0); - } -} - -void replaceByCaptures(QString *s, const QStringList &captures) -{ - static const QLatin1Char kPercent('%'); - - int index; - int from = 0; - while ((index = s->indexOf(kPercent, from)) != -1) { - from = index + 1; - - QString accumulator; - while (from < s->length() && s->at(from).isDigit()) { - accumulator.append(s->at(from)); - ++from; - } - - bool ok; - int number = accumulator.toInt(&ok); - Q_ASSERT(ok); - - s->replace(index, accumulator.length() + 1, captures.at(number)); - } -} -} - -// DetectChar -void DetectCharRule::setChar(const QString &character) -{ setStartCharacter(&m_char, character); } - -void DetectCharRule::doReplaceExpressions(const QStringList &captures) -{ replaceByCaptures(&m_char, captures); } - -bool DetectCharRule::doMatchSucceed(const QString &text, - const int length, - ProgressData *progress) -{ - if (matchCharacter(text, length, progress, m_char)) { - // This is to make code folding have a control flow style look in the case of braces. - // Naturally, this assumes that language definitions use braces with this meaning. - if (m_char == kOpeningBrace && progress->isOnlySpacesSoFar() && !isLookAhead()) { - progress->setOpeningBraceMatchAtFirstNonSpace(true); - } else if (m_char == kClosingBrace && - !text.right(length - progress->offset()).trimmed().isEmpty()) { - progress->setClosingBraceMatchAtNonEnd(true); - } - return true; - } - return false; -} - -// Detect2Chars -void Detect2CharsRule::setChar(const QString &character) -{ setStartCharacter(&m_char, character); } - -void Detect2CharsRule::setChar1(const QString &character) -{ setStartCharacter(&m_char1, character); } - -void Detect2CharsRule::doReplaceExpressions(const QStringList &captures) -{ - replaceByCaptures(&m_char, captures); - replaceByCaptures(&m_char1, captures); -} - -bool Detect2CharsRule::doMatchSucceed(const QString &text, - const int length, - ProgressData *progress) -{ - if (matchCharacter(text, length, progress, m_char)) { - if (progress->offset() < length && matchCharacter(text, length, progress, m_char1, false)) - return true; - else - progress->restoreOffset(); - } - - return false; -} - -// AnyChar -void AnyCharRule::setCharacterSet(const QString &s) -{ m_characterSet = s; } - -bool AnyCharRule::doMatchSucceed(const QString &text, - const int length, - ProgressData *progress) -{ - Q_UNUSED(length) - - if (m_characterSet.contains(text.at(progress->offset()))) { - progress->incrementOffset(); - return true; - } - - return false; -} - -// StringDetect -void StringDetectRule::setString(const QString &s) -{ - m_string = s; - m_length = m_string.length(); -} - -void StringDetectRule::setInsensitive(const QString &insensitive) -{ m_caseSensitivity = toCaseSensitivity(!toBool(insensitive)); } - -void StringDetectRule::doReplaceExpressions(const QStringList &captures) -{ - replaceByCaptures(&m_string, captures); - m_length = m_string.length(); -} - -bool StringDetectRule::doMatchSucceed(const QString &text, - const int length, - ProgressData *progress) -{ - if (length - progress->offset() >= m_length) { - QString candidate = text.fromRawData(text.unicode() + progress->offset(), m_length); - if (candidate.compare(m_string, m_caseSensitivity) == 0) { - progress->incrementOffset(m_length); - return true; - } - } - - return false; -} - -bool WordDetectRule::doMatchSucceed(const QString &text, const int length, ProgressData *progress) -{ - const int offset = progress->offset(); - if (length - offset < m_length) - return false; - if (offset > 0 && !definition()->isDelimiter(text.at(offset - 1))) - return false; - if (text.midRef(offset, m_string.size()).compare(m_string, m_caseSensitivity) != 0) - return false; - if (length > offset + m_string.size() && !definition()->isDelimiter(text.at(offset + m_string.size()))) - return false; - progress->incrementOffset(m_length); - return true; -} - -// RegExpr -RegExprRule::~RegExprRule() -{ - if (m_progress) - m_progress->unTrackRule(this); -} - -void RegExprRule::setPattern(const QString &pattern) -{ - if (pattern.startsWith(QLatin1Char('^'))) - m_onlyBegin = true; - m_expression.setPattern(pattern); -} - -void RegExprRule::setInsensitive(const QString &insensitive) -{ m_expression.setCaseSensitivity(toCaseSensitivity(!toBool(insensitive))); } - -void RegExprRule::setMinimal(const QString &minimal) -{ m_expression.setMinimal(toBool(minimal)); } - -void RegExprRule::doReplaceExpressions(const QStringList &captures) -{ - QString s = m_expression.pattern(); - replaceByCaptures(&s, captures); - m_expression.setPattern(s); -} - -void RegExprRule::doProgressFinished() -{ - m_progress = nullptr; - m_isCached = false; -} - -bool RegExprRule::isExactMatch(ProgressData *progress) -{ - if (progress->offset() == m_offset && m_length > 0) { - progress->incrementOffset(m_length); - progress->setCaptures(m_captures); - return true; - } - return false; -} - -bool RegExprRule::doMatchSucceed(const QString &text, - const int length, - ProgressData *progress) -{ - Q_UNUSED(length) - - // A regular expression match is considered valid if it happens at the current position - // and if the match length is not zero. - const int offset = progress->offset(); - if (offset > 0 && m_onlyBegin) - return false; - - if (m_isCached) { - if (offset < m_offset || m_offset == -1 || m_length == 0) - return false; - if (isExactMatch(progress)) - return true; - } - - m_offset = m_expression.indexIn(text, offset, QRegExp::CaretAtOffset); - m_length = m_expression.matchedLength(); - m_captures = m_expression.capturedTexts(); - - if (isExactMatch(progress)) - return true; - - m_isCached = true; - m_progress = progress; - progress->trackRule(this); - - return false; -} - -RegExprRule *RegExprRule::doClone() const -{ - auto clone = new RegExprRule(*this); - if (m_progress) - m_progress->trackRule(clone); - return clone; -} - -// Keyword -KeywordRule::KeywordRule(const QSharedPointer<HighlightDefinition> &definition) : - m_overrideGlobal(false), - m_localCaseSensitivity(Qt::CaseSensitive) -{ - setDefinition(definition); -} - -KeywordRule::~KeywordRule() = default; - -void KeywordRule::setInsensitive(const QString &insensitive) -{ - if (!insensitive.isEmpty()) { - m_overrideGlobal = true; - m_localCaseSensitivity = toCaseSensitivity(!toBool(insensitive)); - } -} - -void KeywordRule::setList(const QString &listName) -{ m_list = definition()->keywordList(listName); } - -bool KeywordRule::doMatchSucceed(const QString &text, - const int length, - ProgressData *progress) -{ - if (m_list.isNull()) // Happens if a keyword rule points to a none existing keyword list - return false; - - int current = progress->offset(); - - if (current > 0 && !definition()->isDelimiter(text.at(current - 1))) - return false; - if (definition()->isDelimiter(text.at(current))) - return false; - - while (current < length && !definition()->isDelimiter(text.at(current))) - ++current; - - QString candidate = - QString::fromRawData(text.unicode() + progress->offset(), current - progress->offset()); - if ((m_overrideGlobal && m_list->isKeyword(candidate, m_localCaseSensitivity)) || - (!m_overrideGlobal && m_list->isKeyword(candidate, definition()->keywordsSensitive()))) { - progress->setOffset(current); - return true; - } - - return false; -} - -// Int -bool IntRule::doMatchSucceed(const QString &text, - const int length, - ProgressData *progress) -{ - const int offset = progress->offset(); - - // This is necessary to correctly highlight an invalid octal like 09, for example. - if (offset > 0 && text.at(offset - 1).isDigit()) - return false; - - if (text.at(offset).isDigit() && text.at(offset) != kZero) { - progress->incrementOffset(); - charPredicateMatchSucceed(text, length, progress, &QChar::isDigit); - return true; - } - - return false; -} - -// Float -bool FloatRule::doMatchSucceed(const QString &text, const int length, ProgressData *progress) -{ - progress->saveOffset(); - - bool integralPart = charPredicateMatchSucceed(text, length, progress, &QChar::isDigit); - - bool decimalPoint = false; - if (progress->offset() < length && text.at(progress->offset()) == kDot) { - progress->incrementOffset(); - decimalPoint = true; - } - - bool fractionalPart = charPredicateMatchSucceed(text, length, progress, &QChar::isDigit); - - bool exponentialPart = false; - int offset = progress->offset(); - if (offset < length && (text.at(offset) == kE || text.at(offset).toLower() == kE)) { - progress->incrementOffset(); - - offset = progress->offset(); - if (offset < length && (text.at(offset) == kPlus || text.at(offset) == kMinus)) - progress->incrementOffset(); - - if (charPredicateMatchSucceed(text, length, progress, &QChar::isDigit)) { - exponentialPart = true; - } else { - progress->restoreOffset(); - return false; - } - } - - if ((integralPart || fractionalPart) && (decimalPoint || exponentialPart)) - return true; - - progress->restoreOffset(); - return false; -} - -// COctal -bool HlCOctRule::doMatchSucceed(const QString &text, - const int length, - ProgressData *progress) -{ - if (matchCharacter(text, length, progress, kZero)) { - // In the definition files the number matching rules which are more restrictive should - // appear before the rules which are least resctritive. Although this happens in general - // there is at least one case where this is not strictly followed for existent definition - // files (specifically, HlCHex comes before HlCOct). So the condition below. - const int offset = progress->offset(); - if (offset < length && (text.at(offset) == kX || text.at(offset).toLower() == kX)) { - progress->restoreOffset(); - return false; - } - - charPredicateMatchSucceed(text, length, progress, &isOctalDigit); - return true; - } - - return false; -} - -// CHex -bool HlCHexRule::doMatchSucceed(const QString &text, - const int length, - ProgressData *progress) -{ - if (matchCharacter(text, length, progress, kZero)) { - const int offset = progress->offset(); - if (offset < length && text.at(offset) != kX && text.at(offset).toLower() != kX) { - progress->restoreOffset(); - return false; - } - - progress->incrementOffset(); - if (charPredicateMatchSucceed(text, length, progress, &isHexDigit)) - return true; - else - progress->restoreOffset(); - } - - return false; -} - -// CString -bool HlCStringCharRule::doMatchSucceed(const QString &text, - const int length, - ProgressData *progress) -{ - if (matchEscapeSequence(text, length, progress)) - return true; - - if (matchOctalSequence(text, length, progress)) - return true; - - if (matchHexSequence(text, length, progress)) - return true; - - return false; -} - -// CChar -bool HlCCharRule::doMatchSucceed(const QString &text, - const int length, - ProgressData *progress) -{ - if (matchCharacter(text, length, progress, kSingleQuote)) { - if (progress->offset() < length) { - if (text.at(progress->offset()) != kBackSlash && - text.at(progress->offset()) != kSingleQuote) { - progress->incrementOffset(); - } else if (!matchEscapeSequence(text, length, progress, false)) { - progress->restoreOffset(); - return false; - } - - if (progress->offset() < length && - matchCharacter(text, length, progress, kSingleQuote, false)) { - return true; - } else { - progress->restoreOffset(); - } - } else { - progress->restoreOffset(); - } - } - - return false; -} - -// RangeDetect -void RangeDetectRule::setChar(const QString &character) -{ setStartCharacter(&m_char, character); } - -void RangeDetectRule::setChar1(const QString &character) -{ setStartCharacter(&m_char1, character); } - -bool RangeDetectRule::doMatchSucceed(const QString &text, - const int length, - ProgressData *progress) -{ - if (matchCharacter(text, length, progress, m_char)) { - while (progress->offset() < length) { - if (matchCharacter(text, length, progress, m_char1, false)) - return true; - progress->incrementOffset(); - } - progress->restoreOffset(); - } - - return false; -} - -// LineContinue -bool LineContinueRule::doMatchSucceed(const QString &text, - const int length, - ProgressData *progress) -{ - if (progress->offset() != length - 1) - return false; - - if (text.at(progress->offset()) == kBackSlash) { - progress->incrementOffset(); - progress->setWillContinueLine(true); - return true; - } - - return false; -} - -// DetectSpaces -DetectSpacesRule::DetectSpacesRule() : Rule(false) -{} - -bool DetectSpacesRule::doMatchSucceed(const QString &text, - const int length, - ProgressData *progress) -{ - return charPredicateMatchSucceed(text, length, progress, &QChar::isSpace); -} - -// DetectIdentifier -bool DetectIdentifierRule::doMatchSucceed(const QString &text, - const int length, - ProgressData *progress) -{ - // Identifiers are characterized by a letter or underscore as the first character and then - // zero or more word characters (\w*). - if (text.at(progress->offset()).isLetter() || text.at(progress->offset()) == kUnderscore) { - progress->incrementOffset(); - while (progress->offset() < length) { - const QChar ¤t = text.at(progress->offset()); - if (current.isLetterOrNumber() || current.isMark() || current == kUnderscore) - progress->incrementOffset(); - else - break; - } - return true; - } - return false; -} diff --git a/src/plugins/texteditor/generichighlighter/specificrules.h b/src/plugins/texteditor/generichighlighter/specificrules.h deleted file mode 100644 index 00c9cea816..0000000000 --- a/src/plugins/texteditor/generichighlighter/specificrules.h +++ /dev/null @@ -1,265 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include "rule.h" -#include "dynamicrule.h" - -#include <QChar> -#include <QStringList> -#include <QRegExp> -#include <QSharedPointer> - -namespace TextEditor { -namespace Internal { - -class KeywordList; -class HighlightDefinition; - -class DetectCharRule : public DynamicRule -{ -public: - ~DetectCharRule() override = default; - - void setChar(const QString &character); - -private: - bool doMatchSucceed(const QString &text, const int length, ProgressData *progress) override; - DetectCharRule *doClone() const override { return new DetectCharRule(*this); } - void doReplaceExpressions(const QStringList &captures) override; - - QChar m_char; -}; - -class Detect2CharsRule : public DynamicRule -{ -public: - ~Detect2CharsRule() override = default; - - void setChar(const QString &character); - void setChar1(const QString &character); - -private: - bool doMatchSucceed(const QString &text, const int length, ProgressData *progress) override; - Detect2CharsRule *doClone() const override { return new Detect2CharsRule(*this); } - void doReplaceExpressions(const QStringList &captures) override; - - QChar m_char; - QChar m_char1; -}; - -class AnyCharRule : public Rule -{ -public: - ~AnyCharRule() override = default; - - void setCharacterSet(const QString &s); - -private: - bool doMatchSucceed(const QString &text, const int length, ProgressData *progress) override; - AnyCharRule *doClone() const override { return new AnyCharRule(*this); } - - QString m_characterSet; -}; - -class StringDetectRule : public DynamicRule -{ -public: - ~StringDetectRule() override = default; - - void setString(const QString &s); - void setInsensitive(const QString &insensitive); - -protected: - bool doMatchSucceed(const QString &text, const int length, ProgressData *progress) override; - StringDetectRule *doClone() const override { return new StringDetectRule(*this); } - void doReplaceExpressions(const QStringList &captures) override; - - QString m_string; - int m_length = 0; - Qt::CaseSensitivity m_caseSensitivity = Qt::CaseSensitive; -}; - -class WordDetectRule : public StringDetectRule -{ -private: - bool doMatchSucceed(const QString &text, const int length, ProgressData *progress) override; - WordDetectRule *doClone() const override { return new WordDetectRule(*this); } -}; - -class RegExprRule : public DynamicRule -{ -public: - ~RegExprRule() override; - - void setPattern(const QString &pattern); - void setInsensitive(const QString &insensitive); - void setMinimal(const QString &minimal); - -private: - bool doMatchSucceed(const QString &text, const int length, ProgressData *progress) override; - RegExprRule *doClone() const override; - void doReplaceExpressions(const QStringList &captures) override; - void doProgressFinished() override; - - bool isExactMatch(ProgressData *progress); - - bool m_onlyBegin = false; - bool m_isCached = false; - int m_offset = 0; - int m_length = 0; - QStringList m_captures; - QRegExp m_expression; - ProgressData *m_progress = nullptr; -}; - -class KeywordRule : public Rule -{ -public: - KeywordRule(const QSharedPointer<HighlightDefinition> &definition); - ~KeywordRule() override; - - void setInsensitive(const QString &insensitive); - void setList(const QString &listName); - -private: - bool doMatchSucceed(const QString &text, const int length, ProgressData *progress) override; - KeywordRule *doClone() const override { return new KeywordRule(*this); } - - bool m_overrideGlobal; - Qt::CaseSensitivity m_localCaseSensitivity; - QSharedPointer<KeywordList> m_list; -}; - -class IntRule : public Rule -{ -public: - ~IntRule() override = default; - -private: - bool doMatchSucceed(const QString &text, const int length, ProgressData *progress) override; - IntRule *doClone() const override { return new IntRule(*this); } -}; - -class FloatRule : public Rule -{ -public: - ~FloatRule() override = default; - -private: - bool doMatchSucceed(const QString &text, const int length, ProgressData *progress) override; - FloatRule *doClone() const override { return new FloatRule(*this); } -}; - -class HlCOctRule : public Rule -{ -public: - ~HlCOctRule() override = default; - -private: - bool doMatchSucceed(const QString &text, const int length, ProgressData *progress) override; - HlCOctRule *doClone() const override { return new HlCOctRule(*this); } -}; - -class HlCHexRule : public Rule -{ -public: - ~HlCHexRule() override = default; - -private: - bool doMatchSucceed(const QString &text, const int length, ProgressData *progress) override; - HlCHexRule *doClone() const override { return new HlCHexRule(*this); } -}; - -class HlCStringCharRule : public Rule -{ -public: - ~HlCStringCharRule() override = default; - -private: - bool doMatchSucceed(const QString &text, const int length, ProgressData *progress) override; - HlCStringCharRule *doClone() const override { return new HlCStringCharRule(*this); } -}; - -class HlCCharRule : public Rule -{ -public: - ~HlCCharRule() override = default; - -private: - bool doMatchSucceed(const QString &text, const int length, ProgressData *progress) override; - HlCCharRule *doClone() const override { return new HlCCharRule(*this); } -}; - -class RangeDetectRule : public Rule -{ -public: - ~RangeDetectRule() override = default; - - void setChar(const QString &character); - void setChar1(const QString &character); - -private: - bool doMatchSucceed(const QString &text, const int length, ProgressData *progress) override; - RangeDetectRule *doClone() const override { return new RangeDetectRule(*this); } - - QChar m_char; - QChar m_char1; -}; - -class LineContinueRule : public Rule -{ -public: - ~LineContinueRule() override = default; - -private: - bool doMatchSucceed(const QString &text, const int length, ProgressData *progress) override; - LineContinueRule *doClone() const override { return new LineContinueRule(*this); } -}; - -class DetectSpacesRule : public Rule -{ -public: - DetectSpacesRule(); - ~DetectSpacesRule() override = default; - -private: - bool doMatchSucceed(const QString &text, const int length, ProgressData *progress) override; - DetectSpacesRule *doClone() const override { return new DetectSpacesRule(*this); } -}; - -class DetectIdentifierRule : public Rule -{ -public: - ~DetectIdentifierRule() override = default; - -private: - bool doMatchSucceed(const QString &text, const int length, ProgressData *progress) override; - DetectIdentifierRule *doClone() const override { return new DetectIdentifierRule(*this); } -}; - -} // namespace Internal -} // namespace TextEditor diff --git a/src/plugins/texteditor/highlighter.cpp b/src/plugins/texteditor/highlighter.cpp new file mode 100644 index 0000000000..170ec12bc8 --- /dev/null +++ b/src/plugins/texteditor/highlighter.cpp @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "highlighter.h" + +#include "definitiondownloader.h" +#include "highlightersettings.h" +#include "textdocumentlayout.h" +#include "texteditorsettings.h" + +#include <coreplugin/icore.h> +#include <coreplugin/messagemanager.h> + +#include <Format> +#include <Repository> +#include <SyntaxHighlighter> + +#include <QDir> +#include <QMetaEnum> + +using namespace TextEditor; + +KSyntaxHighlighting::Repository *highlightRepository() +{ + static KSyntaxHighlighting::Repository *repository = nullptr; + if (!repository) { + repository = new KSyntaxHighlighting::Repository(); + repository->addCustomSearchPath(TextEditorSettings::highlighterSettings().definitionFilesPath()); + QDir dir(Core::ICore::resourcePath() + QLatin1String("/generic-highlighter/syntax")); + if (dir.exists() && dir.cdUp()) + repository->addCustomSearchPath(dir.path()); + } + return repository; +} + +TextStyle categoryForTextStyle(int style) +{ + switch (style) { + case KSyntaxHighlighting::Theme::Normal: return C_TEXT; + case KSyntaxHighlighting::Theme::Keyword: return C_KEYWORD; + case KSyntaxHighlighting::Theme::Function: return C_FUNCTION; + case KSyntaxHighlighting::Theme::Variable: return C_LOCAL; + case KSyntaxHighlighting::Theme::ControlFlow: return C_KEYWORD; + case KSyntaxHighlighting::Theme::Operator: return C_OPERATOR; + case KSyntaxHighlighting::Theme::BuiltIn: return C_PRIMITIVE_TYPE; + case KSyntaxHighlighting::Theme::Extension: return C_GLOBAL; + case KSyntaxHighlighting::Theme::Preprocessor: return C_PREPROCESSOR; + case KSyntaxHighlighting::Theme::Attribute: return C_LOCAL; + case KSyntaxHighlighting::Theme::Char: return C_STRING; + case KSyntaxHighlighting::Theme::SpecialChar: return C_STRING; + case KSyntaxHighlighting::Theme::String: return C_STRING; + case KSyntaxHighlighting::Theme::VerbatimString: return C_STRING; + case KSyntaxHighlighting::Theme::SpecialString: return C_STRING; + case KSyntaxHighlighting::Theme::Import: return C_PREPROCESSOR; + case KSyntaxHighlighting::Theme::DataType: return C_TYPE; + case KSyntaxHighlighting::Theme::DecVal: return C_NUMBER; + case KSyntaxHighlighting::Theme::BaseN: return C_NUMBER; + case KSyntaxHighlighting::Theme::Float: return C_NUMBER; + case KSyntaxHighlighting::Theme::Constant: return C_KEYWORD; + case KSyntaxHighlighting::Theme::Comment: return C_COMMENT; + case KSyntaxHighlighting::Theme::Documentation: return C_DOXYGEN_COMMENT; + case KSyntaxHighlighting::Theme::Annotation: return C_DOXYGEN_TAG; + case KSyntaxHighlighting::Theme::CommentVar: return C_DOXYGEN_TAG; + case KSyntaxHighlighting::Theme::RegionMarker: return C_PREPROCESSOR; + case KSyntaxHighlighting::Theme::Information: return C_WARNING; + case KSyntaxHighlighting::Theme::Warning: return C_WARNING; + case KSyntaxHighlighting::Theme::Alert: return C_ERROR; + case KSyntaxHighlighting::Theme::Error: return C_ERROR; + case KSyntaxHighlighting::Theme::Others: return C_TEXT; + } + return C_TEXT; +} + +Highlighter::Highlighter() +{ + setTextFormatCategories(QMetaEnum::fromType<KSyntaxHighlighting::Theme::TextStyle>().keyCount(), + &categoryForTextStyle); +} + +KSyntaxHighlighting::Definition Highlighter::definitionForMimeType(const QString &mimeType) +{ + return highlightRepository()->definitionForMimeType(mimeType); +} + +KSyntaxHighlighting::Definition Highlighter::definitionForFileName(const QString &fileName) +{ + return highlightRepository()->definitionForFileName(fileName); +} + +void Highlighter::addCustomHighlighterPath(const Utils::FileName &path) +{ + highlightRepository()->addCustomSearchPath(path.toString()); +} + +void Highlighter::updateDefinitions(std::function<void()> callback) { + auto downloader = + new KSyntaxHighlighting::DefinitionDownloader(highlightRepository()); + connect(downloader, &KSyntaxHighlighting::DefinitionDownloader::done, + [downloader, callback]() { + Core::MessageManager::write(tr("Highlighter updates: done"), + Core::MessageManager::ModeSwitch); + downloader->deleteLater(); + if (callback) + callback(); + }); + connect(downloader, + &KSyntaxHighlighting::DefinitionDownloader::informationMessage, + [](const QString &message) { + Core::MessageManager::write(tr("Highlighter updates:") + ' ' + + message, + Core::MessageManager::ModeSwitch); + }); + downloader->start(); +} + +void Highlighter::handleShutdown() +{ + delete highlightRepository(); +} + +void Highlighter::highlightBlock(const QString &text) +{ + if (!definition().isValid()) + return; + QTextBlock block = currentBlock(); + KSyntaxHighlighting::State state = TextDocumentLayout::userData(block)->syntaxState(); + state = highlightLine(text, state); + block = block.next(); + if (block.isValid()) + TextDocumentLayout::userData(block)->setSyntaxState(state); +} + +void Highlighter::applyFormat(int offset, int length, const KSyntaxHighlighting::Format &format) +{ + setFormat(offset, length, formatForCategory(format.textStyle())); +} diff --git a/src/plugins/texteditor/generichighlighter/dynamicrule.h b/src/plugins/texteditor/highlighter.h index 2c3d46bd8d..90ab31332a 100644 --- a/src/plugins/texteditor/generichighlighter/dynamicrule.h +++ b/src/plugins/texteditor/highlighter.h @@ -25,33 +25,32 @@ #pragma once -#include "rule.h" +#include "syntaxhighlighter.h" -QT_BEGIN_NAMESPACE -class QStringList; -QT_END_NAMESPACE +#include <utils/fileutils.h> + +#include <AbstractHighlighter> +#include <Definition> namespace TextEditor { -namespace Internal { +class FontSettings; -class DynamicRule : public Rule +class Highlighter : public SyntaxHighlighter, public KSyntaxHighlighting::AbstractHighlighter { public: - DynamicRule(); - ~DynamicRule() override; + Highlighter(); - void setActive(const QString &active); - bool isActive() const; + static KSyntaxHighlighting::Definition definitionForMimeType(const QString &mimeType); + static KSyntaxHighlighting::Definition definitionForFileName(const QString &fileName); - virtual void replaceExpressions(const QStringList &captures); + static void addCustomHighlighterPath(const Utils::FileName &path); + static void updateDefinitions(std::function<void()> callback = nullptr); -private: - virtual void doReplaceExpressions(const QStringList &captures) = 0; + static void handleShutdown(); - bool m_active; +protected: + void highlightBlock(const QString &text) override; + void applyFormat(int offset, int length, const KSyntaxHighlighting::Format &format) override; }; -void updateDynamicRules(const QList<QSharedPointer<Rule> > &rules, const QStringList &captures); - -} // namespace Internal } // namespace TextEditor diff --git a/src/plugins/texteditor/generichighlighter/highlightersettings.cpp b/src/plugins/texteditor/highlightersettings.cpp index f0a00d3bc8..76b88b063a 100644 --- a/src/plugins/texteditor/generichighlighter/highlightersettings.cpp +++ b/src/plugins/texteditor/highlightersettings.cpp @@ -96,8 +96,6 @@ QString findFallbackDefinitionsLocation() namespace { static const QLatin1String kDefinitionFilesPath("UserDefinitionFilesPath"); -static const QLatin1String kFallbackDefinitionFilesPath("FallbackDefinitionFilesPath"); -static const QLatin1String kUseFallbackLocation("UseFallbackLocation"); static const QLatin1String kIgnoredFilesPatterns("IgnoredFilesPatterns"); static const QLatin1String kGroupPostfix("HighlighterSettings"); @@ -113,17 +111,11 @@ QString groupSpecifier(const QString &postFix, const QString &category) using namespace TextEditor; using namespace Internal; -HighlighterSettings::HighlighterSettings() : - m_useFallbackLocation(true) -{} - void HighlighterSettings::toSettings(const QString &category, QSettings *s) const { const QString &group = groupSpecifier(kGroupPostfix, category); s->beginGroup(group); s->setValue(kDefinitionFilesPath, m_definitionFilesPath); - s->setValue(kFallbackDefinitionFilesPath, m_fallbackDefinitionFilesPath); - s->setValue(kUseFallbackLocation, m_useFallbackLocation); s->setValue(kIgnoredFilesPatterns, ignoredFilesPatterns()); s->endGroup(); } @@ -137,16 +129,6 @@ void HighlighterSettings::fromSettings(const QString &category, QSettings *s) assignDefaultDefinitionsPath(); else m_definitionFilesPath = s->value(kDefinitionFilesPath).toString(); - if (!s->contains(kFallbackDefinitionFilesPath)) { - m_fallbackDefinitionFilesPath = findFallbackDefinitionsLocation(); - if (m_fallbackDefinitionFilesPath.isEmpty()) - m_useFallbackLocation = false; - else - m_useFallbackLocation = true; - } else { - m_fallbackDefinitionFilesPath = s->value(kFallbackDefinitionFilesPath).toString(); - m_useFallbackLocation = s->value(kUseFallbackLocation, true).toBool(); - } if (!s->contains(kIgnoredFilesPatterns)) assignDefaultIgnoredPatterns(); else @@ -187,7 +169,7 @@ void HighlighterSettings::assignDefaultDefinitionsPath() bool HighlighterSettings::isIgnoredFilePattern(const QString &fileName) const { - for (auto ®Exp : m_ignoredFiles) + for (const QRegExp ®Exp : m_ignoredFiles) if (regExp.indexIn(fileName) != -1) return true; @@ -197,8 +179,6 @@ bool HighlighterSettings::isIgnoredFilePattern(const QString &fileName) const bool HighlighterSettings::equals(const HighlighterSettings &highlighterSettings) const { return m_definitionFilesPath == highlighterSettings.m_definitionFilesPath && - m_fallbackDefinitionFilesPath == highlighterSettings.m_fallbackDefinitionFilesPath && - m_useFallbackLocation == highlighterSettings.m_useFallbackLocation && m_ignoredFiles == highlighterSettings.m_ignoredFiles; } @@ -208,7 +188,7 @@ void HighlighterSettings::setExpressionsFromList(const QStringList &patterns) QRegExp regExp; regExp.setCaseSensitivity(Qt::CaseInsensitive); regExp.setPatternSyntax(QRegExp::Wildcard); - for (auto &pattern : patterns) { + for (const QString &pattern : patterns) { regExp.setPattern(pattern); m_ignoredFiles.append(regExp); } @@ -217,7 +197,7 @@ void HighlighterSettings::setExpressionsFromList(const QStringList &patterns) QStringList HighlighterSettings::listFromExpressions() const { QStringList patterns; - foreach (const QRegExp ®Exp, m_ignoredFiles) + for (const QRegExp ®Exp : m_ignoredFiles) patterns.append(regExp.pattern()); return patterns; } diff --git a/src/plugins/texteditor/generichighlighter/highlightersettings.h b/src/plugins/texteditor/highlightersettings.h index 3323b5bd39..16d2eab318 100644 --- a/src/plugins/texteditor/generichighlighter/highlightersettings.h +++ b/src/plugins/texteditor/highlightersettings.h @@ -39,7 +39,7 @@ namespace TextEditor { class HighlighterSettings { public: - HighlighterSettings(); + HighlighterSettings() = default; void toSettings(const QString &category, QSettings *s) const; void fromSettings(const QString &category, QSettings *s); @@ -47,12 +47,6 @@ public: void setDefinitionFilesPath(const QString &path) { m_definitionFilesPath = path; } const QString &definitionFilesPath() const { return m_definitionFilesPath; } - void setFallbackDefinitionFilesPath(const QString &path){ m_fallbackDefinitionFilesPath = path;} - const QString &fallbackDefinitionFilesPath() const { return m_fallbackDefinitionFilesPath; } - - void setUseFallbackLocation(const bool use) { m_useFallbackLocation = use; } - bool useFallbackLocation() const { return m_useFallbackLocation; } - void setIgnoredFilesPatterns(const QString &patterns); QString ignoredFilesPatterns() const; bool isIgnoredFilePattern(const QString &fileName) const; @@ -66,9 +60,7 @@ private: void setExpressionsFromList(const QStringList &patterns); QStringList listFromExpressions() const; - bool m_useFallbackLocation; QString m_definitionFilesPath; - QString m_fallbackDefinitionFilesPath; QList<QRegExp> m_ignoredFiles; }; diff --git a/src/plugins/texteditor/highlightersettingspage.cpp b/src/plugins/texteditor/highlightersettingspage.cpp new file mode 100644 index 0000000000..ec9d34ee65 --- /dev/null +++ b/src/plugins/texteditor/highlightersettingspage.cpp @@ -0,0 +1,164 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "highlightersettingspage.h" +#include "highlightersettings.h" +#include "highlighter.h" +#include "ui_highlightersettingspage.h" + +#include <coreplugin/icore.h> + +#include <QDir> +#include <QMessageBox> +#include <QPointer> + +using namespace TextEditor; +using namespace Internal; + +struct HighlighterSettingsPage::HighlighterSettingsPagePrivate +{ + explicit HighlighterSettingsPagePrivate(Core::Id id); + void ensureInitialized(); + void migrateGenericHighlighterFiles(); + + bool m_initialized = false; + const Core::Id m_id; + const QString m_displayName; + const QString m_settingsPrefix; + + HighlighterSettings m_settings; + + QPointer<QWidget> m_widget; + Ui::HighlighterSettingsPage *m_page = nullptr; +}; + +HighlighterSettingsPage::HighlighterSettingsPagePrivate:: +HighlighterSettingsPagePrivate(Core::Id id) + : m_id(id) + , m_displayName(tr("Generic Highlighter")) + , m_settingsPrefix("Text") +{} + +void HighlighterSettingsPage::HighlighterSettingsPagePrivate::migrateGenericHighlighterFiles() +{ + QDir userDefinitionPath(m_settings.definitionFilesPath()); + if (userDefinitionPath.mkdir("syntax")) { + const auto link = Utils::HostOsInfo::isAnyUnixHost() + ? QOverload<const QString &, const QString &>::of(&QFile::link) + : QOverload<const QString &, const QString &>::of(&QFile::copy); + + for (const QFileInfo &file : userDefinitionPath.entryInfoList({"*.xml"}, QDir::Files)) + link(file.filePath(), file.absolutePath() + "/syntax/" + file.fileName()); + } +} + +void HighlighterSettingsPage::HighlighterSettingsPagePrivate::ensureInitialized() +{ + if (m_initialized) + return; + m_initialized = true; + m_settings.fromSettings(m_settingsPrefix, Core::ICore::settings()); + migrateGenericHighlighterFiles(); +} + +HighlighterSettingsPage::HighlighterSettingsPage(Core::Id id, QObject *parent) : + TextEditorOptionsPage(parent), + m_d(new HighlighterSettingsPagePrivate(id)) +{ + setId(m_d->m_id); + setDisplayName(m_d->m_displayName); +} + +HighlighterSettingsPage::~HighlighterSettingsPage() +{ + delete m_d; +} + +QWidget *HighlighterSettingsPage::widget() +{ + if (!m_d->m_widget) { + m_d->m_widget = new QWidget; + m_d->m_page = new Ui::HighlighterSettingsPage; + m_d->m_page->setupUi(m_d->m_widget); + m_d->m_page->definitionFilesPath->setExpectedKind(Utils::PathChooser::ExistingDirectory); + m_d->m_page->definitionFilesPath->setHistoryCompleter(QLatin1String("TextEditor.Highlighter.History")); + connect(m_d->m_page->updateDefinitions, + &QPushButton::pressed, + [label = QPointer<QLabel>(m_d->m_page->updateStatus)]() { + Highlighter::updateDefinitions([label](){ + if (label) + label->setText(tr("Update finished")); + }); + }); + + settingsToUI(); + } + return m_d->m_widget; +} + +void HighlighterSettingsPage::apply() +{ + if (!m_d->m_page) // page was not shown + return; + if (settingsChanged()) + settingsFromUI(); +} + +void HighlighterSettingsPage::finish() +{ + delete m_d->m_widget; + if (!m_d->m_page) // page was not shown + return; + delete m_d->m_page; + m_d->m_page = nullptr; +} + +const HighlighterSettings &HighlighterSettingsPage::highlighterSettings() const +{ + m_d->ensureInitialized(); + return m_d->m_settings; +} + +void HighlighterSettingsPage::settingsFromUI() +{ + m_d->ensureInitialized(); + m_d->m_settings.setDefinitionFilesPath(m_d->m_page->definitionFilesPath->path()); + m_d->m_settings.setIgnoredFilesPatterns(m_d->m_page->ignoreEdit->text()); + m_d->m_settings.toSettings(m_d->m_settingsPrefix, Core::ICore::settings()); +} + +void HighlighterSettingsPage::settingsToUI() +{ + m_d->ensureInitialized(); + m_d->m_page->definitionFilesPath->setPath(m_d->m_settings.definitionFilesPath()); + m_d->m_page->ignoreEdit->setText(m_d->m_settings.ignoredFilesPatterns()); +} + +bool HighlighterSettingsPage::settingsChanged() const +{ + m_d->ensureInitialized(); + return (m_d->m_settings.definitionFilesPath() != m_d->m_page->definitionFilesPath->path()) + || (m_d->m_settings.ignoredFilesPatterns() != m_d->m_page->ignoreEdit->text()); +} diff --git a/src/plugins/texteditor/generichighlighter/highlightersettingspage.h b/src/plugins/texteditor/highlightersettingspage.h index 86831876f9..5391016fbb 100644 --- a/src/plugins/texteditor/generichighlighter/highlightersettingspage.h +++ b/src/plugins/texteditor/highlightersettingspage.h @@ -25,8 +25,7 @@ #pragma once -#include "highlightdefinitionmetadata.h" -#include "../texteditoroptionspage.h" +#include "texteditoroptionspage.h" QT_BEGIN_NAMESPACE template <class> class QList; @@ -51,21 +50,11 @@ public: const HighlighterSettings &highlighterSettings() const; private: - void manageDefinitions(const QList<Internal::DefinitionMetaDataPtr> &metaData); - void showError(); - void ignoreDownloadReply(); - void setFallbackLocationState(bool checked); - void setDownloadDefinitionsState(bool valid); - - void resetDefinitionsLocation(); - void requestAvailableDefinitionsMetaData(); void settingsFromUI(); void settingsToUI(); bool settingsChanged() const; - bool m_requestHighlightFileRegistration; - struct HighlighterSettingsPagePrivate; HighlighterSettingsPagePrivate *m_d; }; diff --git a/src/plugins/texteditor/generichighlighter/highlightersettingspage.ui b/src/plugins/texteditor/highlightersettingspage.ui index 1861515176..bcc5d5fe11 100644 --- a/src/plugins/texteditor/generichighlighter/highlightersettingspage.ui +++ b/src/plugins/texteditor/highlightersettingspage.ui @@ -23,8 +23,7 @@ </sizepolicy> </property> <property name="text"> - <string><html><head/><body> -<p>Highlight definitions are provided by the <a href="http://kate-editor.org/">Kate Text Editor</a>.</p></body></html></string> + <string><html><head/><body><p>Highlight definitions are provided by the <a href="https://api.kde.org/frameworks/syntax-highlighting/html/index.html">KSyntaxHighlighting</a> engine.</p></body></html></string> </property> <property name="textFormat"> <enum>Qt::RichText</enum> @@ -63,13 +62,44 @@ </property> <layout class="QVBoxLayout" name="verticalLayout_3"> <item> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <widget class="QPushButton" name="updateDefinitions"> + <property name="text"> + <string>Update Definitions</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="updateStatus"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> <layout class="QHBoxLayout" name="horizontalLayout_3"> <item> <layout class="QHBoxLayout" name="horizontalLayout"> <item> <widget class="QLabel" name="locationLabel"> <property name="text"> - <string>Location:</string> + <string>User Highlight Definition Files</string> </property> </widget> </item> @@ -80,48 +110,22 @@ </item> </layout> </item> - <item> - <layout class="QVBoxLayout" name="verticalLayout"> - <property name="spacing"> - <number>0</number> - </property> - <item> - <widget class="QCheckBox" name="useFallbackLocation"> - <property name="text"> - <string>Use fallback location</string> - </property> - </widget> - </item> - <item> - <widget class="Utils::PathChooser" name="fallbackDefinitionFilesPath" native="true"/> - </item> - </layout> - </item> </layout> </widget> </item> <item> - <widget class="QGroupBox" name="behaviorGroupBox"> - <property name="title"> - <string>Behavior</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="QLabel" name="ignoreLabel"> - <property name="text"> - <string>Ignored file patterns:</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="ignoreEdit"/> - </item> - </layout> - </item> - </layout> - </widget> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="ignoreLabel"> + <property name="text"> + <string>Ignored file patterns:</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="ignoreEdit"/> + </item> + </layout> </item> <item> <spacer name="verticalSpacer"> @@ -151,7 +155,6 @@ </customwidget> </customwidgets> <tabstops> - <tabstop>useFallbackLocation</tabstop> <tabstop>ignoreEdit</tabstop> </tabstops> <resources/> diff --git a/src/plugins/texteditor/highlighterutils.cpp b/src/plugins/texteditor/highlighterutils.cpp deleted file mode 100644 index 9b7332823b..0000000000 --- a/src/plugins/texteditor/highlighterutils.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "highlighterutils.h" -#include "generichighlighter/highlighter.h" -#include "generichighlighter/highlightdefinition.h" -#include "generichighlighter/manager.h" -#include <coreplugin/icore.h> -#include <utils/mimetypes/mimetype.h> - -using namespace TextEditor; -using namespace Internal; - -void TextEditor::setMimeTypeForHighlighter(Highlighter *highlighter, const Utils::MimeType &mimeType, - const QString &filePath, QString *foundDefinitionId) -{ - QString definitionId = Manager::instance()->definitionIdByMimeTypeAndFile(mimeType, filePath); - if (!definitionId.isEmpty()) { - const QSharedPointer<HighlightDefinition> &definition = - Manager::instance()->definition(definitionId); - if (!definition.isNull() && definition->isValid()) - highlighter->setDefaultContext(definition->initialContext()); - } - - if (foundDefinitionId) - *foundDefinitionId = definitionId; -} - diff --git a/src/plugins/texteditor/highlighterutils.h b/src/plugins/texteditor/highlighterutils.h deleted file mode 100644 index 57b62c0712..0000000000 --- a/src/plugins/texteditor/highlighterutils.h +++ /dev/null @@ -1,45 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include <QString> -#include "texteditor_global.h" - -/* These functions were originally a part of TextEditor::Highlighter, - * but due to a very hackish test of that generic highlighter, - * there functions must be outside. */ - -namespace Utils { class MimeType; } - -namespace TextEditor { - -class Highlighter; - -void setMimeTypeForHighlighter(Highlighter *highlighter, const Utils::MimeType &mimeType, - const QString &filePath, - QString *foundDefinitionId = nullptr); - -} // namespace TextEditor diff --git a/src/plugins/texteditor/snippets/snippetprovider.cpp b/src/plugins/texteditor/snippets/snippetprovider.cpp index 0d5caa5229..be84ef8bdb 100644 --- a/src/plugins/texteditor/snippets/snippetprovider.cpp +++ b/src/plugins/texteditor/snippets/snippetprovider.cpp @@ -25,7 +25,7 @@ #include "snippetprovider.h" -#include "texteditorplugin.h" +#include <texteditor/texteditorplugin.h> #include <utils/algorithm.h> diff --git a/src/plugins/texteditor/snippets/snippetssettingspage.cpp b/src/plugins/texteditor/snippets/snippetssettingspage.cpp index 6b947c4375..32daaa503b 100644 --- a/src/plugins/texteditor/snippets/snippetssettingspage.cpp +++ b/src/plugins/texteditor/snippets/snippetssettingspage.cpp @@ -29,10 +29,10 @@ #include "snippet.h" #include "snippetscollection.h" #include "snippetssettings.h" -#include "textdocument.h" #include "ui_snippetssettingspage.h" #include <coreplugin/icore.h> +#include <texteditor/textdocument.h> #include <texteditor/texteditorconstants.h> #include <texteditor/texteditorsettings.h> #include <extensionsystem/pluginmanager.h> diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp index ef504447a5..352c609143 100644 --- a/src/plugins/texteditor/textdocument.cpp +++ b/src/plugins/texteditor/textdocument.cpp @@ -35,7 +35,6 @@ #include "texteditor.h" #include "texteditorconstants.h" #include "typingsettings.h" -#include <texteditor/generichighlighter/highlighter.h> #include <coreplugin/diffservice.h> #include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/documentmodel.h> @@ -340,9 +339,6 @@ void TextDocument::setTabSettings(const TabSettings &newTabSettings) return; d->m_tabSettings = newTabSettings; - if (auto highlighter = qobject_cast<Highlighter *>(d->m_highlighter)) - highlighter->setTabSettings(tabSettings()); - emit tabSettingsChanged(); } diff --git a/src/plugins/texteditor/textdocumentlayout.h b/src/plugins/texteditor/textdocumentlayout.h index f436b30d03..119dcb7e2c 100644 --- a/src/plugins/texteditor/textdocumentlayout.h +++ b/src/plugins/texteditor/textdocumentlayout.h @@ -30,6 +30,8 @@ #include "textmark.h" #include "textdocument.h" +#include <State> + #include <QTextBlockUserData> #include <QPlainTextDocumentLayout> @@ -133,6 +135,9 @@ public: CodeFormatterData *codeFormatterData() const { return m_codeFormatterData; } void setCodeFormatterData(CodeFormatterData *data); + KSyntaxHighlighting::State syntaxState() { return m_syntaxState; } + void setSyntaxState(KSyntaxHighlighting::State state) { m_syntaxState = state; } + private: TextMarks m_marks; int m_foldingIndent : 16; @@ -144,6 +149,7 @@ private: int m_additionalAnnotationHeight = 0; Parentheses m_parentheses; CodeFormatterData *m_codeFormatterData; + KSyntaxHighlighting::State m_syntaxState; }; diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index 96cf099c5e..aed04a3ba7 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -37,31 +37,27 @@ #include "circularclipboardassist.h" #include "codecselector.h" #include "completionsettings.h" -#include "highlighterutils.h" +#include "extraencodingsettings.h" +#include "highlighter.h" +#include "highlightersettings.h" #include "icodestylepreferences.h" #include "indenter.h" +#include "refactoroverlay.h" #include "snippets/snippet.h" +#include "storagesettings.h" #include "syntaxhighlighter.h" #include "tabsettings.h" #include "textdocument.h" #include "textdocumentlayout.h" #include "texteditorconstants.h" #include "texteditoroverlay.h" -#include "refactoroverlay.h" #include "texteditorsettings.h" #include "typingsettings.h" -#include "extraencodingsettings.h" -#include "storagesettings.h" #include <texteditor/codeassist/assistinterface.h> #include <texteditor/codeassist/codeassistant.h> #include <texteditor/codeassist/completionassistprovider.h> #include <texteditor/codeassist/documentcontentcompletion.h> -#include <texteditor/generichighlighter/context.h> -#include <texteditor/generichighlighter/highlightdefinition.h> -#include <texteditor/generichighlighter/highlighter.h> -#include <texteditor/generichighlighter/highlightersettings.h> -#include <texteditor/generichighlighter/manager.h> #include <coreplugin/icore.h> #include <aggregation/aggregate.h> @@ -94,6 +90,7 @@ #include <QClipboard> #include <QCoreApplication> #include <QDebug> +#include <QFutureWatcher> #include <QGridLayout> #include <QKeyEvent> #include <QMap> @@ -847,17 +844,21 @@ TextEditorWidgetPrivate::~TextEditorWidgetPrivate() */ static void updateEditorInfoBar(TextEditorWidget *widget) { - Id infoSyntaxDefinition(Constants::INFO_SYNTAX_DEFINITION); + Id id(Constants::INFO_SYNTAX_DEFINITION); InfoBar *infoBar = widget->textDocument()->infoBar(); if (!widget->isMissingSyntaxDefinition()) { - infoBar->removeInfo(infoSyntaxDefinition); - } else if (infoBar->canInfoBeAdded(infoSyntaxDefinition)) { - InfoBarEntry info(infoSyntaxDefinition, + infoBar->removeInfo(id); + } else if (infoBar->canInfoBeAdded(id)) { + InfoBarEntry info(id, BaseTextEditor::tr("A highlight definition was not found for this file. " - "Would you like to try to find one?"), + "Would you like to update highlight definition files?"), InfoBarEntry::GlobalSuppressionEnabled); - info.setCustomButtonInfo(BaseTextEditor::tr("Show Highlighter Options..."), [widget]() { - ICore::showOptionsDialog(Constants::TEXT_EDITOR_HIGHLIGHTER_SETTINGS, widget); + info.setCustomButtonInfo(BaseTextEditor::tr("Update Definitions"), [id, widget]() { + widget->textDocument()->infoBar()->removeInfo(id); + Highlighter::updateDefinitions([widget = QPointer<TextEditorWidget>(widget)]() { + if (widget) + widget->configureGenericHighlighter(); + }); }); infoBar->addInfo(info); @@ -8463,37 +8464,30 @@ QString TextEditorWidget::textAt(int from, int to) const void TextEditorWidget::configureGenericHighlighter() { auto highlighter = new Highlighter(); - highlighter->setTabSettings(textDocument()->tabSettings()); textDocument()->setSyntaxHighlighter(highlighter); setCodeFoldingSupported(false); const QString type = textDocument()->mimeType(); const MimeType mimeType = Utils::mimeTypeForName(type); - if (mimeType.isValid()) { - d->m_isMissingSyntaxDefinition = true; - - QString definitionId; - setMimeTypeForHighlighter(highlighter, mimeType, textDocument()->filePath().toString(), - &definitionId); - - if (!definitionId.isEmpty()) { - d->m_isMissingSyntaxDefinition = false; - const QSharedPointer<HighlightDefinition> &definition = - Manager::instance()->definition(definitionId); - if (!definition.isNull() && definition->isValid()) { - d->m_commentDefinition.isAfterWhiteSpaces = definition->isCommentAfterWhiteSpaces(); - d->m_commentDefinition.singleLine = definition->singleLineComment(); - d->m_commentDefinition.multiLineStart = definition->multiLineCommentStart(); - d->m_commentDefinition.multiLineEnd = definition->multiLineCommentEnd(); - - setCodeFoldingSupported(true); - } - } else { - const QString fileName = textDocument()->filePath().toString(); - if (TextEditorSettings::highlighterSettings().isIgnoredFilePattern(fileName)) - d->m_isMissingSyntaxDefinition = false; - } + const QString fileName = textDocument()->filePath().fileName(); + KSyntaxHighlighting::Definition definition; + if (mimeType.isValid()) + definition = Highlighter::definitionForMimeType(mimeType.name()); + if (!definition.isValid()) + definition = Highlighter::definitionForFileName(fileName); + + if (definition.isValid()) { + highlighter->setDefinition(definition); + d->m_isMissingSyntaxDefinition = false; + d->m_commentDefinition.singleLine = definition.singleLineCommentMarker(); + d->m_commentDefinition.multiLineStart = definition.multiLineCommentMarker().first; + d->m_commentDefinition.multiLineEnd = definition.multiLineCommentMarker().second; + + setCodeFoldingSupported(true); + } else { + d->m_isMissingSyntaxDefinition = + !TextEditorSettings::highlighterSettings().isIgnoredFilePattern(fileName); } textDocument()->setFontSettings(TextEditorSettings::fontSettings()); @@ -8546,9 +8540,6 @@ void TextEditorWidget::setupGenericHighlighter() connect(textDocument(), &IDocument::filePathChanged, d, &TextEditorWidgetPrivate::reconfigure); - connect(Manager::instance(), &Manager::highlightingFilesRegistered, - d, &TextEditorWidgetPrivate::reconfigure); - updateEditorInfoBar(this); } diff --git a/src/plugins/texteditor/texteditor.pro b/src/plugins/texteditor/texteditor.pro index 6de9e93469..d5bf895ee4 100644 --- a/src/plugins/texteditor/texteditor.pro +++ b/src/plugins/texteditor/texteditor.pro @@ -34,23 +34,9 @@ SOURCES += texteditorplugin.cpp \ textindenter.cpp \ quickfix.cpp \ syntaxhighlighter.cpp \ - highlighterutils.cpp \ - generichighlighter/itemdata.cpp \ - generichighlighter/specificrules.cpp \ - generichighlighter/rule.cpp \ - generichighlighter/dynamicrule.cpp \ - generichighlighter/context.cpp \ - generichighlighter/includerulesinstruction.cpp \ - generichighlighter/progressdata.cpp \ - generichighlighter/keywordlist.cpp \ - generichighlighter/highlightdefinition.cpp \ - generichighlighter/highlighter.cpp \ - generichighlighter/manager.cpp \ - generichighlighter/highlightdefinitionhandler.cpp \ - generichighlighter/highlightersettingspage.cpp \ - generichighlighter/highlightersettings.cpp \ - generichighlighter/managedefinitionsdialog.cpp \ - generichighlighter/definitiondownloader.cpp \ + highlighter.cpp \ + highlightersettings.cpp \ + highlightersettingspage.cpp \ refactoringchanges.cpp \ refactoroverlay.cpp \ outlinefactory.cpp \ @@ -137,27 +123,9 @@ HEADERS += texteditorplugin.h \ textindenter.h \ quickfix.h \ syntaxhighlighter.h \ - highlighterutils.h \ - generichighlighter/reuse.h \ - generichighlighter/itemdata.h \ - generichighlighter/specificrules.h \ - generichighlighter/rule.h \ - generichighlighter/reuse.h \ - generichighlighter/dynamicrule.h \ - generichighlighter/context.h \ - generichighlighter/includerulesinstruction.h \ - generichighlighter/progressdata.h \ - generichighlighter/keywordlist.h \ - generichighlighter/highlighterexception.h \ - generichighlighter/highlightdefinition.h \ - generichighlighter/highlighter.h \ - generichighlighter/manager.h \ - generichighlighter/highlightdefinitionhandler.h \ - generichighlighter/highlightersettingspage.h \ - generichighlighter/highlightersettings.h \ - generichighlighter/managedefinitionsdialog.h \ - generichighlighter/highlightdefinitionmetadata.h \ - generichighlighter/definitiondownloader.h \ + highlighter.h \ + highlightersettings.h \ + highlightersettingspage.h \ refactoringchanges.h \ refactoroverlay.h \ outlinefactory.h \ @@ -223,14 +191,14 @@ FORMS += \ displaysettingspage.ui \ fontsettingspage.ui \ colorschemeedit.ui \ - generichighlighter/highlightersettingspage.ui \ - generichighlighter/managedefinitionsdialog.ui \ snippets/snippetssettingspage.ui \ behaviorsettingswidget.ui \ behaviorsettingspage.ui \ tabsettingswidget.ui \ completionsettingspage.ui \ - codestyleselectorwidget.ui + codestyleselectorwidget.ui \ + highlightersettingspage.ui + RESOURCES += texteditor.qrc equals(TEST, 1) { diff --git a/src/plugins/texteditor/texteditor.qbs b/src/plugins/texteditor/texteditor.qbs index 1e8b4c5be8..475e414dbc 100644 --- a/src/plugins/texteditor/texteditor.qbs +++ b/src/plugins/texteditor/texteditor.qbs @@ -1,4 +1,6 @@ import qbs 1.0 +import qbs.FileInfo +import qbs.Environment Project { name: "TextEditor" @@ -9,10 +11,14 @@ Project { Depends { name: "Qt"; submodules: ["widgets", "xml", "network", "printsupport"] } Depends { name: "Aggregation" } Depends { name: "Utils" } + Depends { name: "KSyntaxHighlighting" } + + Export { + Depends { name: "KSyntaxHighlighting" } + } Depends { name: "Core" } - cpp.includePaths: base.concat([path]) // Needed for the highlighterengine autotest. cpp.enableExceptions: true files: [ @@ -80,8 +86,13 @@ Project { "fontsettingspage.ui", "formattexteditor.cpp", "formattexteditor.h", - "highlighterutils.cpp", - "highlighterutils.h", + "highlighter.cpp", + "highlighter.h", + "highlightersettings.cpp", + "highlightersettings.h", + "highlightersettingspage.cpp", + "highlightersettingspage.h", + "highlightersettingspage.ui", "icodestylepreferences.cpp", "icodestylepreferences.h", "icodestylepreferencesfactory.cpp", @@ -198,50 +209,6 @@ Project { } Group { - name: "GenericHighlighter" - prefix: "generichighlighter/" - files: [ - "context.cpp", - "context.h", - "definitiondownloader.cpp", - "definitiondownloader.h", - "dynamicrule.cpp", - "dynamicrule.h", - "highlightdefinition.cpp", - "highlightdefinition.h", - "highlightdefinitionhandler.cpp", - "highlightdefinitionhandler.h", - "highlightdefinitionmetadata.h", - "highlighter.cpp", - "highlighter.h", - "highlighterexception.h", - "highlightersettings.cpp", - "highlightersettings.h", - "highlightersettingspage.cpp", - "highlightersettingspage.h", - "highlightersettingspage.ui", - "includerulesinstruction.cpp", - "includerulesinstruction.h", - "itemdata.cpp", - "itemdata.h", - "keywordlist.cpp", - "keywordlist.h", - "managedefinitionsdialog.cpp", - "managedefinitionsdialog.h", - "managedefinitionsdialog.ui", - "manager.cpp", - "manager.h", - "progressdata.cpp", - "progressdata.h", - "reuse.h", - "rule.cpp", - "rule.h", - "specificrules.cpp", - "specificrules.h", - ] - } - - Group { name: "Snippets" prefix: "snippets/" files: [ diff --git a/src/plugins/texteditor/texteditor_dependencies.pri b/src/plugins/texteditor/texteditor_dependencies.pri index 1bab312c8a..c624e4cfb2 100644 --- a/src/plugins/texteditor/texteditor_dependencies.pri +++ b/src/plugins/texteditor/texteditor_dependencies.pri @@ -2,6 +2,7 @@ QTC_PLUGIN_NAME = TextEditor QTC_LIB_DEPENDS += \ aggregation \ extensionsystem \ - utils + utils \ + syntax-highlighting QTC_PLUGIN_DEPENDS += \ coreplugin diff --git a/src/plugins/texteditor/texteditorplugin.cpp b/src/plugins/texteditor/texteditorplugin.cpp index 5cacd941c4..e08ecbe75d 100644 --- a/src/plugins/texteditor/texteditorplugin.cpp +++ b/src/plugins/texteditor/texteditorplugin.cpp @@ -25,16 +25,16 @@ #include "texteditorplugin.h" -#include "texteditor.h" #include "findincurrentfile.h" #include "findinfiles.h" #include "findinopenfiles.h" #include "fontsettings.h" -#include "generichighlighter/manager.h" +#include "highlighter.h" #include "linenumberfilter.h" #include "outlinefactory.h" #include "plaintexteditorfactory.h" #include "snippets/snippetprovider.h" +#include "texteditor.h" #include "texteditoractionhandler.h" #include "texteditorsettings.h" @@ -144,9 +144,6 @@ bool TextEditorPlugin::initialize(const QStringList &arguments, QString *errorMe editor->editorWidget()->showContextMenu(); }); - // Generic highlighter. - connect(ICore::instance(), &ICore::coreOpened, Manager::instance(), &Manager::registerHighlightingFiles); - // Add text snippet provider. SnippetProvider::registerGroup(Constants::TEXT_SNIPPET_GROUP_ID, tr("Text", "SnippetProvider")); @@ -229,6 +226,12 @@ LineNumberFilter *TextEditorPlugin::lineNumberFilter() return &m_instance->d->lineNumberFilter; } +ExtensionSystem::IPlugin::ShutdownFlag TextEditorPlugin::aboutToShutdown() +{ + Highlighter::handleShutdown(); + return SynchronousShutdown; +} + void TextEditorPluginPrivate::updateSearchResultsFont(const FontSettings &settings) { if (auto window = SearchResultWindow::instance()) { diff --git a/src/plugins/texteditor/texteditorplugin.h b/src/plugins/texteditor/texteditorplugin.h index 297cde9a8b..e5dba0f4ac 100644 --- a/src/plugins/texteditor/texteditorplugin.h +++ b/src/plugins/texteditor/texteditorplugin.h @@ -44,6 +44,8 @@ public: static TextEditorPlugin *instance(); static LineNumberFilter *lineNumberFilter(); + ShutdownFlag aboutToShutdown() override; + private: bool initialize(const QStringList &arguments, QString *errorMessage) final; void extensionsInitialized() final; diff --git a/src/plugins/texteditor/texteditorsettings.cpp b/src/plugins/texteditor/texteditorsettings.cpp index c6b1710c7c..78cea2b828 100644 --- a/src/plugins/texteditor/texteditorsettings.cpp +++ b/src/plugins/texteditor/texteditorsettings.cpp @@ -25,23 +25,24 @@ #include "texteditorsettings.h" -#include "fontsettings.h" -#include "texteditor.h" #include "behaviorsettings.h" #include "behaviorsettingspage.h" #include "completionsettings.h" -#include "marginsettings.h" +#include "completionsettingspage.h" #include "displaysettings.h" #include "displaysettingspage.h" -#include "fontsettingspage.h" -#include "typingsettings.h" -#include "storagesettings.h" -#include "tabsettings.h" #include "extraencodingsettings.h" +#include "fontsettings.h" +#include "fontsettingspage.h" +#include "highlightersettingspage.h" #include "icodestylepreferences.h" #include "icodestylepreferencesfactory.h" -#include "completionsettingspage.h" -#include <texteditor/generichighlighter/highlightersettingspage.h> +#include "marginsettings.h" +#include "storagesettings.h" +#include "tabsettings.h" +#include "texteditor.h" +#include "typingsettings.h" + #include <texteditor/snippets/snippetssettingspage.h> #include <extensionsystem/pluginmanager.h> |