KSyntaxHighlighting

definition.cpp
1/*
2 SPDX-FileCopyrightText: 2016 Volker Krause <vkrause@kde.org>
3 SPDX-FileCopyrightText: 2018 Dominik Haumann <dhaumann@kde.org>
4 SPDX-FileCopyrightText: 2018 Christoph Cullmann <cullmann@kde.org>
5 SPDX-FileCopyrightText: 2020 Jonathan Poelen <jonathan.poelen@gmail.com>
6
7 SPDX-License-Identifier: MIT
8*/
9
10#include "definition.h"
11#include "definition_p.h"
12#include "definitionref_p.h"
13
14#include "context_p.h"
15#include "format.h"
16#include "format_p.h"
17#include "highlightingdata_p.hpp"
18#include "ksyntaxhighlighting_logging.h"
19#include "ksyntaxhighlighting_version.h"
20#include "repository.h"
21#include "repository_p.h"
22#include "rule_p.h"
23#include "worddelimiters_p.h"
24#include "xml_p.h"
25
26#include <QCborMap>
27#include <QCoreApplication>
28#include <QFile>
29#include <QXmlStreamReader>
30
31#include <algorithm>
32#include <atomic>
33
34using namespace KSyntaxHighlighting;
35
36DefinitionData::DefinitionData()
37 : wordDelimiters()
38 , wordWrapDelimiters(wordDelimiters)
39{
40}
41
42DefinitionData::~DefinitionData() = default;
43
45 : d(std::make_shared<DefinitionData>())
46{
47 d->q = *this;
48}
49
50Definition::Definition(Definition &&other) noexcept = default;
51Definition::Definition(const Definition &) = default;
52Definition::~Definition() = default;
53Definition &Definition::operator=(Definition &&other) noexcept = default;
55
56Definition::Definition(std::shared_ptr<DefinitionData> &&dd)
57 : d(std::move(dd))
58{
59 if (!d) {
60 Definition().d.swap(d);
61 }
62}
63
64bool Definition::operator==(const Definition &other) const
65{
66 return d->fileName == other.d->fileName;
67}
68
69bool Definition::operator!=(const Definition &other) const
70{
71 return d->fileName != other.d->fileName;
72}
73
75{
76 return d->repo && !d->fileName.isEmpty() && !d->name.isEmpty();
77}
78
80{
81 return d->fileName;
82}
83
84QString Definition::name() const
85{
86 return d->name;
87}
88
90{
91 return d->alternativeNames;
92}
93
94QString Definition::translatedName() const
95{
96 if (d->translatedName.isEmpty()) {
97 d->translatedName = QCoreApplication::instance()->translate("Language", d->nameUtf8.isEmpty() ? d->name.toUtf8().constData() : d->nameUtf8.constData());
98 }
99 return d->translatedName;
100}
101
102QString Definition::section() const
103{
104 return d->section;
105}
106
107QString Definition::translatedSection() const
108{
109 if (d->translatedSection.isEmpty()) {
110 d->translatedSection = QCoreApplication::instance()->translate("Language Section",
111 d->sectionUtf8.isEmpty() ? d->section.toUtf8().constData() : d->sectionUtf8.constData());
112 }
113 return d->translatedSection;
114}
115
117{
118 return d->mimetypes;
119}
120
122{
123 return d->extensions;
124}
125
127{
128 return d->version;
129}
130
132{
133 return d->priority;
134}
135
137{
138 return d->hidden;
139}
140
142{
143 return d->style;
144}
145
147{
148 return d->indenter;
149}
150
151QString Definition::author() const
152{
153 return d->author;
154}
155
156QString Definition::license() const
157{
158 return d->license;
159}
160
162{
163 d->load();
164 return d->wordDelimiters.contains(c);
165}
166
168{
169 d->load();
170 return d->wordWrapDelimiters.contains(c);
171}
172
174{
175 d->load();
176 if (d->hasFoldingRegions || indentationBasedFoldingEnabled()) {
177 return true;
178 }
179
180 // check included definitions
181 const auto defs = includedDefinitions();
182 for (const auto &def : defs) {
183 if (def.foldingEnabled()) {
184 d->hasFoldingRegions = true;
185 break;
186 }
187 }
188
189 return d->hasFoldingRegions;
190}
191
193{
194 d->load();
195 return d->indentationBasedFolding;
196}
197
199{
200 d->load();
201 return d->foldingIgnoreList;
202}
203
205{
206 d->load(DefinitionData::OnlyKeywords(true));
207 return d->keywordLists.keys();
208}
209
211{
212 d->load(DefinitionData::OnlyKeywords(true));
213 const auto list = d->keywordList(name);
214 return list ? list->keywords() : QStringList();
215}
216
217bool Definition::setKeywordList(const QString &name, const QStringList &content)
218{
219 d->load(DefinitionData::OnlyKeywords(true));
220 KeywordList *list = d->keywordList(name);
221 if (list) {
222 list->setKeywordList(content);
223 return true;
224 } else {
225 return false;
226 }
227}
228
230{
231 d->load();
232
233 // sort formats so that the order matches the order of the itemDatas in the xml files.
234 auto formatList = d->formats.values();
235 std::sort(formatList.begin(), formatList.end(), [](const KSyntaxHighlighting::Format &lhs, const KSyntaxHighlighting::Format &rhs) {
236 return lhs.id() < rhs.id();
237 });
238
239 return formatList;
240}
241
243{
244 d->load();
245
246 // init worklist and result used as guard with this definition
247 QList<const DefinitionData *> queue{d.get()};
248 QList<Definition> definitions{*this};
249 while (!queue.empty()) {
250 const auto *def = queue.back();
251 queue.pop_back();
252 for (const auto &defRef : std::as_const(def->immediateIncludedDefinitions)) {
253 const auto definition = defRef.definition();
254 if (!definitions.contains(definition)) {
255 definitions.push_back(definition);
256 queue.push_back(definition.d.get());
257 }
258 }
259 }
260
261 // remove the 1st entry, since it is this Definition
262 definitions.front() = std::move(definitions.back());
263 definitions.pop_back();
264
265 return definitions;
266}
267
269{
270 d->load();
271 return d->singleLineCommentMarker;
272}
273
275{
276 d->load();
277 return d->singleLineCommentPosition;
278}
279
280QPair<QString, QString> Definition::multiLineCommentMarker() const
281{
282 d->load();
283 return {d->multiLineCommentStartMarker, d->multiLineCommentEndMarker};
284}
285
287{
288 d->load();
289 return d->characterEncodings;
290}
291
292Context *DefinitionData::initialContext()
293{
294 Q_ASSERT(!contexts.empty());
295 return &contexts.front();
296}
297
298Context *DefinitionData::contextByName(QStringView wantedName)
299{
300 for (auto &context : contexts) {
301 if (context.name() == wantedName) {
302 return &context;
303 }
304 }
305 return nullptr;
306}
307
308KeywordList *DefinitionData::keywordList(const QString &wantedName)
309{
310 auto it = keywordLists.find(wantedName);
311 return (it == keywordLists.end()) ? nullptr : &it.value();
312}
313
314Format DefinitionData::formatByName(const QString &wantedName) const
315{
316 const auto it = formats.constFind(wantedName);
317 if (it != formats.constEnd()) {
318 return it.value();
319 }
320
321 return Format();
322}
323
324bool DefinitionData::isLoaded() const
325{
326 return !contexts.empty();
327}
328
329namespace
330{
331std::atomic<uint64_t> definitionId{1};
332}
333
334bool DefinitionData::load(OnlyKeywords onlyKeywords)
335{
336 if (fileName.isEmpty()) {
337 return false;
338 }
339
340 if (isLoaded()) {
341 return true;
342 }
343
344 if (bool(onlyKeywords) && keywordIsLoaded) {
345 return true;
346 }
347
348 QFile file(fileName);
349 if (!file.open(QFile::ReadOnly)) {
350 return false;
351 }
352
353 QXmlStreamReader reader(&file);
354 while (!reader.atEnd()) {
355 const auto token = reader.readNext();
356 if (token != QXmlStreamReader::StartElement) {
357 continue;
358 }
359
360 if (reader.name() == QLatin1String("highlighting")) {
361 loadHighlighting(reader, onlyKeywords);
362 if (bool(onlyKeywords)) {
363 return true;
364 }
365 }
366
367 else if (reader.name() == QLatin1String("general")) {
368 loadGeneral(reader);
369 }
370 }
371
372 for (auto it = keywordLists.begin(); it != keywordLists.end(); ++it) {
373 it->setCaseSensitivity(caseSensitive);
374 }
375
376 resolveContexts();
377
378 id = definitionId.fetch_add(1, std::memory_order_relaxed);
379
380 return true;
381}
382
383void DefinitionData::clear()
384{
385 // keep only name and repo, so we can re-lookup to make references persist over repo reloads
386 id = 0;
387 keywordLists.clear();
388 contexts.clear();
389 formats.clear();
390 contextDatas.clear();
391 immediateIncludedDefinitions.clear();
392 wordDelimiters = WordDelimiters();
393 wordWrapDelimiters = wordDelimiters;
394 keywordIsLoaded = false;
395 hasFoldingRegions = false;
396 indentationBasedFolding = false;
397 foldingIgnoreList.clear();
398 singleLineCommentMarker.clear();
399 singleLineCommentPosition = CommentPosition::StartOfLine;
400 multiLineCommentStartMarker.clear();
401 multiLineCommentEndMarker.clear();
402 characterEncodings.clear();
403
404 fileName.clear();
405 nameUtf8.clear();
406 translatedName.clear();
407 section.clear();
408 sectionUtf8.clear();
409 translatedSection.clear();
410 style.clear();
411 indenter.clear();
412 author.clear();
413 license.clear();
414 mimetypes.clear();
415 extensions.clear();
416 caseSensitive = Qt::CaseSensitive;
417 version = 0.0f;
418 priority = 0;
419 hidden = false;
420
421 // purge our cache that is used to unify states
422 unify.clear();
423}
424
425bool DefinitionData::loadMetaData(const QString &definitionFileName)
426{
427 fileName = definitionFileName;
428
429 QFile file(definitionFileName);
430 if (!file.open(QFile::ReadOnly)) {
431 return false;
432 }
433
434 QXmlStreamReader reader(&file);
435 while (!reader.atEnd()) {
436 const auto token = reader.readNext();
437 if (token != QXmlStreamReader::StartElement) {
438 continue;
439 }
440 if (reader.name() == QLatin1String("language")) {
441 return loadLanguage(reader);
442 }
443 }
444
445 return false;
446}
447
448bool DefinitionData::loadMetaData(const QString &file, const QCborMap &obj)
449{
450 name = obj.value(QLatin1String("name")).toString();
451 nameUtf8 = obj.value(QLatin1String("name")).toByteArray();
452 section = obj.value(QLatin1String("section")).toString();
453 sectionUtf8 = obj.value(QLatin1String("section")).toByteArray();
454 version = obj.value(QLatin1String("version")).toInteger();
455 priority = obj.value(QLatin1String("priority")).toInteger();
456 style = obj.value(QLatin1String("style")).toString();
457 author = obj.value(QLatin1String("author")).toString();
458 license = obj.value(QLatin1String("license")).toString();
459 indenter = obj.value(QLatin1String("indenter")).toString();
460 hidden = obj.value(QLatin1String("hidden")).toBool();
461 fileName = file;
462
463 const auto names = obj.value(QLatin1String("alternativeNames")).toString();
464 alternativeNames = names.split(QLatin1Char(';'), Qt::SkipEmptyParts);
465
466 const auto exts = obj.value(QLatin1String("extensions")).toString();
467 extensions = exts.split(QLatin1Char(';'), Qt::SkipEmptyParts);
468
469 const auto mts = obj.value(QLatin1String("mimetype")).toString();
470 mimetypes = mts.split(QLatin1Char(';'), Qt::SkipEmptyParts);
471
472 return true;
473}
474
475bool DefinitionData::loadLanguage(QXmlStreamReader &reader)
476{
477 Q_ASSERT(reader.name() == QLatin1String("language"));
478 Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement);
479
480 if (!checkKateVersion(reader.attributes().value(QLatin1String("kateversion")))) {
481 return false;
482 }
483
484 name = reader.attributes().value(QLatin1String("name")).toString();
485 const auto names = reader.attributes().value(QLatin1String("alternativeNames"));
486 for (const auto &n : names.split(QLatin1Char(';'), Qt::SkipEmptyParts)) {
487 alternativeNames.push_back(n.toString());
488 }
489 section = reader.attributes().value(QLatin1String("section")).toString();
490 // toFloat instead of toInt for backward compatibility with old Kate files
491 version = reader.attributes().value(QLatin1String("version")).toFloat();
492 priority = reader.attributes().value(QLatin1String("priority")).toInt();
493 hidden = Xml::attrToBool(reader.attributes().value(QLatin1String("hidden")));
494 style = reader.attributes().value(QLatin1String("style")).toString();
495 indenter = reader.attributes().value(QLatin1String("indenter")).toString();
496 author = reader.attributes().value(QLatin1String("author")).toString();
497 license = reader.attributes().value(QLatin1String("license")).toString();
498 const auto exts = reader.attributes().value(QLatin1String("extensions"));
499 for (const auto &ext : exts.split(QLatin1Char(';'), Qt::SkipEmptyParts)) {
500 extensions.push_back(ext.toString());
501 }
502 const auto mts = reader.attributes().value(QLatin1String("mimetype"));
503 for (const auto &mt : mts.split(QLatin1Char(';'), Qt::SkipEmptyParts)) {
504 mimetypes.push_back(mt.toString());
505 }
506 if (reader.attributes().hasAttribute(QLatin1String("casesensitive"))) {
507 caseSensitive = Xml::attrToBool(reader.attributes().value(QLatin1String("casesensitive"))) ? Qt::CaseSensitive : Qt::CaseInsensitive;
508 }
509 return true;
510}
511
512void DefinitionData::loadHighlighting(QXmlStreamReader &reader, OnlyKeywords onlyKeywords)
513{
514 Q_ASSERT(reader.name() == QLatin1String("highlighting"));
515 Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement);
516
517 // skip highlighting
518 reader.readNext();
519
520 while (!reader.atEnd()) {
521 switch (reader.tokenType()) {
523 if (reader.name() == QLatin1String("list")) {
524 if (!keywordIsLoaded) {
525 KeywordList keywords;
526 keywords.load(reader);
527 keywordLists.insert(keywords.name(), keywords);
528 } else {
529 reader.skipCurrentElement();
530 reader.readNext(); // Skip </list>
531 }
532 } else if (bool(onlyKeywords)) {
533 resolveIncludeKeywords();
534 return;
535 } else if (reader.name() == QLatin1String("contexts")) {
536 resolveIncludeKeywords();
537 loadContexts(reader);
538 reader.readNext();
539 } else if (reader.name() == QLatin1String("itemDatas")) {
540 loadItemData(reader);
541 } else {
542 reader.readNext();
543 }
544 break;
546 return;
547 default:
548 reader.readNext();
549 break;
550 }
551 }
552}
553
554void DefinitionData::resolveIncludeKeywords()
555{
556 if (keywordIsLoaded) {
557 return;
558 }
559
560 keywordIsLoaded = true;
561
562 for (auto it = keywordLists.begin(); it != keywordLists.end(); ++it) {
563 it->resolveIncludeKeywords(*this);
564 }
565}
566
567void DefinitionData::loadContexts(QXmlStreamReader &reader)
568{
569 Q_ASSERT(reader.name() == QLatin1String("contexts"));
570 Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement);
571
572 contextDatas.reserve(32);
573
574 while (!reader.atEnd()) {
575 switch (reader.tokenType()) {
577 if (reader.name() == QLatin1String("context")) {
578 contextDatas.push_back(HighlightingContextData());
579 contextDatas.back().load(name, reader);
580 }
581 reader.readNext();
582 break;
584 return;
585 default:
586 reader.readNext();
587 break;
588 }
589 }
590}
591
592void DefinitionData::resolveContexts()
593{
594 contexts.reserve(contextDatas.size());
595
596 /**
597 * Transform all HighlightingContextData to Context.
598 * This is necessary so that Context::resolveContexts() can find the referenced contexts.
599 */
600 for (const auto &contextData : std::as_const(contextDatas)) {
601 contexts.emplace_back(*this, contextData);
602 }
603
604 /**
605 * Resolves contexts and rules.
606 */
607 auto ctxIt = contexts.begin();
608 for (const auto &contextData : std::as_const(contextDatas)) {
609 ctxIt->resolveContexts(*this, contextData);
610 ++ctxIt;
611 }
612
613 /**
614 * To free the memory, constDatas is emptied because it is no longer used.
615 */
616 contextDatas.clear();
617 contextDatas.shrink_to_fit();
618
619 /**
620 * Resolved includeRules.
621 */
622 for (auto &context : contexts) {
623 context.resolveIncludes(*this);
624 }
625}
626
627void DefinitionData::loadItemData(QXmlStreamReader &reader)
628{
629 Q_ASSERT(reader.name() == QLatin1String("itemDatas"));
630 Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement);
631
632 while (!reader.atEnd()) {
633 switch (reader.tokenType()) {
635 if (reader.name() == QLatin1String("itemData")) {
636 Format f;
637 auto formatData = FormatPrivate::detachAndGet(f);
638 formatData->definitionName = name;
639 formatData->load(reader);
640 formatData->id = RepositoryPrivate::get(repo)->nextFormatId();
641 formats.insert(f.name(), f);
642 reader.readNext();
643 }
644 reader.readNext();
645 break;
647 return;
648 default:
649 reader.readNext();
650 break;
651 }
652 }
653}
654
655void DefinitionData::loadGeneral(QXmlStreamReader &reader)
656{
657 Q_ASSERT(reader.name() == QLatin1String("general"));
658 Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement);
659 reader.readNext();
660
661 // reference counter to count XML child elements, to not return too early
662 int elementRefCounter = 1;
663
664 while (!reader.atEnd()) {
665 switch (reader.tokenType()) {
667 ++elementRefCounter;
668
669 if (reader.name() == QLatin1String("keywords")) {
670 if (reader.attributes().hasAttribute(QLatin1String("casesensitive"))) {
671 caseSensitive = Xml::attrToBool(reader.attributes().value(QLatin1String("casesensitive"))) ? Qt::CaseSensitive : Qt::CaseInsensitive;
672 }
673
674 // adapt wordDelimiters
675 wordDelimiters.append(reader.attributes().value(QLatin1String("additionalDeliminator")));
676 wordDelimiters.remove(reader.attributes().value(QLatin1String("weakDeliminator")));
677
678 // adapt WordWrapDelimiters
679 auto wordWrapDeliminatorAttr = reader.attributes().value(QLatin1String("wordWrapDeliminator"));
680 if (wordWrapDeliminatorAttr.isEmpty()) {
681 wordWrapDelimiters = wordDelimiters;
682 } else {
683 wordWrapDelimiters.append(wordWrapDeliminatorAttr);
684 }
685 } else if (reader.name() == QLatin1String("folding")) {
686 if (reader.attributes().hasAttribute(QLatin1String("indentationsensitive"))) {
687 indentationBasedFolding = Xml::attrToBool(reader.attributes().value(QLatin1String("indentationsensitive")));
688 }
689 } else if (reader.name() == QLatin1String("emptyLines")) {
690 loadFoldingIgnoreList(reader);
691 } else if (reader.name() == QLatin1String("comments")) {
692 loadComments(reader);
693 } else if (reader.name() == QLatin1String("spellchecking")) {
694 loadSpellchecking(reader);
695 } else {
696 reader.skipCurrentElement();
697 }
698 reader.readNext();
699 break;
701 --elementRefCounter;
702 if (elementRefCounter == 0) {
703 return;
704 }
705 reader.readNext();
706 break;
707 default:
708 reader.readNext();
709 break;
710 }
711 }
712}
713
714void DefinitionData::loadComments(QXmlStreamReader &reader)
715{
716 Q_ASSERT(reader.name() == QLatin1String("comments"));
717 Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement);
718 reader.readNext();
719
720 // reference counter to count XML child elements, to not return too early
721 int elementRefCounter = 1;
722
723 while (!reader.atEnd()) {
724 switch (reader.tokenType()) {
726 ++elementRefCounter;
727 if (reader.name() == QLatin1String("comment")) {
728 const bool isSingleLine = reader.attributes().value(QLatin1String("name")) == QLatin1String("singleLine");
729 if (isSingleLine) {
730 singleLineCommentMarker = reader.attributes().value(QLatin1String("start")).toString();
731 const bool afterWhiteSpace = reader.attributes().value(QLatin1String("position")) == QLatin1String("afterwhitespace");
732 singleLineCommentPosition = afterWhiteSpace ? CommentPosition::AfterWhitespace : CommentPosition::StartOfLine;
733 } else {
734 multiLineCommentStartMarker = reader.attributes().value(QLatin1String("start")).toString();
735 multiLineCommentEndMarker = reader.attributes().value(QLatin1String("end")).toString();
736 }
737 }
738 reader.readNext();
739 break;
741 --elementRefCounter;
742 if (elementRefCounter == 0) {
743 return;
744 }
745 reader.readNext();
746 break;
747 default:
748 reader.readNext();
749 break;
750 }
751 }
752}
753
754void DefinitionData::loadFoldingIgnoreList(QXmlStreamReader &reader)
755{
756 Q_ASSERT(reader.name() == QLatin1String("emptyLines"));
757 Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement);
758 reader.readNext();
759
760 // reference counter to count XML child elements, to not return too early
761 int elementRefCounter = 1;
762
763 while (!reader.atEnd()) {
764 switch (reader.tokenType()) {
766 ++elementRefCounter;
767 if (reader.name() == QLatin1String("emptyLine")) {
768 foldingIgnoreList << reader.attributes().value(QLatin1String("regexpr")).toString();
769 }
770 reader.readNext();
771 break;
773 --elementRefCounter;
774 if (elementRefCounter == 0) {
775 return;
776 }
777 reader.readNext();
778 break;
779 default:
780 reader.readNext();
781 break;
782 }
783 }
784}
785
786void DefinitionData::loadSpellchecking(QXmlStreamReader &reader)
787{
788 Q_ASSERT(reader.name() == QLatin1String("spellchecking"));
789 Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement);
790 reader.readNext();
791
792 // reference counter to count XML child elements, to not return too early
793 int elementRefCounter = 1;
794
795 while (!reader.atEnd()) {
796 switch (reader.tokenType()) {
798 ++elementRefCounter;
799 if (reader.name() == QLatin1String("encoding")) {
800 const auto charRef = reader.attributes().value(QLatin1String("char"));
801 if (!charRef.isEmpty()) {
802 const auto str = reader.attributes().value(QLatin1String("string"));
803 characterEncodings.push_back({charRef[0], str.toString()});
804 }
805 }
806 reader.readNext();
807 break;
809 --elementRefCounter;
810 if (elementRefCounter == 0) {
811 return;
812 }
813 reader.readNext();
814 break;
815 default:
816 reader.readNext();
817 break;
818 }
819 }
820}
821
822bool DefinitionData::checkKateVersion(QStringView verStr)
823{
824 const auto idx = verStr.indexOf(QLatin1Char('.'));
825 if (idx <= 0) {
826 qCWarning(Log) << "Skipping" << fileName << "due to having no valid kateversion attribute:" << verStr;
827 return false;
828 }
829 const auto major = verStr.left(idx).toInt();
830 const auto minor = verStr.mid(idx + 1).toInt();
831
832 if (major > KSYNTAXHIGHLIGHTING_VERSION_MAJOR || (major == KSYNTAXHIGHLIGHTING_VERSION_MAJOR && minor > KSYNTAXHIGHLIGHTING_VERSION_MINOR)) {
833 qCWarning(Log) << "Skipping" << fileName << "due to being too new, version:" << verStr;
834 return false;
835 }
836
837 return true;
838}
839
840quint16 DefinitionData::foldingRegionId(const QString &foldName)
841{
842 hasFoldingRegions = true;
843 return RepositoryPrivate::get(repo)->foldingRegionId(name, foldName);
844}
845
846void DefinitionData::addImmediateIncludedDefinition(const Definition &def)
847{
848 if (get(def) != this) {
849 DefinitionRef defRef(def);
850 if (!immediateIncludedDefinitions.contains(defRef)) {
851 immediateIncludedDefinitions.push_back(std::move(defRef));
852 }
853 }
854}
855
856DefinitionRef::DefinitionRef() = default;
857
858DefinitionRef::DefinitionRef(const Definition &def) noexcept
859 : d(def.d)
860{
861}
862
863DefinitionRef &DefinitionRef::operator=(const Definition &def) noexcept
864{
865 d = def.d;
866 return *this;
867}
868
869Definition DefinitionRef::definition() const
870{
871 return Definition(d.lock());
872}
873
874bool DefinitionRef::operator==(const DefinitionRef &other) const
875{
876 return !d.owner_before(other.d) && !other.d.owner_before(d);
877}
878
879bool DefinitionRef::operator==(const Definition &other) const
880{
881 return !d.owner_before(other.d) && !other.d.owner_before(d);
882}
883
884#include "moc_definition.cpp"
Represents a syntax definition.
Definition definition.h:83
QString style() const
Generalized language style, used for indentation.
QStringList keywordList(const QString &name) const
Returns the list of keywords for the keyword list name.
QString singleLineCommentMarker() const
Returns the marker that starts a single line comment.
int priority() const
Returns the definition priority.
bool isValid() const
Checks whether this object refers to a valid syntax definition.
QStringList foldingIgnoreList() const
If indentationBasedFoldingEnabled() returns true, this function returns a list of regular expressions...
QString filePath() const
Returns the full path to the definition XML file containing the syntax definition.
Definition & operator=(Definition &&other) noexcept
Move assignment operator.
CommentPosition singleLineCommentPosition() const
Returns the insert position of the comment marker for sinle line comments.
bool isHidden() const
Returns true if this is an internal definition that should not be displayed to the user.
bool indentationBasedFoldingEnabled() const
Returns whether indentation-based folding is enabled.
QStringList alternativeNames() const
Alternate names the syntax can be referred to by.
Definition()
Default constructor, creating an empty (invalid) Definition instance.
QList< QString > mimeTypes() const
Mime types associated with this syntax definition.
bool operator!=(const Definition &other) const
Checks two definitions for inequality.
bool foldingEnabled() const
Returns whether the highlighting supports code folding.
bool setKeywordList(const QString &name, const QStringList &content)
Set the contents of the keyword list name to content.
bool operator==(const Definition &other) const
Checks two definitions for equality.
QPair< QString, QString > multiLineCommentMarker() const
Returns the markers that start and end multiline comments.
QList< QPair< QChar, QString > > characterEncodings() const
Returns a list of character/string mapping that can be used for spell checking.
bool isWordWrapDelimiter(QChar c) const
Returns whether it is safe to break a line at before the character .
bool isWordDelimiter(QChar c) const
Returns whether the character c is a word delimiter.
QList< QString > extensions() const
File extensions associated with this syntax definition.
int version() const
Returns the definition version.
QList< Format > formats() const
Returns a list of all Format items used by this definition.
QStringList keywordLists() const
Returns the section names of keywords.
QString indenter() const
Indentation style to be used for this syntax.
QList< Definition > includedDefinitions() const
Returns a list of Definitions that are referenced with the IncludeRules rule.
Describes the format to be used for a specific text fragment.
Definition format.h:28
QString name() const
The name of this format as used in the syntax definition file.
Definition format.cpp:96
Represents the raw xml data of a context and its rules.
KDB_EXPORT KDbVersionInfo version()
KIOCORE_EXPORT TransferJob * get(const QUrl &url, LoadType reload=NoReload, JobFlags flags=DefaultFlags)
QString name(StandardShortcut id)
Syntax highlighting engine for Kate syntax definitions.
CommentPosition
Defines the insert position when commenting code.
Definition definition.h:32
@ AfterWhitespace
The comment marker is inserted after leading whitespaces right befire the first non-whitespace charac...
@ StartOfLine
The comment marker is inserted at the beginning of a line at column 0.
QCborValue value(QLatin1StringView key) const const
bool toBool(bool defaultValue) const const
QByteArray toByteArray(const QByteArray &defaultValue) const const
qint64 toInteger(qint64 defaultValue) const const
QString toString(const QString &defaultValue) const const
QCoreApplication * instance()
QString translate(const char *context, const char *sourceText, const char *disambiguation, int n)
reference back()
QString & insert(qsizetype position, QChar ch)
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
QStringView left(qsizetype length) const const
QStringView mid(qsizetype start, qsizetype length) const const
qsizetype indexOf(QChar c, qsizetype from, Qt::CaseSensitivity cs) const const
float toFloat(bool *ok) const const
int toInt(bool *ok, int base) const const
QString toString() const const
CaseSensitive
SkipEmptyParts
bool hasAttribute(QAnyStringView namespaceUri, QAnyStringView name) const const
QStringView value(QAnyStringView namespaceUri, QAnyStringView name) const const
bool atEnd() const const
QXmlStreamAttributes attributes() const const
QStringView name() const const
TokenType readNext()
void skipCurrentElement()
TokenType tokenType() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:19:29 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.