1 /* This file is part of KDevelop
2 Copyright 2008 David Nolden <david.nolden.kdevelop@art-master.de>
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 Boston, MA 02110-1301, USA.
19 #include "persistentsymboltable.h"
24 #include "declarationid.h"
25 #include "appendedlist.h"
26 #include "repositories/itemrepository.h"
27 #include "identifier.h"
28 #include "ducontext.h"
29 #include "topducontext.h"
33 DEFINE_LIST_MEMBER_HASH(PersistentSymbolTableItem
, declarations
, IndexedDeclaration
)
35 class PersistentSymbolTableItem
{
37 PersistentSymbolTableItem() {
38 initializeAppendedLists();
40 PersistentSymbolTableItem(const PersistentSymbolTableItem
& rhs
) : id(rhs
.id
) {
41 initializeAppendedLists();
45 ~PersistentSymbolTableItem() {
49 unsigned int hash() const {
50 //We only compare the declaration. This allows us implementing a map, although the item-repository
51 //originally represents a set.
55 unsigned short int itemSize() const {
59 uint
classSize() const {
60 return sizeof(PersistentSymbolTableItem
);
63 IndexedQualifiedIdentifier id
;
65 START_APPENDED_LISTS(PersistentSymbolTableItem
);
66 APPENDED_LIST_FIRST(PersistentSymbolTableItem
, IndexedDeclaration
, declarations
);
67 END_APPENDED_LISTS(PersistentSymbolTableItem
, declarations
);
70 class PersistentSymbolTableRequestItem
{
73 PersistentSymbolTableRequestItem(const PersistentSymbolTableItem
& item
) : m_item(item
) {
76 AverageSize
= 30 //This should be the approximate average size of an Item
79 unsigned int hash() const {
83 size_t itemSize() const {
84 return m_item
.itemSize();
87 void createItem(PersistentSymbolTableItem
* item
) const {
88 item
->initializeAppendedLists(false);
90 item
->copyListsFrom(m_item
);
93 bool equals(const PersistentSymbolTableItem
* item
) const {
94 return m_item
.id
== item
->id
;
97 const PersistentSymbolTableItem
& m_item
;
100 DEFINE_LIST_MEMBER_HASH(PersistentContextTableItem
, contexts
, IndexedDUContext
)
102 class PersistentContextTableItem
{
104 PersistentContextTableItem() {
105 initializeAppendedLists();
107 PersistentContextTableItem(const PersistentContextTableItem
& rhs
) : id(rhs
.id
) {
108 initializeAppendedLists();
112 ~PersistentContextTableItem() {
116 unsigned int hash() const {
117 //We only compare the context. This allows us implementing a map, although the item-repository
118 //originally represents a set.
122 size_t itemSize() const {
123 return dynamicSize();
126 uint
classSize() const {
127 return sizeof(PersistentContextTableItem
);
130 IndexedQualifiedIdentifier id
;
132 START_APPENDED_LISTS(PersistentContextTableItem
);
133 APPENDED_LIST_FIRST(PersistentContextTableItem
, IndexedDUContext
, contexts
);
134 END_APPENDED_LISTS(PersistentContextTableItem
, contexts
);
137 class PersistentContextTableRequestItem
{
140 PersistentContextTableRequestItem(const PersistentContextTableItem
& item
) : m_item(item
) {
143 AverageSize
= 30 //This should be the approximate average size of an Item
146 unsigned int hash() const {
147 return m_item
.hash();
150 size_t itemSize() const {
151 return m_item
.itemSize();
154 void createItem(PersistentContextTableItem
* item
) const {
155 item
->initializeAppendedLists(false);
156 item
->id
= m_item
.id
;
157 item
->copyListsFrom(m_item
);
160 bool equals(const PersistentContextTableItem
* item
) const {
161 return m_item
.id
== item
->id
;
164 const PersistentContextTableItem
& m_item
;
168 struct PersistentSymbolTablePrivate
{
169 PersistentSymbolTablePrivate() : m_declarations("Persistent Declaration Table"), m_contexts("Persistent Context Table") {
171 //Maps declaration-ids to declarations
172 ItemRepository
<PersistentSymbolTableItem
, PersistentSymbolTableRequestItem
> m_declarations
;
173 ItemRepository
<PersistentContextTableItem
, PersistentContextTableRequestItem
> m_contexts
;
176 PersistentSymbolTable::PersistentSymbolTable() : d(new PersistentSymbolTablePrivate())
180 PersistentSymbolTable::~PersistentSymbolTable()
185 void PersistentSymbolTable::addDeclaration(const IndexedQualifiedIdentifier
& id
, const IndexedDeclaration
& declaration
)
187 PersistentSymbolTableItem item
;
189 item
.declarationsList().append(declaration
);
190 PersistentSymbolTableRequestItem
request(item
);
192 uint index
= d
->m_declarations
.findIndex(item
);
195 //Check whether the item is already in the mapped list, else copy the list into the new created item
196 const PersistentSymbolTableItem
* oldItem
= d
->m_declarations
.itemFromIndex(index
);
197 for(uint a
= 0; a
< oldItem
->declarationsSize(); ++a
) {
198 if(oldItem
->declarations()[a
] == declaration
)
199 return; //Already there
200 item
.declarationsList().append(oldItem
->declarations()[a
]);
203 if(request
.itemSize() > (1<<15))
204 kWarning() << "many many declarations for id" << id
.identifier().toString() << item
.declarationsSize();
206 d
->m_declarations
.deleteItem(index
);
207 uint stillExistingIndex
= d
->m_declarations
.findIndex(request
);
208 Q_ASSERT(!stillExistingIndex
);
211 //This inserts the changed item
212 d
->m_declarations
.index(request
);
215 void PersistentSymbolTable::removeDeclaration(const IndexedQualifiedIdentifier
& id
, const IndexedDeclaration
& declaration
)
217 PersistentSymbolTableItem item
;
219 PersistentSymbolTableRequestItem
request(item
);
221 uint index
= d
->m_declarations
.findIndex(item
);
224 //Check whether the item is already in the mapped list, else copy the list into the new created item
225 const PersistentSymbolTableItem
* oldItem
= d
->m_declarations
.itemFromIndex(index
);
226 uint oldSize
= oldItem
->declarationsSize();
230 for(uint a
= 0; a
< oldSize
; ++a
)
231 if(!(oldItem
->declarations()[a
] == declaration
))
232 item
.declarationsList().append(oldItem
->declarations()[a
]);
237 d
->m_declarations
.deleteItem(index
);
238 Q_ASSERT(d
->m_declarations
.findIndex(item
) == 0);
240 //This inserts the changed item
241 if(item
.declarationsSize() != 0) {
242 uint newIndex
= d
->m_declarations
.index(request
);
243 Q_ASSERT(oldSize
== d
->m_declarations
.itemFromIndex(newIndex
)->declarationsSize()+1);
246 kDebug() << "tried to remove a declaration from the symbol-table that isn't there" << id
.identifier().toString();
251 void PersistentSymbolTable::declarations(const IndexedQualifiedIdentifier
& id
, uint
& countTarget
, const IndexedDeclaration
*& declarationsTarget
) const
253 PersistentSymbolTableItem item
;
255 PersistentSymbolTableRequestItem
request(item
);
257 uint index
= d
->m_declarations
.findIndex(item
);
260 const PersistentSymbolTableItem
* repositoryItem
= d
->m_declarations
.itemFromIndex(index
);
261 countTarget
= repositoryItem
->declarationsSize();
262 declarationsTarget
= repositoryItem
->declarations();
265 declarationsTarget
= 0;
269 void PersistentSymbolTable::addContext(const IndexedQualifiedIdentifier
& id
, const IndexedDUContext
& context
) {
270 PersistentContextTableItem item
;
272 item
.contextsList().append(context
);
273 PersistentContextTableRequestItem
request(item
);
275 uint index
= d
->m_contexts
.findIndex(item
);
278 //Check whether the item is already in the mapped list, else copy the list into the new created item
279 const PersistentContextTableItem
* oldItem
= d
->m_contexts
.itemFromIndex(index
);
280 for(uint a
= 0; a
< oldItem
->contextsSize(); ++a
) {
281 if(oldItem
->contexts()[a
] == context
)
282 return; //Already there
283 item
.contextsList().append(oldItem
->contexts()[a
]);
286 if(request
.itemSize() > (1<<15))
287 kWarning() << "too many contexts for id" << id
.identifier().toString() << item
.contextsSize();
289 d
->m_contexts
.deleteItem(index
);
292 //This inserts the changed item
293 d
->m_contexts
.index(request
);
296 void PersistentSymbolTable::removeContext(const IndexedQualifiedIdentifier
& id
, const IndexedDUContext
& context
) {
297 PersistentContextTableItem item
;
299 PersistentContextTableRequestItem
request(item
);
301 uint index
= d
->m_contexts
.findIndex(item
);
304 //Check whether the item is already in the mapped list, else copy the list into the new created item
305 const PersistentContextTableItem
* oldItem
= d
->m_contexts
.itemFromIndex(index
);
306 for(uint a
= 0; a
< oldItem
->contextsSize(); ++a
)
307 if(!(oldItem
->contexts()[a
] == context
))
308 item
.contextsList().append(oldItem
->contexts()[a
]);
310 d
->m_contexts
.deleteItem(index
);
311 Q_ASSERT(d
->m_contexts
.findIndex(item
) == 0);
313 //This inserts the changed item
314 if(item
.contextsSize() != 0)
315 d
->m_contexts
.index(request
);
319 void PersistentSymbolTable::contexts(const IndexedQualifiedIdentifier
& id
, uint
& countTarget
, const IndexedDUContext
*& contextsTarget
) const {
320 PersistentContextTableItem item
;
322 PersistentContextTableRequestItem
request(item
);
324 uint index
= d
->m_contexts
.findIndex(item
);
327 const PersistentContextTableItem
* repositoryItem
= d
->m_contexts
.itemFromIndex(index
);
328 countTarget
= repositoryItem
->contextsSize();
329 contextsTarget
= repositoryItem
->contexts();
336 uint
qHash(IndexedDeclaration decl
) {
341 bool operator() (const PersistentSymbolTableItem
* item
) {
342 QualifiedIdentifier
id(item
->id
.identifier());
343 if(identifiers
.contains(id
))
344 kDebug() << "identifier" << id
.toString() << "appears for" << identifiers
[id
] << "th time";
348 for(uint a
= 0; a
< item
->declarationsSize(); ++a
) {
349 IndexedDeclaration
decl(item
->declarations()[a
]);
350 if(declarations
.contains(decl
)) {
351 kDebug() << "declaration found for multiple identifiers. Previous identifier:" << declarations
[decl
].toString() << "current identifier:" << id
.toString();
353 declarations
.insert(decl
, id
);
356 kDebug() << "Item in symbol-table is invalid:" << id
.toString() << item
->declarations()[a
].localIndex() << IndexedTopDUContext(item
->declarations()[a
].topContextIndex()).url().str();
361 QHash
<QualifiedIdentifier
, uint
> identifiers
;
362 QHash
<IndexedDeclaration
, QualifiedIdentifier
> declarations
;
365 struct ContextVisitor
{
366 bool operator() (const PersistentContextTableItem
* item
) {
367 QualifiedIdentifier
id(item
->id
.identifier());
368 if(identifiers
.contains(id
))
369 kDebug() << "identifier" << id
.toString() << "appears for" << identifiers
[id
] << "th time";
373 for(uint a
= 0; a
< item
->contextsSize(); ++a
) {
374 if(!item
->contexts()[a
].data()) {
375 kDebug() << "Item in Context-table is invalid:" << id
.toString() << item
->contexts()[a
].localIndex() << IndexedTopDUContext(item
->contexts()[a
].topContextIndex()).url().str();
380 QHash
<QualifiedIdentifier
, uint
> identifiers
;
383 void PersistentSymbolTable::selfAnalysis() {
386 kDebug() << d
->m_declarations
.statistics();
387 d
->m_declarations
.visitAllItems(v
);
388 kDebug() << "visited" << v
.identifiers
.size() << "identifiers";
393 kDebug() << d
->m_contexts
.statistics();
394 d
->m_contexts
.visitAllItems(v
);
395 kDebug() << "visited" << v
.identifiers
.size() << "identifiers";
399 PersistentSymbolTable
& PersistentSymbolTable::self() {
400 static PersistentSymbolTable ret
;