Changeset View
Changeset View
Standalone View
Standalone View
plugins/clang/codecompletion/model.cpp
Show All 31 Lines | |||||
32 | #include <language/codecompletion/codecompletionworker.h> | 32 | #include <language/codecompletion/codecompletionworker.h> | ||
33 | #include <language/duchain/topducontext.h> | 33 | #include <language/duchain/topducontext.h> | ||
34 | #include <language/duchain/duchainutils.h> | 34 | #include <language/duchain/duchainutils.h> | ||
35 | #include <language/duchain/duchainlock.h> | 35 | #include <language/duchain/duchainlock.h> | ||
36 | 36 | | |||
37 | #include <KTextEditor/View> | 37 | #include <KTextEditor/View> | ||
38 | #include <KTextEditor/Document> | 38 | #include <KTextEditor/Document> | ||
39 | 39 | | |||
40 | #include <QTimer> | ||||
41 | | ||||
40 | using namespace KDevelop; | 42 | using namespace KDevelop; | ||
41 | 43 | | |||
42 | namespace { | 44 | namespace { | ||
43 | 45 | | |||
44 | bool isSpaceOnly(const QString& string) | 46 | bool isSpaceOnly(const QString& string) | ||
45 | { | 47 | { | ||
46 | return std::find_if(string.begin(), string.end(), [] (const QChar c) { return !c.isSpace(); }) == string.end(); | 48 | return std::find_if(string.begin(), string.end(), [] (const QChar c) { return !c.isSpace(); }) == string.end(); | ||
47 | } | 49 | } | ||
Show All 26 Lines | 75 | ClangCodeCompletionWorker(ClangIndex* index, CodeCompletionModel* model) | |||
74 | : CodeCompletionWorker(model) | 76 | : CodeCompletionWorker(model) | ||
75 | , m_index(index) | 77 | , m_index(index) | ||
76 | {} | 78 | {} | ||
77 | ~ClangCodeCompletionWorker() override = default; | 79 | ~ClangCodeCompletionWorker() override = default; | ||
78 | 80 | | |||
79 | public Q_SLOTS: | 81 | public Q_SLOTS: | ||
80 | void completionRequested(const QUrl &url, const KTextEditor::Cursor& position, const QString& text, const QString& followingText) | 82 | void completionRequested(const QUrl &url, const KTextEditor::Cursor& position, const QString& text, const QString& followingText) | ||
81 | { | 83 | { | ||
84 | // group requests and only handle the latest one | ||||
85 | m_url = url; | ||||
86 | m_position = position; | ||||
87 | m_text = text; | ||||
88 | m_followingText = followingText; | ||||
89 | | ||||
90 | if (!m_timer) { | ||||
brauch: Can you not use QMetaObject::invokeMethod(this, &ClangCodeCompletionWorker::run, Qt… | |||||
yes, but as you say it's 5.10 - this code here is fine and a bit better than using QTimer::singleShot since that would recreate the timer continously mwolff: yes, but as you say it's 5.10 - this code here is fine and a bit better than using QTimer… | |||||
Eh, never mind me, wouldn't work -- you need the timer object for the merging, calling invokeMethod several times would still invoke the slot more than once. Sorry. brauch: Eh, never mind me, wouldn't work -- you need the timer object for the merging, calling… | |||||
91 | // lazy-load the timer to initialize it in the background thread | ||||
92 | m_timer = new QTimer(this); | ||||
93 | m_timer->setInterval(0); | ||||
94 | m_timer->setSingleShot(true); | ||||
95 | connect(m_timer, &QTimer::timeout, this, &ClangCodeCompletionWorker::run); | ||||
96 | } | ||||
97 | m_timer->start(); | ||||
98 | } | ||||
99 | | ||||
100 | private: | ||||
101 | void run() | ||||
102 | { | ||||
82 | aborting() = false; | 103 | aborting() = false; | ||
83 | 104 | | |||
84 | DUChainReadLocker lock; | 105 | DUChainReadLocker lock; | ||
85 | if (aborting()) { | 106 | if (aborting()) { | ||
86 | failed(); | 107 | failed(); | ||
87 | return; | 108 | return; | ||
88 | } | 109 | } | ||
89 | 110 | | |||
90 | auto top = DUChainUtils::standardContextForUrl(url); | 111 | auto top = DUChainUtils::standardContextForUrl(m_url); | ||
91 | if (!top) { | 112 | if (!top) { | ||
92 | qCWarning(KDEV_CLANG) << "No context found for" << url; | 113 | qCWarning(KDEV_CLANG) << "No context found for" << m_url; | ||
93 | return; | 114 | return; | ||
94 | } | 115 | } | ||
95 | 116 | | |||
96 | ParseSessionData::Ptr sessionData(ClangIntegration::DUChainUtils::findParseSessionData(top->url(), m_index->translationUnitForUrl(top->url()))); | 117 | ParseSessionData::Ptr sessionData(ClangIntegration::DUChainUtils::findParseSessionData(top->url(), m_index->translationUnitForUrl(top->url()))); | ||
97 | 118 | | |||
98 | if (!sessionData) { | 119 | if (!sessionData) { | ||
99 | // TODO: trigger reparse and re-request code completion | 120 | // TODO: trigger reparse and re-request code completion | ||
100 | qCWarning(KDEV_CLANG) << "No parse session / AST attached to context for url" << url; | 121 | qCWarning(KDEV_CLANG) << "No parse session / AST attached to context for url" << m_url; | ||
101 | return; | 122 | return; | ||
102 | } | 123 | } | ||
103 | 124 | | |||
104 | if (aborting()) { | 125 | if (aborting()) { | ||
105 | failed(); | 126 | failed(); | ||
106 | return; | 127 | return; | ||
107 | } | 128 | } | ||
108 | 129 | | |||
109 | // We hold DUChain lock, and ask for ParseSession, but TUDUChain indirectly holds ParseSession lock. | 130 | // We hold DUChain lock, and ask for ParseSession, but TUDUChain indirectly holds ParseSession lock. | ||
110 | lock.unlock(); | 131 | lock.unlock(); | ||
111 | 132 | | |||
112 | auto completionContext = ::createCompletionContext(DUContextPointer(top), sessionData, url, position, text, followingText); | 133 | auto completionContext = ::createCompletionContext(DUContextPointer(top), sessionData, m_url, | ||
134 | m_position, m_text, m_followingText); | ||||
113 | 135 | | |||
114 | lock.lock(); | 136 | lock.lock(); | ||
115 | if (aborting()) { | 137 | if (aborting()) { | ||
116 | failed(); | 138 | failed(); | ||
117 | return; | 139 | return; | ||
118 | } | 140 | } | ||
119 | 141 | | |||
120 | bool abort = false; | 142 | bool abort = false; | ||
Show All 15 Lines | |||||
136 | } | 158 | } | ||
137 | 159 | | |||
138 | tree += completionContext->ungroupedElements(); | 160 | tree += completionContext->ungroupedElements(); | ||
139 | 161 | | |||
140 | foundDeclarations( tree, {} ); | 162 | foundDeclarations( tree, {} ); | ||
141 | } | 163 | } | ||
142 | private: | 164 | private: | ||
143 | ClangIndex* m_index; | 165 | ClangIndex* m_index; | ||
166 | QTimer* m_timer = nullptr; | ||||
167 | QUrl m_url; | ||||
168 | KTextEditor::Cursor m_position; | ||||
169 | QString m_text; | ||||
170 | QString m_followingText; | ||||
144 | }; | 171 | }; | ||
145 | } | 172 | } | ||
146 | 173 | | |||
147 | ClangCodeCompletionModel::ClangCodeCompletionModel(ClangIndex* index, QObject* parent) | 174 | ClangCodeCompletionModel::ClangCodeCompletionModel(ClangIndex* index, QObject* parent) | ||
148 | : CodeCompletionModel(parent) | 175 | : CodeCompletionModel(parent) | ||
149 | , m_index(index) | 176 | , m_index(index) | ||
150 | { | 177 | { | ||
151 | qRegisterMetaType<KTextEditor::Cursor>(); | 178 | qRegisterMetaType<KTextEditor::Cursor>(); | ||
▲ Show 20 Lines • Show All 65 Lines • Show Last 20 Lines |
Can you not use QMetaObject::invokeMethod(this, &ClangCodeCompletionWorker::run, Qt::QueuedConnection) instead of this timer? (The function pointer syntax is Qt 5.10+ though I think)