KSyntaxHighlighting

context.cpp
1 /*
2  SPDX-FileCopyrightText: 2016 Volker Krause <[email protected]>
3  SPDX-FileCopyrightText: 2020 Jonathan Poelen <[email protected]>
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 "repository.h"
13 #include "rule_p.h"
14 #include "xml_p.h"
15 
16 #include <QString>
17 #include <QXmlStreamReader>
18 
19 using namespace KSyntaxHighlighting;
20 
21 Context::Context(const DefinitionData &def, const HighlightingContextData &data)
22  : m_name(data.name)
23  , m_attributeFormat(data.attribute.isEmpty() ? Format() : def.formatByName(data.attribute))
24  , m_indentationBasedFolding(!data.noIndentationBasedFolding && def.indentationBasedFolding)
25 {
26  if (!data.attribute.isEmpty() && !m_attributeFormat.isValid()) {
27  qCWarning(Log) << "Context: Unknown format" << data.attribute << "in context" << m_name << "of definition" << def.name;
28  }
29 }
30 
31 bool Context::indentationBasedFoldingEnabled() const
32 {
33  return m_indentationBasedFolding;
34 }
35 
36 void Context::resolveContexts(DefinitionData &def, const HighlightingContextData &data)
37 {
38  m_lineEndContext.resolve(def, data.lineEndContext);
39  m_lineEmptyContext.resolve(def, data.lineEmptyContext);
40  m_fallthroughContext.resolve(def, data.fallthroughContext);
41  m_fallthrough = !m_fallthroughContext.isStay();
42 
43  m_rules.reserve(data.rules.size());
44  for (const auto &ruleData : data.rules) {
45  m_rules.push_back(Rule::create(def, ruleData, m_name));
46  if (!m_rules.back()) {
47  m_rules.pop_back();
48  }
49  }
50 }
51 
52 void Context::resolveIncludes(DefinitionData &def)
53 {
54  if (m_resolveState == Resolved) {
55  return;
56  }
57  if (m_resolveState == Resolving) {
58  qCWarning(Log) << "Cyclic dependency!";
59  return;
60  }
61 
62  Q_ASSERT(m_resolveState == Unresolved);
63  m_resolveState = Resolving; // cycle guard
64 
65  for (auto it = m_rules.begin(); it != m_rules.end();) {
66  const IncludeRules *includeRules = it->get()->castToIncludeRules();
67  if (!includeRules) {
68  ++it;
69  continue;
70  }
71 
72  Context *context = nullptr;
73  DefinitionData *defData = &def;
74 
75  const auto &contextName = includeRules->contextName();
76  const int idx = contextName.indexOf(QLatin1String("##"));
77 
78  if (idx == -1) { // local include
79  context = def.contextByName(contextName);
80  } else {
81  auto definitionName = contextName.mid(idx + 2);
82  auto includedDef = def.repo->definitionForName(definitionName);
83  if (!includedDef.isValid()) {
84  qCWarning(Log) << "Unable to resolve external include rule for definition" << definitionName << "in" << def.name;
85  ++it;
86  continue;
87  }
88  defData = DefinitionData::get(includedDef);
89  def.addImmediateIncludedDefinition(includedDef);
90  defData->load();
91  if (idx == 0) {
92  context = defData->initialContext();
93  } else {
94  context = defData->contextByName(QStringView(contextName).left(idx));
95  }
96  }
97 
98  if (!context) {
99  qCWarning(Log) << "Unable to resolve include rule for definition" << contextName << "in" << def.name;
100  ++it;
101  continue;
102  }
103 
104  if (context == this) {
105  qCWarning(Log) << "Unable to resolve self include rule for definition" << contextName << "in" << def.name;
106  ++it;
107  continue;
108  }
109 
110  if (context->m_resolveState != Resolved) {
111  context->resolveIncludes(*defData);
112  }
113 
114  /**
115  * handle included attribute
116  * transitive closure: we might include attributes included from somewhere else
117  */
118  if (includeRules->includeAttribute()) {
119  m_attributeFormat = context->m_attributeFormat;
120  }
121 
122  it = m_rules.erase(it);
123  it = m_rules.insert(it, context->rules().begin(), context->rules().end());
124  it += context->rules().size();
125  }
126 
127  m_resolveState = Resolved;
128 }
Represents the raw xml data of a context and its rules.
QTextStream & left(QTextStream &stream)
Describes the format to be used for a specific text fragment.
Definition: format.h:33
void reserve(int size)
bool isEmpty() const const
QString name(StandardShortcut id)
QString attribute
attribute name, to lookup our format
virtual QVariant get(ScriptableExtension *callerPrincipal, quint64 objId, const QString &propName)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sun Mar 26 2023 04:09:17 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.