1 /***************************************************************************
2 * This file is part of KDevelop *
3 * Copyright 2006 Hamish Rodda <rodda@kde.org> *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU Library General Public License as *
7 * published by the Free Software Foundation; either version 2 of the *
8 * License, or (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU Library General Public *
16 * License along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
24 #include <QtCore/QMutex>
25 #include <QtCore/QMultiHash>
26 #include <QtCore/QMap>
28 #include "../editor/simplecursor.h"
30 #include "duchainbase.h"
31 #include "ducontext.h"
32 #include "duchainpointer.h"
33 #include "declaration.h"
35 #include "../languageexport.h"
37 namespace KTextEditor
{
45 KDEVPLATFORMLANGUAGE_EXPORT
DECLARE_LIST_MEMBER_HASH(DUContextData
, m_childContexts
, LocalIndexedDUContext
)
46 KDEVPLATFORMLANGUAGE_EXPORT
DECLARE_LIST_MEMBER_HASH(DUContextData
, m_importers
, IndexedDUContext
)
47 KDEVPLATFORMLANGUAGE_EXPORT
DECLARE_LIST_MEMBER_HASH(DUContextData
, m_importedContexts
, DUContext::Import
)
48 KDEVPLATFORMLANGUAGE_EXPORT
DECLARE_LIST_MEMBER_HASH(DUContextData
, m_localDeclarations
, LocalIndexedDeclaration
)
49 KDEVPLATFORMLANGUAGE_EXPORT
DECLARE_LIST_MEMBER_HASH(DUContextData
, m_uses
, Use
)
51 ///This class contains data that needs to be stored to disk
52 class KDEVPLATFORMLANGUAGE_EXPORT DUContextData
: public DUChainBaseData
57 DUContextData(const DUContextData
& rhs
);
58 DUContext::ContextType m_contextType
;
59 IndexedQualifiedIdentifier m_scopeIdentifier
;
60 IndexedDeclaration m_owner
;
62 START_APPENDED_LISTS_BASE(DUContextData
, DUChainBaseData
);
63 APPENDED_LIST_FIRST(DUContextData
, DUContext::Import
, m_importedContexts
);
64 APPENDED_LIST(DUContextData
, LocalIndexedDUContext
, m_childContexts
, m_importedContexts
);
66 ///@todo eventually move the importers into some separate structure
67 APPENDED_LIST(DUContextData
, IndexedDUContext
, m_importers
, m_childContexts
);
69 ///@warning: Whenever m_localDeclarations is read or written, DUContextDynamicData::m_localDeclarationsMutex must be locked.
70 APPENDED_LIST(DUContextData
, LocalIndexedDeclaration
, m_localDeclarations
, m_importers
);
72 * Vector of all uses in this context
73 * Mutable for range synchronization
75 APPENDED_LIST(DUContextData
, Use
, m_uses
, m_localDeclarations
);
76 END_APPENDED_LISTS(DUContextData
, m_uses
);
78 bool m_inSymbolTable
: 1;
79 bool m_anonymousInParent
: 1; //Whether this context was added anonymously into the parent. This means that it cannot be found as child-context in the parent.
80 bool m_propagateDeclarations
: 1;
82 DUContextData
& operator=(const DUContextData
&) {
87 ///This class contains data that is only runtime-dependant and does not need to be stored to disk
88 class DUContextDynamicData
91 DUContextDynamicData( DUContext
* );
92 DUContextPointer m_parentContext
;
94 TopDUContext
* m_topContext
;
96 //Use DeclarationPointer instead of declaration, so we can locate management-problems
97 typedef QMultiHash
<Identifier
, DeclarationPointer
> DeclarationsHash
;
99 //Whether this context uses m_localDeclarationsHash
100 bool m_hasLocalDeclarationsHash
;
102 static QMutex m_localDeclarationsMutex
;
103 ///@warning: Whenever m_localDeclarations is read or written, m_localDeclarationsHash must be locked.
104 DeclarationsHash m_localDeclarationsHash
; //This hash can contain more declarations than m_localDeclarations, due to declarations propagated up from children.
106 uint m_indexInTopContext
; //Index of this DUContext in the top-context
109 * If this document is loaded, this contains a smart-range for each use.
110 * This may temporarily contain zero ranges.
112 mutable QVector
<KTextEditor::SmartRange
*> m_rangesForUses
;
114 DUContext
* m_context
;
116 mutable bool m_rangesChanged
: 1;
118 * Adds a child context.
120 * \note Be sure to have set the text location first, so that
121 * the chain is sorted correctly.
123 void addChildContext(DUContext
* context
);
125 /**Removes the context from childContexts
126 * @return Whether a context was removed
128 bool removeChildContext(DUContext
* context
);
130 void addImportedChildContext( DUContext
* context
);
131 void removeImportedChildContext( DUContext
* context
);
133 void addDeclaration(Declaration
* declaration
);
135 /**Removes the declaration from localDeclarations
136 * @return Whether a declaration was removed
138 bool removeDeclaration(Declaration
* declaration
);
140 //Files the scope identifier into target
141 void scopeIdentifier(bool includeClasses
, QualifiedIdentifier
& target
) const;
144 * This propagates the declaration into the parent search-hashes,
145 * up to the first parent that has m_propagateDeclarations set to false.
147 * Must be called with m_localDeclarationsMutex locked
149 void addDeclarationToHash(const Identifier
& identifer
, Declaration
* declaration
);
150 ///Must be called with m_localDeclarationsMutex locked
151 void removeDeclarationFromHash(const Identifier
& identifer
, Declaration
* declaration
);
153 ///Adds all declarations that should be in the hash into the hash
154 void enableLocalDeclarationsHash(DUContext
* ctx
, const Identifier
& currentIdentifier
= Identifier(), Declaration
* currentDecl
= 0);
156 void disableLocalDeclarationsHash();
158 bool needsLocalDeclarationsHash();
160 //Iterates through all visible declarations within a given context, including the ones propagated from sub-contexts
161 struct VisibleDeclarationIterator
{
164 StackEntry() : data(0), item(0), endItem(0), nextChild(0) {
167 DUContextDynamicData
* data
;
168 const LocalIndexedDeclaration
* item
;
169 const LocalIndexedDeclaration
* endItem
;
173 VisibleDeclarationIterator(DUContextDynamicData
* data
) {
175 current
.item
= data
->m_context
->d_func()->m_localDeclarations();
176 current
.endItem
= current
.item
+ data
->m_context
->d_func()->m_localDeclarationsSize();
177 current
.nextChild
= 0;
181 Declaration
* operator*() const {
182 return current
.item
->data(current
.data
->m_topContext
);
185 VisibleDeclarationIterator
& operator++() {
191 operator bool() const {
192 return (bool)current
.data
;
195 //Moves the cursor to the next valid position, from an invalid one(currentPos.back() == current.data->declarationCount())
196 void toValidPosition() {
197 if(current
.item
== current
.endItem
) {
199 const DUContextData
* data
= current
.data
->m_context
->d_func();
201 //Check if we can proceed into a propagating child-context
202 uint childContextCount
= data
->m_childContextsSize();
203 const LocalIndexedDUContext
* childContexts
= data
->m_childContexts();
205 for(unsigned int a
= 0; a
< childContextCount
; ++a
) {
206 DUContext
* child
= childContexts
[a
].data(current
.data
->m_topContext
);
207 if(child
->d_func()->m_propagateDeclarations
) {
208 current
.nextChild
= a
+1;
209 stack
.append(current
);
210 current
.data
= child
->m_dynamicData
;
211 current
.item
= child
->d_func()->m_localDeclarations();
212 current
.endItem
= current
.item
+ child
->d_func()->m_localDeclarationsSize();
213 current
.nextChild
= 0;
220 //Go up and into the next valid context
221 if(stack
.isEmpty()) {
222 current
= StackEntry();
226 current
= stack
.back();
229 const DUContextData
* data
= current
.data
->m_context
->d_func();
230 uint childContextCount
= data
->m_childContextsSize();
231 const LocalIndexedDUContext
* childContexts
= data
->m_childContexts();
233 for(unsigned int a
= current
.nextChild
; a
< childContextCount
; ++a
) {
234 DUContext
* child
= childContexts
[a
].data(current
.data
->m_topContext
);
236 if(child
->d_func()->m_propagateDeclarations
) {
238 current
.nextChild
= a
+1;
239 stack
.append(current
);
241 current
.data
= child
->m_dynamicData
;
242 current
.item
= child
->d_func()->m_localDeclarations();
243 current
.endItem
= current
.item
+ child
->d_func()->m_localDeclarationsSize();
244 current
.nextChild
= 0;
256 KDevVarLengthArray
<StackEntry
> stack
;
260 * Returns true if this context is imported by the given one, on any level.
262 bool isThisImportedBy(const DUContext
* context
) const;
270 //kate: space-indent on; indent-width 2; replace-tabs on; auto-insert-doxygen on; indent-mode cstyle;