File indexing completed on 2024-05-12 04:37:47
0001 /* 0002 SPDX-FileCopyrightText: 2008 David Nolden <david.nolden.kdevelop@art-master.de> 0003 0004 SPDX-License-Identifier: LGPL-2.0-only 0005 */ 0006 0007 #ifndef KDEVPLATFORM_CODEREPRESENTATION_H 0008 #define KDEVPLATFORM_CODEREPRESENTATION_H 0009 0010 #include <language/languageexport.h> 0011 #include <serialization/indexedstring.h> 0012 0013 #include <KTextEditor/ConfigInterface> 0014 #include <KTextEditor/Document> 0015 0016 #include <memory> 0017 0018 class QString; 0019 0020 namespace KTextEditor { 0021 class Range; 0022 } 0023 0024 namespace KDevelop { 0025 struct KDevEditingTransaction; 0026 0027 class IndexedString; 0028 0029 //NOTE: this is ugly, but otherwise kate might remove tabs again :-/ 0030 // see also: https://bugs.kde.org/show_bug.cgi?id=291074 0031 struct EditorDisableReplaceTabs 0032 { 0033 explicit EditorDisableReplaceTabs(KTextEditor::Document* document) : m_iface(qobject_cast<KTextEditor::ConfigInterface*>( 0034 document)) 0035 , m_count(0) 0036 { 0037 ++m_count; 0038 if (m_count > 1) 0039 return; 0040 if (m_iface) { 0041 m_oldReplaceTabs = m_iface->configValue(configKey()); 0042 m_iface->setConfigValue(configKey(), false); 0043 } 0044 } 0045 0046 ~EditorDisableReplaceTabs() 0047 { 0048 --m_count; 0049 if (m_count > 0) 0050 return; 0051 0052 Q_ASSERT(m_count == 0); 0053 0054 if (m_iface) 0055 m_iface->setConfigValue(configKey(), m_oldReplaceTabs); 0056 } 0057 0058 inline QString configKey() const 0059 { 0060 return QStringLiteral("replace-tabs"); 0061 } 0062 0063 private: 0064 Q_DISABLE_COPY(EditorDisableReplaceTabs) 0065 0066 KTextEditor::ConfigInterface* m_iface; 0067 int m_count; 0068 QVariant m_oldReplaceTabs; 0069 }; 0070 0071 struct KDevEditingTransaction 0072 { 0073 explicit KDevEditingTransaction(KTextEditor::Document* document) 0074 : edit(document) 0075 , disableReplaceTabs(document) 0076 {} 0077 // NOTE: It's important to close the transaction first and only then destroy the EditorDisableReplaceTabs. Otherwise we hit asserts in KTextEditor. 0078 KTextEditor::Document::EditingTransaction edit; 0079 EditorDisableReplaceTabs disableReplaceTabs; 0080 using Ptr = std::unique_ptr<KDevEditingTransaction>; 0081 }; 0082 0083 /** 0084 * Allows getting code-lines conveniently, either through an open editor, or from a disk-loaded file. 0085 */ 0086 class KDEVPLATFORMLANGUAGE_EXPORT CodeRepresentation 0087 : public QSharedData 0088 { 0089 public: 0090 virtual ~CodeRepresentation() 0091 { 0092 } 0093 virtual QString line(int line) const = 0; 0094 virtual int lines() const = 0; 0095 virtual QString text() const = 0; 0096 virtual QString rangeText(const KTextEditor::Range& range) const; 0097 /** 0098 * Search for the given identifier in the document, and returns all ranges 0099 * where it was found. 0100 * @param identifier The identifier to search for 0101 * @param surroundedByBoundary Whether only matches that are surrounded by typical word-boundaries 0102 * should be acceded. Everything except letters, numbers, and the _ character 0103 * counts as word boundary. 0104 * */ 0105 virtual QVector<KTextEditor::Range> grep(const QString& identifier, bool surroundedByBoundary = true) const = 0; 0106 /** 0107 * Overwrites the text in the file with the new given one 0108 * 0109 * @return true on success 0110 */ 0111 virtual bool setText(const QString&) = 0; 0112 /** @return true if this representation represents an actual file on disk */ 0113 virtual bool fileExists() const = 0; 0114 0115 /** 0116 * Can be used for example from tests to disallow on-disk changes. When such a change is done, an assertion is triggered. 0117 * You should enable this within tests, unless you really want to work on the disk. 0118 */ 0119 static void setDiskChangesForbidden(bool changesForbidden); 0120 0121 /** 0122 * Returns the specified name as a url for artificial source code 0123 * suitable for code being inserted into the parser 0124 */ 0125 static QString artificialPath(const QString& name); 0126 0127 using Ptr = QExplicitlySharedDataPointer<CodeRepresentation>; 0128 }; 0129 0130 class KDEVPLATFORMLANGUAGE_EXPORT DynamicCodeRepresentation 0131 : public CodeRepresentation 0132 { 0133 public: 0134 /** Used to group edit-history together. Call this optionally before a bunch 0135 * of replace() calls, to group them together. */ 0136 virtual KDevEditingTransaction::Ptr makeEditTransaction() = 0; 0137 virtual bool replace(const KTextEditor::Range& range, const QString& oldText, 0138 const QString& newText, bool ignoreOldText = false) = 0; 0139 0140 using Ptr = QExplicitlySharedDataPointer<DynamicCodeRepresentation>; 0141 }; 0142 0143 /** 0144 * Creates a code-representation for the given url, that allows conveniently accessing its data. Returns zero on failure. 0145 */ 0146 KDEVPLATFORMLANGUAGE_EXPORT CodeRepresentation::Ptr createCodeRepresentation(const IndexedString& url); 0147 0148 /** 0149 * @return true if an artificial code representation already exists for the specified URL 0150 */ 0151 KDEVPLATFORMLANGUAGE_EXPORT bool artificialCodeRepresentationExists(const IndexedString& url); 0152 0153 /** 0154 * Allows inserting artificial source-code into the code-representation and parsing framework. 0155 * The source-code logically represents a file. 0156 * 0157 * The artificial code is automatically removed when the object is destroyed. 0158 */ 0159 class KDEVPLATFORMLANGUAGE_EXPORT InsertArtificialCodeRepresentation 0160 : public QSharedData 0161 { 0162 public: 0163 /** 0164 * Inserts an artificial source-code representation with filename @p file and the contents @p text 0165 * If @p file is not an absolute path or url, it will be made absolute using the CodeRepresentation::artificialUrl() 0166 * function, while ensuring that the name is unique. 0167 */ 0168 InsertArtificialCodeRepresentation(const IndexedString& file, const QString& text); 0169 ~InsertArtificialCodeRepresentation(); 0170 InsertArtificialCodeRepresentation(const InsertArtificialCodeRepresentation&) = delete; 0171 InsertArtificialCodeRepresentation& operator=(const InsertArtificialCodeRepresentation&) = delete; 0172 0173 void setText(const QString& text); 0174 QString text() const; 0175 /** 0176 * Returns the file-name for this code-representation. 0177 */ 0178 IndexedString file(); 0179 0180 private: 0181 IndexedString m_file; 0182 }; 0183 0184 using InsertArtificialCodeRepresentationPointer = QExplicitlySharedDataPointer<InsertArtificialCodeRepresentation>; 0185 } 0186 0187 #endif