aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp')
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp798
1 files changed, 798 insertions, 0 deletions
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp
new file mode 100644
index 0000000000..c03d23dc48
--- /dev/null
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp
@@ -0,0 +1,798 @@
+/*
+ Copyright (C) 2016 Volker Krause <vkrause@kde.org>
+ Copyright (C) 2018 Dominik Haumann <dhaumann@kde.org>
+ Copyright (C) 2018 Christoph Cullmann <cullmann@kde.org>
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+
+#include "definition.h"
+#include "definition_p.h"
+#include "definitionref_p.h"
+
+#include "context_p.h"
+#include "format.h"
+#include "format_p.h"
+#include "repository_p.h"
+#include "rule_p.h"
+#include "ksyntaxhighlighting_logging.h"
+#include "ksyntaxhighlighting_version.h"
+#include "xml_p.h"
+
+#include <QCoreApplication>
+#include <QDebug>
+#include <QFile>
+#include <QHash>
+#include <QJsonObject>
+#include <QStringList>
+#include <QVector>
+#include <QXmlStreamReader>
+
+#include <algorithm>
+
+using namespace KSyntaxHighlighting;
+
+DefinitionData::DefinitionData()
+ : wordDelimiters(QStringLiteral("\t !%&()*+,-./:;<=>?[\\]^{|}~")) // must be sorted!
+ , wordWrapDelimiters(wordDelimiters)
+{
+}
+
+DefinitionData::~DefinitionData()
+{
+ qDeleteAll(contexts);
+}
+
+DefinitionData* DefinitionData::get(const Definition &def)
+{
+ return def.d.get();
+}
+
+Definition::Definition() :
+ d(new DefinitionData)
+{
+}
+
+Definition::Definition(const Definition &other) :
+ d(other.d)
+{
+ d->q = *this;
+}
+
+Definition::Definition(const std::shared_ptr<DefinitionData> &dd) :
+ d(dd)
+{
+}
+
+Definition::~Definition()
+{
+}
+
+Definition& Definition::operator=(const Definition &rhs)
+{
+ d = rhs.d;
+ return *this;
+}
+
+bool Definition::operator==(const Definition &other) const
+{
+ return d->fileName == other.d->fileName;
+}
+
+bool Definition::operator!=(const Definition& other) const
+{
+ return d->fileName != other.d->fileName;
+}
+
+bool Definition::isValid() const
+{
+ return d->repo && !d->fileName.isEmpty() && !d->name.isEmpty();
+}
+
+QString Definition::filePath() const
+{
+ return d->fileName;
+}
+
+QString Definition::name() const
+{
+ return d->name;
+}
+
+QString Definition::translatedName() const
+{
+ return QCoreApplication::instance()->translate("Language", d->name.toUtf8().constData());
+}
+
+QString Definition::section() const
+{
+ return d->section;
+}
+
+QString Definition::translatedSection() const
+{
+ return QCoreApplication::instance()->translate("Language Section", d->section.toUtf8().constData());
+}
+
+QVector<QString> Definition::mimeTypes() const
+{
+ return d->mimetypes;
+}
+
+QVector<QString> Definition::extensions() const
+{
+ return d->extensions;
+}
+
+int Definition::version() const
+{
+ return d->version;
+}
+
+int Definition::priority() const
+{
+ return d->priority;
+}
+
+bool Definition::isHidden() const
+{
+ return d->hidden;
+}
+
+QString Definition::style() const
+{
+ return d->style;
+}
+
+QString Definition::indenter() const
+{
+ return d->indenter;
+}
+
+QString Definition::author() const
+{
+ return d->author;
+}
+
+QString Definition::license() const
+{
+ return d->license;
+}
+
+bool Definition::isWordDelimiter(QChar c) const
+{
+ d->load();
+ return d->isWordDelimiter(c);
+}
+
+bool Definition::isWordWrapDelimiter(QChar c) const
+{
+ d->load();
+ return std::binary_search(d->wordWrapDelimiters.constBegin(), d->wordWrapDelimiters.constEnd(), c);
+}
+
+bool Definition::foldingEnabled() const
+{
+ d->load();
+ if (d->hasFoldingRegions || indentationBasedFoldingEnabled()) {
+ return true;
+ }
+
+ // check included definitions
+ const auto defs = includedDefinitions();
+ for (const auto &def : defs) {
+ if (def.foldingEnabled()) {
+ d->hasFoldingRegions = true;
+ break;
+ }
+ }
+
+ return d->hasFoldingRegions;
+}
+
+bool Definition::indentationBasedFoldingEnabled() const
+{
+ d->load();
+ return d->indentationBasedFolding;
+}
+
+QStringList Definition::foldingIgnoreList() const
+{
+ d->load();
+ return d->foldingIgnoreList;
+}
+
+QStringList Definition::keywordLists() const
+{
+ d->load();
+ return d->keywordLists.keys();
+}
+
+QStringList Definition::keywordList(const QString& name) const
+{
+ d->load();
+ const auto list = d->keywordList(name);
+ return list ? list->keywords() : QStringList();
+}
+
+QVector<Format> Definition::formats() const
+{
+ d->load();
+
+ // sort formats so that the order matches the order of the itemDatas in the xml files.
+ auto formatList = QVector<Format>::fromList(d->formats.values());
+ std::sort(formatList.begin(), formatList.end(), [](const KSyntaxHighlighting::Format & lhs, const KSyntaxHighlighting::Format & rhs){
+ return lhs.id() < rhs.id();
+ });
+
+ return formatList;
+}
+
+QVector<Definition> Definition::includedDefinitions() const
+{
+ d->load();
+
+ // init worklist and result used as guard with this definition
+ QVector<Definition> queue{*this};
+ QVector<Definition> definitions{*this};
+ while (!queue.isEmpty()) {
+ // Iterate all context rules to find associated Definitions. This will
+ // automatically catch other Definitions referenced with IncludeRuldes or ContextSwitch.
+ const auto definition = queue.takeLast();
+ for (const auto & context : qAsConst(definition.d->contexts)) {
+ // handle context switch attributes of this context itself
+ for (const auto switchContext : {context->lineEndContext().context(), context->lineEmptyContext().context(), context->fallthroughContext().context()}) {
+ if (switchContext) {
+ if (!definitions.contains(switchContext->definition())) {
+ queue.push_back(switchContext->definition());
+ definitions.push_back(switchContext->definition());
+ }
+ }
+ }
+
+ // handle the embedded rules
+ for (const auto &rule : context->rules()) {
+ // handle include rules like inclusion
+ if (!definitions.contains(rule->definition())) {
+ queue.push_back(rule->definition());
+ definitions.push_back(rule->definition());
+ }
+
+ // handle context switch context inclusion
+ if (auto switchContext = rule->context().context()) {
+ if (!definitions.contains(switchContext->definition())) {
+ queue.push_back(switchContext->definition());
+ definitions.push_back(switchContext->definition());
+ }
+ }
+ }
+ }
+ }
+
+ // remove the 1st entry, since it is this Definition
+ definitions.pop_front();
+
+ return definitions;
+}
+
+QString Definition::singleLineCommentMarker() const
+{
+ d->load();
+ return d->singleLineCommentMarker;
+}
+
+CommentPosition Definition::singleLineCommentPosition() const
+{
+ d->load();
+ return d->singleLineCommentPosition;
+}
+
+QPair<QString, QString> Definition::multiLineCommentMarker() const
+{
+ d->load();
+ return { d->multiLineCommentStartMarker, d->multiLineCommentEndMarker };
+}
+
+QVector<QPair<QChar, QString>> Definition::characterEncodings() const
+{
+ d->load();
+ return d->characterEncodings;
+}
+
+Context* DefinitionData::initialContext() const
+{
+ Q_ASSERT(!contexts.isEmpty());
+ return contexts.first();
+}
+
+Context* DefinitionData::contextByName(const QString& name) const
+{
+ foreach (auto context, contexts) {
+ if (context->name() == name)
+ return context;
+ }
+ return nullptr;
+}
+
+KeywordList *DefinitionData::keywordList(const QString& name)
+{
+ auto it = keywordLists.find(name);
+ return (it == keywordLists.end()) ? nullptr : &it.value();
+}
+
+bool DefinitionData::isWordDelimiter(QChar c) const
+{
+ return std::binary_search(wordDelimiters.constBegin(), wordDelimiters.constEnd(), c);
+}
+
+Format DefinitionData::formatByName(const QString& name) const
+{
+ const auto it = formats.constFind(name);
+ if (it != formats.constEnd())
+ return it.value();
+
+ return Format();
+}
+
+bool DefinitionData::isLoaded() const
+{
+ return !contexts.isEmpty();
+}
+
+bool DefinitionData::load()
+{
+ if (fileName.isEmpty())
+ return false;
+
+ if (isLoaded())
+ return true;
+
+ QFile file(fileName);
+ if (!file.open(QFile::ReadOnly))
+ return false;
+
+ QXmlStreamReader reader(&file);
+ while (!reader.atEnd()) {
+ const auto token = reader.readNext();
+ if (token != QXmlStreamReader::StartElement)
+ continue;
+
+ if (reader.name() == QLatin1String("highlighting"))
+ loadHighlighting(reader);
+
+ else if (reader.name() == QLatin1String("general"))
+ loadGeneral(reader);
+ }
+
+ for (auto it = keywordLists.begin(); it != keywordLists.end(); ++it)
+ (*it).setCaseSensitivity(caseSensitive);
+
+ foreach (auto context, contexts) {
+ context->resolveContexts();
+ context->resolveIncludes();
+ context->resolveAttributeFormat();
+ }
+
+ Q_ASSERT(std::is_sorted(wordDelimiters.constBegin(), wordDelimiters.constEnd()));
+ return true;
+}
+
+void DefinitionData::clear()
+{
+ // keep only name and repo, so we can re-lookup to make references persist over repo reloads
+ keywordLists.clear();
+ qDeleteAll(contexts);
+ contexts.clear();
+ formats.clear();
+
+ fileName.clear();
+ section.clear();
+ style.clear();
+ indenter.clear();
+ author.clear();
+ license.clear();
+ mimetypes.clear();
+ extensions.clear();
+ wordDelimiters = QStringLiteral("\t !%&()*+,-./:;<=>?[\\]^{|}~"); // must be sorted!
+ wordWrapDelimiters = wordDelimiters;
+ caseSensitive = Qt::CaseSensitive;
+ version = 0.0f;
+ priority = 0;
+ hidden = false;
+}
+
+bool DefinitionData::loadMetaData(const QString& definitionFileName)
+{
+ fileName = definitionFileName;
+
+ QFile file(definitionFileName);
+ if (!file.open(QFile::ReadOnly))
+ return false;
+
+ QXmlStreamReader reader(&file);
+ while (!reader.atEnd()) {
+ const auto token = reader.readNext();
+ if (token != QXmlStreamReader::StartElement)
+ continue;
+ if (reader.name() == QLatin1String("language")) {
+ return loadLanguage(reader);
+ }
+ }
+
+ return false;
+}
+
+bool DefinitionData::loadMetaData(const QString &file, const QJsonObject &obj)
+{
+ name = obj.value(QLatin1String("name")).toString();
+ section = obj.value(QLatin1String("section")).toString();
+ version = obj.value(QLatin1String("version")).toInt();
+ priority = obj.value(QLatin1String("priority")).toInt();
+ style = obj.value(QLatin1String("style")).toString();
+ author = obj.value(QLatin1String("author")).toString();
+ license = obj.value(QLatin1String("license")).toString();
+ indenter = obj.value(QLatin1String("indenter")).toString();
+ hidden = obj.value(QLatin1String("hidden")).toBool();
+ fileName = file;
+
+ const auto exts = obj.value(QLatin1String("extensions")).toString();
+ foreach (const auto &ext, exts.split(QLatin1Char(';'), QString::SkipEmptyParts))
+ extensions.push_back(ext);
+ const auto mts = obj.value(QLatin1String("mimetype")).toString();
+ foreach (const auto &mt, mts.split(QLatin1Char(';'), QString::SkipEmptyParts))
+ mimetypes.push_back(mt);
+
+ return true;
+}
+
+bool DefinitionData::loadLanguage(QXmlStreamReader &reader)
+{
+ Q_ASSERT(reader.name() == QLatin1String("language"));
+ Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement);
+
+ if (!checkKateVersion(reader.attributes().value(QStringLiteral("kateversion"))))
+ return false;
+
+ name = reader.attributes().value(QStringLiteral("name")).toString();
+ section = reader.attributes().value(QStringLiteral("section")).toString();
+ // toFloat instead of toInt for backward compatibility with old Kate files
+ version = reader.attributes().value(QStringLiteral("version")).toFloat();
+ priority = reader.attributes().value(QStringLiteral("priority")).toInt();
+ hidden = Xml::attrToBool(reader.attributes().value(QStringLiteral("hidden")));
+ style = reader.attributes().value(QStringLiteral("style")).toString();
+ indenter = reader.attributes().value(QStringLiteral("indenter")).toString();
+ author = reader.attributes().value(QStringLiteral("author")).toString();
+ license = reader.attributes().value(QStringLiteral("license")).toString();
+ const auto exts = reader.attributes().value(QStringLiteral("extensions")).toString();
+ foreach (const auto &ext, exts.split(QLatin1Char(';'), QString::SkipEmptyParts))
+ extensions.push_back(ext);
+ const auto mts = reader.attributes().value(QStringLiteral("mimetype")).toString();
+ foreach (const auto &mt, mts.split(QLatin1Char(';'), QString::SkipEmptyParts))
+ mimetypes.push_back(mt);
+ if (reader.attributes().hasAttribute(QStringLiteral("casesensitive")))
+ caseSensitive = Xml::attrToBool(reader.attributes().value(QStringLiteral("casesensitive"))) ? Qt::CaseSensitive : Qt::CaseInsensitive;
+ return true;
+}
+
+void DefinitionData::loadHighlighting(QXmlStreamReader& reader)
+{
+ Q_ASSERT(reader.name() == QLatin1String("highlighting"));
+ Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement);
+
+ while (!reader.atEnd()) {
+ switch (reader.tokenType()) {
+ case QXmlStreamReader::StartElement:
+ if (reader.name() == QLatin1String("list")) {
+ KeywordList keywords;
+ keywords.load(reader);
+ keywordLists.insert(keywords.name(), keywords);
+ } else if (reader.name() == QLatin1String("contexts")) {
+ loadContexts(reader);
+ reader.readNext();
+ } else if (reader.name() == QLatin1String("itemDatas")) {
+ loadItemData(reader);
+ } else {
+ reader.readNext();
+ }
+ break;
+ case QXmlStreamReader::EndElement:
+ return;
+ default:
+ reader.readNext();
+ break;
+ }
+ }
+}
+
+void DefinitionData::loadContexts(QXmlStreamReader& reader)
+{
+ Q_ASSERT(reader.name() == QLatin1String("contexts"));
+ Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement);
+
+ while (!reader.atEnd()) {
+ switch (reader.tokenType()) {
+ case QXmlStreamReader::StartElement:
+ if (reader.name() == QLatin1String("context")) {
+ auto context = new Context;
+ context->setDefinition(q);
+ context->load(reader);
+ contexts.push_back(context);
+ }
+ reader.readNext();
+ break;
+ case QXmlStreamReader::EndElement:
+ return;
+ default:
+ reader.readNext();
+ break;
+ }
+ }
+}
+
+void DefinitionData::loadItemData(QXmlStreamReader& reader)
+{
+ Q_ASSERT(reader.name() == QLatin1String("itemDatas"));
+ Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement);
+
+ while (!reader.atEnd()) {
+ switch (reader.tokenType()) {
+ case QXmlStreamReader::StartElement:
+ if (reader.name() == QLatin1String("itemData")) {
+ Format f;
+ auto formatData = FormatPrivate::detachAndGet(f);
+ formatData->definition = q;
+ formatData->load(reader);
+ formatData->id = RepositoryPrivate::get(repo)->nextFormatId();
+ formats.insert(f.name(), f);
+ reader.readNext();
+ }
+ reader.readNext();
+ break;
+ case QXmlStreamReader::EndElement:
+ return;
+ default:
+ reader.readNext();
+ break;
+ }
+ }
+}
+
+void DefinitionData::loadGeneral(QXmlStreamReader& reader)
+{
+ Q_ASSERT(reader.name() == QLatin1String("general"));
+ Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement);
+ reader.readNext();
+
+ // reference counter to count XML child elements, to not return too early
+ int elementRefCounter = 1;
+
+ while (!reader.atEnd()) {
+ switch (reader.tokenType()) {
+ case QXmlStreamReader::StartElement:
+ ++elementRefCounter;
+
+ if (reader.name() == QLatin1String("keywords")) {
+ if (reader.attributes().hasAttribute(QStringLiteral("casesensitive")))
+ caseSensitive = Xml::attrToBool(reader.attributes().value(QStringLiteral("casesensitive"))) ? Qt::CaseSensitive : Qt::CaseInsensitive;
+
+ // adapt sorted wordDelimiters
+ wordDelimiters += reader.attributes().value(QStringLiteral("additionalDeliminator"));
+ std::sort(wordDelimiters.begin(), wordDelimiters.end());
+ auto it = std::unique(wordDelimiters.begin(), wordDelimiters.end());
+ wordDelimiters.truncate(std::distance(wordDelimiters.begin(), it));
+ foreach (const auto c, reader.attributes().value(QLatin1String("weakDeliminator")))
+ wordDelimiters.remove(c);
+
+ // adaptWordWrapDelimiters, and sort
+ wordWrapDelimiters = reader.attributes().value(QStringLiteral("wordWrapDeliminator")).toString();
+ std::sort(wordWrapDelimiters.begin(), wordWrapDelimiters.end());
+ if (wordWrapDelimiters.isEmpty())
+ wordWrapDelimiters = wordDelimiters;
+ } else if (reader.name() == QLatin1String("folding")) {
+ if (reader.attributes().hasAttribute(QStringLiteral("indentationsensitive")))
+ indentationBasedFolding = Xml::attrToBool(reader.attributes().value(QStringLiteral("indentationsensitive")));
+ } else if (reader.name() == QLatin1String("emptyLines")) {
+ loadFoldingIgnoreList(reader);
+ } else if (reader.name() == QLatin1String("comments")) {
+ loadComments(reader);
+ } else if (reader.name() == QLatin1String("spellchecking")) {
+ loadSpellchecking(reader);
+ } else {
+ reader.skipCurrentElement();
+ }
+ reader.readNext();
+ break;
+ case QXmlStreamReader::EndElement:
+ --elementRefCounter;
+ if (elementRefCounter == 0)
+ return;
+ reader.readNext();
+ break;
+ default:
+ reader.readNext();
+ break;
+ }
+ }
+}
+
+void DefinitionData::loadComments(QXmlStreamReader &reader)
+{
+ Q_ASSERT(reader.name() == QLatin1String("comments"));
+ Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement);
+ reader.readNext();
+
+ // reference counter to count XML child elements, to not return too early
+ int elementRefCounter = 1;
+
+ while (!reader.atEnd()) {
+ switch (reader.tokenType()) {
+ case QXmlStreamReader::StartElement:
+ ++elementRefCounter;
+ if (reader.name() == QLatin1String("comment")) {
+ const bool isSingleLine = reader.attributes().value(QStringLiteral("name")) == QStringLiteral("singleLine");
+ if (isSingleLine) {
+ singleLineCommentMarker = reader.attributes().value(QStringLiteral("start")).toString();
+ const bool afterWhiteSpace = reader.attributes().value(QStringLiteral("position")).toString() == QStringLiteral("afterwhitespace");
+ singleLineCommentPosition = afterWhiteSpace ? CommentPosition::AfterWhitespace : CommentPosition::StartOfLine;
+ } else {
+ multiLineCommentStartMarker = reader.attributes().value(QStringLiteral("start")).toString();
+ multiLineCommentEndMarker = reader.attributes().value(QStringLiteral("end")).toString();
+ }
+ }
+ reader.readNext();
+ break;
+ case QXmlStreamReader::EndElement:
+ --elementRefCounter;
+ if (elementRefCounter == 0)
+ return;
+ reader.readNext();
+ break;
+ default:
+ reader.readNext();
+ break;
+ }
+ }
+}
+
+void DefinitionData::loadFoldingIgnoreList(QXmlStreamReader& reader)
+{
+ Q_ASSERT(reader.name() == QLatin1String("emptyLines"));
+ Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement);
+ reader.readNext();
+
+ // reference counter to count XML child elements, to not return too early
+ int elementRefCounter = 1;
+
+ while (!reader.atEnd()) {
+ switch (reader.tokenType()) {
+ case QXmlStreamReader::StartElement:
+ ++elementRefCounter;
+ if (reader.name() == QLatin1String("emptyLine")) {
+ foldingIgnoreList << reader.attributes().value(QStringLiteral("regexpr")).toString();
+ }
+ reader.readNext();
+ break;
+ case QXmlStreamReader::EndElement:
+ --elementRefCounter;
+ if (elementRefCounter == 0)
+ return;
+ reader.readNext();
+ break;
+ default:
+ reader.readNext();
+ break;
+ }
+ }
+}
+
+void DefinitionData::loadSpellchecking(QXmlStreamReader &reader)
+{
+ Q_ASSERT(reader.name() == QLatin1String("spellchecking"));
+ Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement);
+ reader.readNext();
+
+ // reference counter to count XML child elements, to not return too early
+ int elementRefCounter = 1;
+
+ while (!reader.atEnd()) {
+ switch (reader.tokenType()) {
+ case QXmlStreamReader::StartElement:
+ ++elementRefCounter;
+ if (reader.name() == QLatin1String("encoding")) {
+ const auto charRef = reader.attributes().value(QStringLiteral("char"));
+ if (!charRef.isEmpty()) {
+ const auto str = reader.attributes().value(QStringLiteral("string")).toString();
+ characterEncodings.push_back({ charRef[0], str });
+ }
+ }
+ reader.readNext();
+ break;
+ case QXmlStreamReader::EndElement:
+ --elementRefCounter;
+ if (elementRefCounter == 0)
+ return;
+ reader.readNext();
+ break;
+ default:
+ reader.readNext();
+ break;
+ }
+ }
+}
+
+bool DefinitionData::checkKateVersion(const QStringRef& verStr)
+{
+ const auto idx = verStr.indexOf(QLatin1Char('.'));
+ if (idx <= 0) {
+ qCWarning(Log) << "Skipping" << fileName << "due to having no valid kateversion attribute:" << verStr;
+ return false;
+ }
+ const auto major = verStr.left(idx).toInt();
+ const auto minor = verStr.mid(idx + 1).toInt();
+
+ if (major > SyntaxHighlighting_VERSION_MAJOR || (major == SyntaxHighlighting_VERSION_MAJOR && minor > SyntaxHighlighting_VERSION_MINOR)) {
+ qCWarning(Log) << "Skipping" << fileName << "due to being too new, version:" << verStr;
+ return false;
+ }
+
+ return true;
+}
+
+quint16 DefinitionData::foldingRegionId(const QString &foldName)
+{
+ hasFoldingRegions = true;
+ return RepositoryPrivate::get(repo)->foldingRegionId(name, foldName);
+}
+
+DefinitionRef::DefinitionRef()
+{
+}
+
+DefinitionRef::DefinitionRef(const Definition &def) :
+ d(def.d)
+{
+}
+
+DefinitionRef::~DefinitionRef()
+{
+}
+
+DefinitionRef& DefinitionRef::operator=(const Definition &def)
+{
+ d = def.d;
+ return *this;
+}
+
+Definition DefinitionRef::definition() const
+{
+ if (!d.expired())
+ return Definition(d.lock());
+ return Definition();
+}
+
+bool DefinitionRef::operator==(const DefinitionRef &other) const
+{
+ if (d.expired() != other.d.expired()) {
+ return false;
+ }
+
+ return d.expired() || d.lock().get() == other.d.lock().get();
+}