KSyntaxHighlighting

context.cpp
1/*
2 SPDX-FileCopyrightText: 2016 Volker Krause <vkrause@kde.org>
3 SPDX-FileCopyrightText: 2020 Jonathan Poelen <jonathan.poelen@gmail.com>
4
5 SPDX-License-Identifier: MIT
6*/
7
8#include "context_p.h"
9#include "definition_p.h"
10#include "format.h"
11#include "ksyntaxhighlighting_logging.h"
12#include "rule_p.h"
13#include "xml_p.h"
14
15#include <QString>
16#include <QXmlStreamReader>
17
18using namespace KSyntaxHighlighting;
19
20Context::Context(const DefinitionData &def, const HighlightingContextData &data)
21 : m_name(data.name)
22 , m_attributeFormat(data.attribute.isEmpty() ? Format() : def.formatByName(data.attribute))
23 , m_indentationBasedFolding(!data.noIndentationBasedFolding && def.indentationBasedFolding)
24{
25 if (!data.attribute.isEmpty() && !m_attributeFormat.isValid()) {
26 qCWarning(Log) << "Context: Unknown format" << data.attribute << "in context" << m_name << "of definition" << def.name;
27 }
28}
29
30bool Context::indentationBasedFoldingEnabled() const
31{
32 return m_indentationBasedFolding;
33}
34
35void Context::resolveContexts(DefinitionData &def, const HighlightingContextData &data)
36{
37 m_lineEndContext.resolve(def, data.lineEndContext);
38 m_lineEmptyContext.resolve(def, data.lineEmptyContext);
39 m_fallthroughContext.resolve(def, data.fallthroughContext);
40 m_stopEmptyLineContextSwitchLoop = data.stopEmptyLineContextSwitchLoop;
41
42 /**
43 * line end context switches only when lineEmptyContext is #stay. This avoids
44 * skipping empty lines after a line continuation character (see bug 405903)
45 */
46 if (m_lineEmptyContext.isStay()) {
47 m_lineEmptyContext = m_lineEndContext;
48 }
49
50 m_rules.reserve(data.rules.size());
51 for (const auto &ruleData : data.rules) {
52 m_rules.push_back(Rule::create(def, ruleData, m_name));
53 if (!m_rules.back()) {
54 m_rules.pop_back();
55 }
56 }
57}
58
59void Context::resolveIncludes(DefinitionData &def)
60{
61 if (m_resolveState == Resolved) {
62 return;
63 }
64 if (m_resolveState == Resolving) {
65 qCWarning(Log) << "Cyclic dependency!";
66 return;
67 }
68
69 Q_ASSERT(m_resolveState == Unresolved);
70 m_resolveState = Resolving; // cycle guard
71
72 for (auto it = m_rules.begin(); it != m_rules.end();) {
73 const IncludeRules *includeRules = it->get()->castToIncludeRules();
74 if (!includeRules) {
75 m_hasDynamicRule = m_hasDynamicRule || it->get()->isDynamic();
76 ++it;
77 continue;
78 }
79
80 const QStringView includeContext = includeRules->contextName();
81 const qsizetype idx = includeContext.indexOf(QLatin1String("##"));
82
83 Context *context = nullptr;
84 DefinitionData *defData = &def;
85
86 if (idx <= -1) { // local include
87 context = def.contextByName(includeContext);
88 } else {
89 const auto definitionName = includeContext.sliced(idx + 2);
90 const auto contextName = includeContext.sliced(0, idx);
91 auto resolvedContext = def.resolveIncludedContext(definitionName, contextName);
92 defData = resolvedContext.def;
93 context = resolvedContext.context;
94 if (!defData) {
95 qCWarning(Log) << "Unable to resolve external include rule for definition" << definitionName << "in" << def.name;
96 }
97 }
98
99 if (!context) {
100 qCWarning(Log) << "Unable to resolve include rule for definition" << includeContext << "in" << def.name;
101 ++it;
102 continue;
103 }
104
105 if (context == this) {
106 qCWarning(Log) << "Unable to resolve self include rule for definition" << includeContext << "in" << def.name;
107 ++it;
108 continue;
109 }
110
111 if (context->m_resolveState != Resolved) {
112 context->resolveIncludes(*defData);
113 }
114
115 m_hasDynamicRule = m_hasDynamicRule || context->m_hasDynamicRule;
116
117 /**
118 * handle included attribute
119 * transitive closure: we might include attributes included from somewhere else
120 */
121 if (includeRules->includeAttribute()) {
122 m_attributeFormat = context->m_attributeFormat;
123 }
124
125 it = m_rules.erase(it);
126 it = m_rules.insert(it, context->rules().begin(), context->rules().end());
127 it += context->rules().size();
128 }
129
130 m_resolveState = Resolved;
131}
Describes the format to be used for a specific text fragment.
Definition format.h:28
Represents the raw xml data of a context and its rules.
QString attribute
attribute name, to lookup our format
QString name(GameStandardAction id)
Syntax highlighting engine for Kate syntax definitions.
bool isEmpty() const const
qsizetype indexOf(QChar c, qsizetype from, Qt::CaseSensitivity cs) const const
QStringView sliced(qsizetype pos) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:38:04 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.