language/duchain
abstractdeclarationbuilder.h
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef ABSTRACTDECLARATIONBUILDER_H
00020 #define ABSTRACTDECLARATIONBUILDER_H
00021
00022 #include <typeinfo>
00023
00024 #include "../classfunctiondeclaration.h"
00025 #include "../forwarddeclaration.h"
00026 #include "../types/identifiedtype.h"
00027 #include "../functiondeclaration.h"
00028 #include "../../editor/editorintegrator.h"
00029
00030 namespace KDevelop
00031 {
00032 class Declaration;
00033
00037 template<typename T, typename NameT, typename LanguageSpecificDeclarationBuilderBase>
00038 class AbstractDeclarationBuilder : public LanguageSpecificDeclarationBuilderBase
00039 {
00040 protected:
00042 inline bool hasCurrentDeclaration() const { return !m_declarationStack.isEmpty(); }
00044 inline Declaration* currentDeclaration() const { return m_declarationStack.isEmpty() ? 0 : m_declarationStack.top(); }
00046 template<class DeclarationType>
00047 inline DeclarationType* currentDeclaration() const { return m_declarationStack.isEmpty() ? 0 : dynamic_cast<DeclarationType*>(m_declarationStack.top()); }
00048
00050 inline const QByteArray& comment() const { return m_lastComment; }
00052 inline void setComment(const QByteArray& comment) { m_lastComment = comment; }
00054 inline void clearComment() { m_lastComment.clear(); }
00055
00056 enum DeclarationFlags {
00057 NoFlags = 0x0,
00058 DeclarationIsDefinition = 0x1
00059 };
00060
00070 template<class DeclarationT>
00071 DeclarationT* openDeclaration(NameT* name, T* range, DeclarationFlags flags = NoFlags)
00072 {
00073 DUChainWriteLocker lock(DUChain::lock());
00074
00075 SimpleRange newRange = editorFindRange(name ? name : range, name ? name : range);
00076
00077 if (newRange.start >= newRange.end)
00078 kWarning() << "Range collapsed";
00079
00080 QualifiedIdentifier id = identifierForNode(name);
00081
00082 return openDeclaration<DeclarationT>(id, newRange, flags);
00083 }
00084
00094 template<class DeclarationT>
00095 DeclarationT* openDeclaration(const QualifiedIdentifier& id, const SimpleRange& newRange, DeclarationFlags flags = NoFlags)
00096 {
00097 Identifier localId;
00098
00099 if(!id.isEmpty()) {
00100 localId = id.last();
00101 }
00102
00103 DeclarationT* declaration = 0;
00104
00105 if (LanguageSpecificDeclarationBuilderBase::recompiling()) {
00106
00107
00108
00109 LockedSmartInterface iface = LanguageSpecificDeclarationBuilderBase::editor()->smart();
00110 SimpleRange translated = LanguageSpecificDeclarationBuilderBase::editor()->translate(iface, newRange);
00111
00112 QList<Declaration*> declarations = LanguageSpecificDeclarationBuilderBase::currentContext()->allLocalDeclarations(localId);
00113 foreach( Declaration* dec, declarations ) {
00114
00115 if( LanguageSpecificDeclarationBuilderBase::wasEncountered(dec) )
00116 continue;
00117
00118
00119 if (dec->range() == translated &&
00120 (localId == dec->identifier() || (localId.isUnique() && dec->identifier().isUnique())) &&
00121 typeid(*dec) == typeid(DeclarationT)
00122
00123 )
00124 {
00125
00126 declaration = dynamic_cast<DeclarationT*>(dec);
00127 break;
00128 }
00129 }
00130 }
00131
00132 if (!declaration) {
00133 declaration = new DeclarationT(newRange, LanguageSpecificDeclarationBuilderBase::currentContext());
00134
00135 LockedSmartInterface iface = LanguageSpecificDeclarationBuilderBase::editor()->smart();
00136 KTextEditor::SmartRange* range = LanguageSpecificDeclarationBuilderBase::editor()->createRange(iface, newRange.textRange());
00137 declaration->setSmartRange(range);
00138 if (flags & DeclarationIsDefinition)
00139 declaration->setDeclarationIsDefinition(true);
00140 declaration->setIdentifier(localId);
00141
00142 LanguageSpecificDeclarationBuilderBase::editor()->exitCurrentRange(iface);
00143 }
00144
00145 declaration->setComment(m_lastComment);
00146 m_lastComment.clear();
00147
00148 LanguageSpecificDeclarationBuilderBase::setEncountered(declaration);
00149
00150 openDeclarationInternal(declaration);
00151
00152 return declaration;
00153 }
00154
00156 template<class DeclarationT>
00157 DeclarationT* openDefinition(NameT* name, T* range)
00158 {
00159 return openDeclaration<DeclarationT>(name, range, DeclarationIsDefinition);
00160 }
00161
00163 template<class DeclarationT>
00164 DeclarationT* openDefinition(const QualifiedIdentifier& id, const SimpleRange& newRange)
00165 {
00166 return openDeclaration<DeclarationT>(id, newRange, DeclarationIsDefinition);
00167 }
00168
00171 void openDeclarationInternal(Declaration* declaration)
00172 {
00173 m_declarationStack.push(declaration);
00174 }
00175
00177 ForwardDeclaration* openForwardDeclaration(NameT* name, T* range)
00178 {
00179 return openDeclaration<ForwardDeclaration*>(name, range);
00180 }
00181
00184 void eventuallyAssignInternalContext()
00185 {
00186 if (LanguageSpecificDeclarationBuilderBase::lastContext()) {
00187 DUChainWriteLocker lock(DUChain::lock());
00188
00189 if( dynamic_cast<ClassFunctionDeclaration*>(currentDeclaration()) )
00190 Q_ASSERT( !static_cast<ClassFunctionDeclaration*>(currentDeclaration())->isConstructor() || currentDeclaration()->context()->type() == DUContext::Class );
00191
00192 if(LanguageSpecificDeclarationBuilderBase::lastContext() &&
00193 (LanguageSpecificDeclarationBuilderBase::lastContext()->type() == DUContext::Class ||
00194 LanguageSpecificDeclarationBuilderBase::lastContext()->type() == DUContext::Other ||
00195 LanguageSpecificDeclarationBuilderBase::lastContext()->type() == DUContext::Function ||
00196 LanguageSpecificDeclarationBuilderBase::lastContext()->type() == DUContext::Template ||
00197 LanguageSpecificDeclarationBuilderBase::lastContext()->type() == DUContext::Enum ||
00198 (LanguageSpecificDeclarationBuilderBase::lastContext()->type() == DUContext::Namespace && currentDeclaration()->kind() == Declaration::Namespace)
00199 ) )
00200 {
00201 if( !LanguageSpecificDeclarationBuilderBase::lastContext()->owner() || !LanguageSpecificDeclarationBuilderBase::wasEncountered(LanguageSpecificDeclarationBuilderBase::lastContext()->owner()) ) {
00202 currentDeclaration()->setInternalContext(LanguageSpecificDeclarationBuilderBase::lastContext());
00203
00204 LanguageSpecificDeclarationBuilderBase::clearLastContext();
00205 }
00206 }
00207 }
00208 }
00209
00211 virtual void closeDeclaration()
00212 {
00213 m_declarationStack.pop();
00214 }
00215
00217 void abortDeclaration()
00218 {
00219 delete m_declarationStack.pop();
00220 }
00221
00222 private:
00223 QStack<Declaration*> m_declarationStack;
00224 QByteArray m_lastComment;
00225 };
00226
00227 }
00228
00229 #endif // ABSTRACTDECLARATIONBUILDER_H