• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDevelop Platform Libraries
  • Sitemap
  • Contact Us
 

language/duchain

abstractdeclarationbuilder.h

00001 /* This file is part of KDevelop
00002     Copyright 2006-2008 Hamish Rodda <rodda@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License version 2 as published by the Free Software Foundation.
00007 
00008    This library is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011    Library General Public License for more details.
00012 
00013    You should have received a copy of the GNU Library General Public License
00014    along with this library; see the file COPYING.LIB.  If not, write to
00015    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016    Boston, MA 02110-1301, USA.
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       // Seek a matching declaration
00107 
00108       // Translate cursor to take into account any changes the user may have made since the text was retrieved
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         //This works because dec->textRange() is taken from a smart-range. This means that now both ranges are translated to the current document-revision.
00119         if (dec->range() == translated &&
00120             (localId == dec->identifier() || (localId.isUnique() && dec->identifier().isUnique())) &&
00121             typeid(*dec) == typeid(DeclarationT)
00122             //&& extraDeclarationComparisons()
00123           )
00124         {
00125           // Match
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()) ) { //if the context is already internalContext of another declaration, leave it alone
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

language/duchain

Skip menu "language/duchain"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDevelop Platform Libraries

Skip menu "KDevelop Platform Libraries"
  • interfaces
  • language
  •   codegen
  •   duchain
  •   editor
  • outputview
  • project
  • shell
  • sublime
  • util
  • vcs
Generated for KDevelop Platform Libraries by doxygen 1.5.9-20090814
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal