File indexing completed on 2024-05-12 15:50:03
0001 /* 0002 SPDX-FileCopyrightText: 2016 Volker Krause <vkrause@kde.org> 0003 SPDX-FileCopyrightText: 2020 Jonathan Poelen <jonathan.poelen@gmail.com> 0004 0005 SPDX-License-Identifier: MIT 0006 */ 0007 0008 #include "context_p.h" 0009 #include "definition_p.h" 0010 #include "format.h" 0011 #include "ksyntaxhighlighting_logging.h" 0012 #include "repository.h" 0013 #include "rule_p.h" 0014 #include "xml_p.h" 0015 0016 #include <QString> 0017 #include <QXmlStreamReader> 0018 0019 using namespace KSyntaxHighlighting; 0020 0021 Context::Context(const DefinitionData &def, const HighlightingContextData &data) 0022 : m_name(data.name) 0023 , m_attributeFormat(data.attribute.isEmpty() ? Format() : def.formatByName(data.attribute)) 0024 , m_indentationBasedFolding(!data.noIndentationBasedFolding && def.indentationBasedFolding) 0025 { 0026 if (!data.attribute.isEmpty() && !m_attributeFormat.isValid()) { 0027 qCWarning(Log) << "Context: Unknown format" << data.attribute << "in context" << m_name << "of definition" << def.name; 0028 } 0029 } 0030 0031 bool Context::indentationBasedFoldingEnabled() const 0032 { 0033 return m_indentationBasedFolding; 0034 } 0035 0036 void Context::resolveContexts(DefinitionData &def, const HighlightingContextData &data) 0037 { 0038 m_lineEndContext.resolve(def, data.lineEndContext); 0039 m_lineEmptyContext.resolve(def, data.lineEmptyContext); 0040 m_fallthroughContext.resolve(def, data.fallthroughContext); 0041 m_fallthrough = !m_fallthroughContext.isStay(); 0042 0043 m_rules.reserve(data.rules.size()); 0044 for (const auto &ruleData : data.rules) { 0045 m_rules.push_back(Rule::create(def, ruleData, m_name)); 0046 if (!m_rules.back()) { 0047 m_rules.pop_back(); 0048 } 0049 } 0050 } 0051 0052 void Context::resolveIncludes(DefinitionData &def) 0053 { 0054 if (m_resolveState == Resolved) { 0055 return; 0056 } 0057 if (m_resolveState == Resolving) { 0058 qCWarning(Log) << "Cyclic dependency!"; 0059 return; 0060 } 0061 0062 Q_ASSERT(m_resolveState == Unresolved); 0063 m_resolveState = Resolving; // cycle guard 0064 0065 for (auto it = m_rules.begin(); it != m_rules.end();) { 0066 const IncludeRules *includeRules = it->get()->castToIncludeRules(); 0067 if (!includeRules) { 0068 ++it; 0069 continue; 0070 } 0071 0072 Context *context = nullptr; 0073 DefinitionData *defData = &def; 0074 0075 const auto &contextName = includeRules->contextName(); 0076 const int idx = contextName.indexOf(QLatin1String("##")); 0077 0078 if (idx == -1) { // local include 0079 context = def.contextByName(contextName); 0080 } else { 0081 auto definitionName = contextName.mid(idx + 2); 0082 auto includedDef = def.repo->definitionForName(definitionName); 0083 if (!includedDef.isValid()) { 0084 qCWarning(Log) << "Unable to resolve external include rule for definition" << definitionName << "in" << def.name; 0085 ++it; 0086 continue; 0087 } 0088 defData = DefinitionData::get(includedDef); 0089 def.addImmediateIncludedDefinition(includedDef); 0090 defData->load(); 0091 if (idx == 0) { 0092 context = defData->initialContext(); 0093 } else { 0094 context = defData->contextByName(QStringView(contextName).left(idx)); 0095 } 0096 } 0097 0098 if (!context) { 0099 qCWarning(Log) << "Unable to resolve include rule for definition" << contextName << "in" << def.name; 0100 ++it; 0101 continue; 0102 } 0103 0104 if (context == this) { 0105 qCWarning(Log) << "Unable to resolve self include rule for definition" << contextName << "in" << def.name; 0106 ++it; 0107 continue; 0108 } 0109 0110 if (context->m_resolveState != Resolved) { 0111 context->resolveIncludes(*defData); 0112 } 0113 0114 /** 0115 * handle included attribute 0116 * transitive closure: we might include attributes included from somewhere else 0117 */ 0118 if (includeRules->includeAttribute()) { 0119 m_attributeFormat = context->m_attributeFormat; 0120 } 0121 0122 it = m_rules.erase(it); 0123 it = m_rules.insert(it, context->rules().begin(), context->rules().end()); 0124 it += context->rules().size(); 0125 } 0126 0127 m_resolveState = Resolved; 0128 }