language/duchain
abstractusebuilder.h
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef ABSTRACTUSEBUILDER_H
00020 #define ABSTRACTUSEBUILDER_H
00021
00022 #include "../declaration.h"
00023 #include "../use.h"
00024 #include "../topducontext.h"
00025 #include "../duchain.h"
00026 #include "../duchainlock.h"
00027
00028 #include <language/editor/editorintegrator.h>
00029 #include <ktexteditor/smartinterface.h>
00030
00031 namespace KDevelop {
00032
00043 template<typename T, typename NameT, typename LanguageSpecificUseBuilderBase>
00044 class AbstractUseBuilder: public LanguageSpecificUseBuilderBase
00045 {
00046 public:
00048 AbstractUseBuilder()
00049 : m_finishContext(true)
00050 {
00051 }
00052
00059 void buildUses(T *node)
00060 {
00061 TopDUContext* top = dynamic_cast<TopDUContext*>(contextFromNode(node));
00062
00063 if (top) {
00064 DUChainWriteLocker lock(DUChain::lock());
00065 top->clearUsedDeclarationIndices();
00066 if(top->features() & TopDUContext::AllDeclarationsContextsAndUses)
00067 LanguageSpecificUseBuilderBase::setRecompiling(true);
00068 }
00069
00070 LanguageSpecificUseBuilderBase::supportBuild(node);
00071 }
00072
00073 protected:
00080 struct ContextUseTracker {
00081 QSet<KTextEditor::SmartRange*> reuseRanges;
00082 QList<QPair<KDevelop::Use, KTextEditor::SmartRange*> > createUses;
00083 };
00084
00085 void newUse(NameT* name)
00086 {
00087 QualifiedIdentifier id = identifierForNode(name);
00088
00089 SimpleRange newRange = editorFindRange(name, name);
00090
00091 DUChainWriteLocker lock(DUChain::lock());
00092 QList<Declaration*> declarations = LanguageSpecificUseBuilderBase::currentContext()->findDeclarations(id, newRange.start);
00093 foreach (Declaration* declaration, declarations)
00094 if (!declaration->isForwardDeclaration()) {
00095 declarations.clear();
00096 declarations.append(declaration);
00097 break;
00098 }
00099
00100
00101 lock.unlock();
00102 newUse( name, newRange, !declarations.isEmpty() ? declarations.first() : 0 );
00103 }
00104
00106
00113 void newUse(T* node, KDevelop::Declaration* declaration)
00114 {
00115 newUse(node, editorFindRange(node, node), declaration);
00116 }
00117
00124 void newUse(T* node, const SimpleRange& newRange, Declaration* declaration)
00125 {
00126 DUChainWriteLocker lock(DUChain::lock());
00127
00128 bool encountered = false;
00129 int declarationIndex = LanguageSpecificUseBuilderBase::currentContext()->topContext()->indexForUsedDeclaration(declaration);
00130 int contextUpSteps = 0;
00131
00132 {
00133
00134 LockedSmartInterface iface = LanguageSpecificUseBuilderBase::editor()->smart();
00135 SimpleRange translated = LanguageSpecificUseBuilderBase::editor()->translate(iface, newRange);
00136
00137
00138
00139
00140 KTextEditor::Range textTranslated = translated.textRange();
00141
00142
00143
00144
00145
00146
00147
00148
00149 DUContext* newContext = LanguageSpecificUseBuilderBase::currentContext();
00150 while (!newContext->range().contains(translated) && contextUpSteps < (LanguageSpecificUseBuilderBase::contextStack().size()-1)) {
00151 ++contextUpSteps;
00152 newContext = LanguageSpecificUseBuilderBase::contextStack()[LanguageSpecificUseBuilderBase::contextStack().size()-1-contextUpSteps];
00153 }
00154
00155 KTextEditor::SmartRange* use = 0;
00156
00157 if (contextUpSteps) {
00158 LanguageSpecificUseBuilderBase::editor()->setCurrentRange(iface, newContext->smartRange());
00159 m_finishContext = false;
00160 openContext(newContext);
00161 m_finishContext = true;
00162 currentUseTracker() = m_trackerStack.at(m_trackerStack.size()-contextUpSteps-2);
00163
00164 Q_ASSERT(m_contexts[m_trackerStack.size()-contextUpSteps-2] == LanguageSpecificUseBuilderBase::currentContext());
00165 }
00166
00167 if (LanguageSpecificUseBuilderBase::recompiling() && this->currentContext()->smartRange()) {
00168
00169
00170 KTextEditor::SmartRange* containerRange = this->currentContext()->smartRange();
00171 KTextEditor::SmartRange* child = containerRange->mostSpecificRange(textTranslated);
00172 while(child && child->parentRange() != containerRange)
00173 child = child->parentRange();
00174
00175
00176 while(child && child->end() == textTranslated.end() && (!currentUseTracker().reuseRanges.contains(child) || *child != textTranslated))
00177 child = containerRange->childAfter(child);
00178
00179 if(child && *child == textTranslated && currentUseTracker().reuseRanges.contains(child)) {
00180
00181 currentUseTracker().reuseRanges.remove(child);
00182 use = child;
00183 }
00184 }
00185 if (!encountered) {
00186 if(!use) {
00187 use = LanguageSpecificUseBuilderBase::editor()->currentRange(iface) ? LanguageSpecificUseBuilderBase::editor()->createRange(iface, newRange.textRange()) : 0;
00188 LanguageSpecificUseBuilderBase::editor()->exitCurrentRange(iface);
00189 }
00190
00191 if (LanguageSpecificUseBuilderBase::m_mapAst)
00192 LanguageSpecificUseBuilderBase::editor()->parseSession()->mapAstUse(
00193 node, qMakePair<DUContextPointer, SimpleRange>(DUContextPointer(newContext), newRange));
00194
00195 currentUseTracker().createUses << qMakePair(KDevelop::Use(newRange, declarationIndex), use);
00196 }
00197 }
00198
00199 if (contextUpSteps) {
00200 Q_ASSERT(m_contexts[m_trackerStack.size()-contextUpSteps-2] == LanguageSpecificUseBuilderBase::currentContext());
00201 m_trackerStack[m_trackerStack.size()-contextUpSteps-2] = currentUseTracker();
00202 m_finishContext = false;
00203 closeContext();
00204 m_finishContext = true;
00205 }
00206 }
00207
00211 virtual void openContext(KDevelop::DUContext* newContext)
00212 {
00213 LanguageSpecificUseBuilderBase::openContext(newContext);
00214
00215 DUChainWriteLocker lock(DUChain::lock());
00216 LockedSmartInterface iface = LanguageSpecificUseBuilderBase::editor()->smart();
00217
00218 ContextUseTracker newTracker;
00219 foreach(KTextEditor::SmartRange* range, newContext->useRanges())
00220 newTracker.reuseRanges.insert(range);
00221
00222 m_trackerStack.push(newTracker);
00223 m_contexts.push(newContext);
00224 }
00225
00229 virtual void closeContext()
00230 {
00231 if(m_finishContext) {
00232 DUChainWriteLocker lock(DUChain::lock());
00233
00234 LockedSmartInterface iface = LanguageSpecificUseBuilderBase::editor()->smart();
00235
00236 if(this->currentContext()->smartRange() && iface) {
00237 this->currentContext()->takeUseRanges();
00238 foreach(KTextEditor::SmartRange* range, currentUseTracker().reuseRanges) {
00239 #ifdef DEBUG_UPDATE_MATCHING
00240 if(!range->isEmpty())
00241 kDebug() << "deleting not re-used range:" << *range;
00242 #endif
00243 delete range;
00244 }
00245 }
00246
00247 this->currentContext()->deleteUses();
00248
00249 Q_ASSERT(this->currentContext()->usesCount() == 0);
00250
00251 ContextUseTracker& tracker(currentUseTracker());
00252 for(int a = 0; a < tracker.createUses.size(); ++a) {
00253 KTextEditor::SmartRange* range = 0;
00254
00255 if(this->currentContext()->smartRange() && iface) {
00256 range = tracker.createUses[a].second;
00257 Q_ASSERT(range);
00258 }
00259
00260 Q_ASSERT(this->currentContext()->usesCount() == a);
00261 this->currentContext()->createUse(tracker.createUses[a].first.m_declarationIndex, tracker.createUses[a].first.m_range, range);
00262 }
00263
00264 }
00265
00266 LanguageSpecificUseBuilderBase::closeContext();
00267
00268 m_trackerStack.pop();
00269 m_contexts.pop();
00270 }
00271
00272 private:
00273 inline ContextUseTracker& currentUseTracker() { return m_trackerStack.top(); }
00274 QStack<ContextUseTracker> m_trackerStack;
00275 QStack<KDevelop::DUContext*> m_contexts;
00276
00277
00278 bool m_finishContext;
00279 };
00280
00281 }
00282
00283 #endif // ABSTRACTUSEBUILDER_H
00284