KSyntaxHighlighting

keywordlist.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 "definition_p.h"
9 #include "keywordlist_p.h"
10 #include "ksyntaxhighlighting_logging.h"
11 #include "repository.h"
12 
13 #include <QXmlStreamReader>
14 
15 #include <algorithm>
16 
17 using namespace KSyntaxHighlighting;
18 
19 namespace
20 {
21 struct KeywordComparator {
22  Qt::CaseSensitivity caseSensitive;
23 
24  bool operator()(QStringView a, QStringView b) const
25  {
26  if (a.size() < b.size()) {
27  return true;
28  }
29 
30  if (a.size() > b.size()) {
31  return false;
32  }
33 
34  return a.compare(b, caseSensitive) < 0;
35  }
36 };
37 
38 }
39 
40 bool KeywordList::contains(QStringView str, Qt::CaseSensitivity caseSensitive) const
41 {
42  /**
43  * get right vector to search in
44  */
45  const auto &vectorToSearch = (caseSensitive == Qt::CaseSensitive) ? m_keywordsSortedCaseSensitive : m_keywordsSortedCaseInsensitive;
46 
47  /**
48  * search with right predicate
49  */
50  return std::binary_search(vectorToSearch.begin(), vectorToSearch.end(), QStringView(str), KeywordComparator{caseSensitive});
51 }
52 
53 void KeywordList::load(QXmlStreamReader &reader)
54 {
55  Q_ASSERT(reader.name() == QLatin1String("list"));
56  Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement);
57 
58  m_name = reader.attributes().value(QLatin1String("name")).toString();
59 
60  while (!reader.atEnd()) {
61  switch (reader.tokenType()) {
63  if (reader.name() == QLatin1String("item")) {
64  m_keywords.append(reader.readElementText().trimmed());
65  reader.readNextStartElement();
66  break;
67  } else if (reader.name() == QLatin1String("include")) {
68  m_includes.append(reader.readElementText().trimmed());
69  reader.readNextStartElement();
70  break;
71  }
72  reader.readNext();
73  break;
75  reader.readNext();
76  return;
77  default:
78  reader.readNext();
79  break;
80  }
81  }
82 }
83 
84 void KeywordList::setCaseSensitivity(Qt::CaseSensitivity caseSensitive)
85 {
86  /**
87  * remember default case-sensitivity and init lookup for it
88  */
89  m_caseSensitive = caseSensitive;
90  initLookupForCaseSensitivity(m_caseSensitive);
91 }
92 
93 void KeywordList::initLookupForCaseSensitivity(Qt::CaseSensitivity caseSensitive)
94 {
95  /**
96  * get right vector to sort, if non-empty, we are done
97  */
98  auto &vectorToSort = (caseSensitive == Qt::CaseSensitive) ? m_keywordsSortedCaseSensitive : m_keywordsSortedCaseInsensitive;
99  if (!vectorToSort.empty()) {
100  return;
101  }
102 
103  /**
104  * fill vector with refs to keywords
105  */
106  vectorToSort.reserve(m_keywords.size());
107  for (const auto &keyword : std::as_const(m_keywords)) {
108  vectorToSort.push_back(keyword);
109  }
110 
111  /**
112  * sort with right predicate
113  */
114  std::sort(vectorToSort.begin(), vectorToSort.end(), KeywordComparator{caseSensitive});
115 }
116 
117 void KeywordList::resolveIncludeKeywords(DefinitionData &def)
118 {
119  while (!m_includes.isEmpty()) {
120  const auto kw_include = std::move(m_includes.back());
121  m_includes.pop_back();
122 
123  const auto idx = kw_include.indexOf(QLatin1String("##"));
124  KeywordList *keywords = nullptr;
125 
126  if (idx >= 0) {
127  auto defName = kw_include.mid(idx + 2);
128  auto includeDef = def.repo->definitionForName(defName);
129  if (includeDef.isValid()) {
130  auto listName = kw_include.left(idx);
131  auto defData = DefinitionData::get(includeDef);
132  defData->load(DefinitionData::OnlyKeywords(true));
133  keywords = defData->keywordList(listName);
134  } else {
135  qCWarning(Log) << "Unable to resolve external include keyword for definition" << defName << "in" << def.name;
136  }
137  } else {
138  keywords = def.keywordList(kw_include);
139  }
140 
141  if (keywords) {
142  if (this != keywords) {
143  keywords->resolveIncludeKeywords(def);
144  }
145  m_keywords += keywords->m_keywords;
146  } else {
147  qCWarning(Log) << "Unresolved include keyword" << kw_include << "in" << def.name;
148  }
149  }
150 }
CaseSensitivity
QStringRef value(const QString &namespaceUri, const QString &name) const const
bool readNextStartElement()
QString trimmed() const const
qsizetype size() const const
QStringRef name() const const
QXmlStreamReader::TokenType readNext()
QXmlStreamReader::TokenType tokenType() const const
QString readElementText(QXmlStreamReader::ReadElementTextBehaviour behaviour)
QXmlStreamAttributes attributes() const const
QString toString() const const
int compare(QStringView str, Qt::CaseSensitivity cs) const const
bool atEnd() const const
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.