1 | /* This file is part of KDevelop |
---|
2 | Copyright 2006-2007 Hamish Rodda <rodda@kde.org> |
---|
3 | Copyright 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de> |
---|
4 | |
---|
5 | This library is free software; you can redistribute it and/or |
---|
6 | modify it under the terms of the GNU Library General Public |
---|
7 | License version 2 as published by the Free Software Foundation. |
---|
8 | |
---|
9 | This library is distributed in the hope that it will be useful, |
---|
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
12 | Library General Public License for more details. |
---|
13 | |
---|
14 | You should have received a copy of the GNU Library General Public License |
---|
15 | along with this library; see the file COPYING.LIB. If not, write to |
---|
16 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
---|
17 | Boston, MA 02110-1301, USA. |
---|
18 | */ |
---|
19 | |
---|
20 | #include "declarationbuilder.h" |
---|
21 | |
---|
22 | #include "debugbuilders.h" |
---|
23 | |
---|
24 | #include <QByteArray> |
---|
25 | #include <typeinfo> |
---|
26 | #include <iterator> |
---|
27 | |
---|
28 | #include "templatedeclaration.h" |
---|
29 | |
---|
30 | #include "parser/type_compiler.h" |
---|
31 | #include "parser/commentformatter.h" |
---|
32 | |
---|
33 | #include <language/duchain/forwarddeclaration.h> |
---|
34 | #include <language/duchain/duchain.h> |
---|
35 | #include <language/duchain/duchainlock.h> |
---|
36 | #include <language/duchain/repositories/itemrepository.h> |
---|
37 | #include <language/duchain/types/identifiedtype.h> |
---|
38 | #include <language/duchain/namespacealiasdeclaration.h> |
---|
39 | #include <language/duchain/aliasdeclaration.h> |
---|
40 | #include <util/pushvalue.h> |
---|
41 | |
---|
42 | #include "qtfunctiondeclaration.h" |
---|
43 | #include "qpropertydeclaration.h" |
---|
44 | #include "cppeditorintegrator.h" |
---|
45 | #include "name_compiler.h" |
---|
46 | #include <language/duchain/classfunctiondeclaration.h> |
---|
47 | #include <language/duchain/functiondeclaration.h> |
---|
48 | #include <language/duchain/functiondefinition.h> |
---|
49 | #include "templateparameterdeclaration.h" |
---|
50 | #include "type_compiler.h" |
---|
51 | #include "tokens.h" |
---|
52 | #include "parsesession.h" |
---|
53 | #include "cpptypes.h" |
---|
54 | #include "cppduchain.h" |
---|
55 | #include "cpptypes.h" |
---|
56 | #include <language/duchain/classdeclaration.h> |
---|
57 | |
---|
58 | #include "cppdebughelper.h" |
---|
59 | #include "name_visitor.h" |
---|
60 | #include "usebuilder.h" |
---|
61 | |
---|
62 | #include "overloadresolutionhelper.h" |
---|
63 | |
---|
64 | using namespace KTextEditor; |
---|
65 | using namespace KDevelop; |
---|
66 | using namespace Cpp; |
---|
67 | |
---|
68 | ClassDeclarationData::ClassType classTypeFromTokenKind(int kind) |
---|
69 | { |
---|
70 | switch(kind) |
---|
71 | { |
---|
72 | case Token_struct: |
---|
73 | return ClassDeclarationData::Struct; |
---|
74 | case Token_union: |
---|
75 | return ClassDeclarationData::Union; |
---|
76 | default: |
---|
77 | return ClassDeclarationData::Class; |
---|
78 | } |
---|
79 | } |
---|
80 | |
---|
81 | bool DeclarationBuilder::changeWasSignificant() const |
---|
82 | { |
---|
83 | ///@todo Also set m_changeWasSignificant if publically visible declarations were removed(needs interaction with abstractcontextbuilder) |
---|
84 | return m_changeWasSignificant; |
---|
85 | } |
---|
86 | |
---|
87 | DeclarationBuilder::DeclarationBuilder (ParseSession* session) |
---|
88 | : DeclarationBuilderBase(session), m_changeWasSignificant(false), m_ignoreDeclarators(false), m_functionFlag(NoFunctionFlag), m_collectQtFunctionSignature(false), m_lastDeclaration(0) |
---|
89 | { |
---|
90 | } |
---|
91 | |
---|
92 | ReferencedTopDUContext DeclarationBuilder::buildDeclarations(Cpp::EnvironmentFilePointer file, AST *node, IncludeFileList* includes, const ReferencedTopDUContext& updateContext, bool removeOldImports) |
---|
93 | { |
---|
94 | ReferencedTopDUContext top = buildContexts(file, node, includes, updateContext, removeOldImports); |
---|
95 | |
---|
96 | Q_ASSERT(m_accessPolicyStack.isEmpty()); |
---|
97 | Q_ASSERT(m_functionDefinedStack.isEmpty()); |
---|
98 | |
---|
99 | return top; |
---|
100 | } |
---|
101 | |
---|
102 | void DeclarationBuilder::visitTemplateParameter(TemplateParameterAST * ast) { |
---|
103 | |
---|
104 | //Backup and zero the parameter declaration, because we will handle it here directly, and don't want a normal one to be created |
---|
105 | |
---|
106 | m_ignoreDeclarators = true; |
---|
107 | DeclarationBuilderBase::visitTemplateParameter(ast); |
---|
108 | m_ignoreDeclarators = false; |
---|
109 | |
---|
110 | if( ast->type_parameter || ast->parameter_declaration ) { |
---|
111 | ///@todo deal with all the other stuff the AST may contain |
---|
112 | TemplateParameterDeclaration* decl; |
---|
113 | if(ast->type_parameter) |
---|
114 | decl = openDeclaration<TemplateParameterDeclaration>(ast->type_parameter->name, ast, Identifier(), false, !ast->type_parameter->name); |
---|
115 | else |
---|
116 | decl = openDeclaration<TemplateParameterDeclaration>(ast->parameter_declaration->declarator ? ast->parameter_declaration->declarator->id : 0, ast, Identifier(), false, !ast->parameter_declaration->declarator); |
---|
117 | |
---|
118 | DUChainWriteLocker lock(DUChain::lock()); |
---|
119 | AbstractType::Ptr type = lastType(); |
---|
120 | if( type.cast<CppTemplateParameterType>() ) { |
---|
121 | type.cast<CppTemplateParameterType>()->setDeclaration(decl); |
---|
122 | } else { |
---|
123 | kDebug(9007) << "bad last type"; |
---|
124 | } |
---|
125 | decl->setAbstractType(type); |
---|
126 | |
---|
127 | if( ast->type_parameter && ast->type_parameter->type_id ) { |
---|
128 | //Extract default type-parameter |
---|
129 | QualifiedIdentifier defaultParam; |
---|
130 | |
---|
131 | QString str; |
---|
132 | ///Only record the strings, because these expressions may depend on template-parameters and thus must be evaluated later |
---|
133 | str += stringFromSessionTokens( editor()->parseSession(), ast->type_parameter->type_id->start_token, ast->type_parameter->type_id->end_token ); |
---|
134 | |
---|
135 | defaultParam = QualifiedIdentifier(str); |
---|
136 | |
---|
137 | decl->setDefaultParameter(defaultParam); |
---|
138 | } |
---|
139 | |
---|
140 | if( ast->parameter_declaration ) { |
---|
141 | if( ast->parameter_declaration->expression ) |
---|
142 | decl->setDefaultParameter( QualifiedIdentifier( stringFromSessionTokens( editor()->parseSession(), ast->parameter_declaration->expression->start_token, ast->parameter_declaration->expression->end_token ) ) ); |
---|
143 | } |
---|
144 | closeDeclaration(ast->parameter_declaration); |
---|
145 | } |
---|
146 | } |
---|
147 | |
---|
148 | void DeclarationBuilder::parseComments(const ListNode<uint> *comments) |
---|
149 | { |
---|
150 | setComment(editor()->parseSession()->m_commentFormatter.formatComment(comments, editor()->parseSession())); |
---|
151 | } |
---|
152 | |
---|
153 | void DeclarationBuilder::visitFunctionDeclaration(FunctionDefinitionAST* node) |
---|
154 | { |
---|
155 | FunctionFlag flag = NoFunctionFlag; |
---|
156 | switch(node->defaultDeleted) { |
---|
157 | case FunctionDefinitionAST::NotDefaultOrDeleted: |
---|
158 | flag = NoFunctionFlag; |
---|
159 | break; |
---|
160 | case FunctionDefinitionAST::Default: |
---|
161 | flag = DefaultFunction; |
---|
162 | break; |
---|
163 | case FunctionDefinitionAST::Deleted: |
---|
164 | flag = DeleteFunction; |
---|
165 | break; |
---|
166 | } |
---|
167 | PushValue<FunctionFlag> setDefaultDeleted(m_functionFlag, flag); |
---|
168 | |
---|
169 | parseComments(node->comments); |
---|
170 | parseStorageSpecifiers(node->storage_specifiers); |
---|
171 | parseFunctionSpecifiers(node->function_specifiers); |
---|
172 | |
---|
173 | //Used to map to the top level function node once the Declaration is built |
---|
174 | if(m_mapAst) |
---|
175 | m_mappedNodes.push(node); |
---|
176 | |
---|
177 | m_functionDefinedStack.push(node->start_token); |
---|
178 | |
---|
179 | DeclarationBuilderBase::visitFunctionDeclaration(node); |
---|
180 | |
---|
181 | m_functionDefinedStack.pop(); |
---|
182 | |
---|
183 | if(m_mapAst) |
---|
184 | m_mappedNodes.pop(); |
---|
185 | |
---|
186 | popSpecifiers(); |
---|
187 | } |
---|
188 | |
---|
189 | //Visitor that clears the ducontext from all AST nodes |
---|
190 | struct ClearDUContextVisitor : public DefaultVisitor { |
---|
191 | |
---|
192 | virtual void visit(AST* node) { |
---|
193 | if(node) |
---|
194 | node->ducontext = 0; |
---|
195 | DefaultVisitor::visit(node); |
---|
196 | } |
---|
197 | }; |
---|
198 | |
---|
199 | void DeclarationBuilder::visitInitDeclarator(InitDeclaratorAST *node) |
---|
200 | { |
---|
201 | ///FIXME: properly add support for member-declaration/member-declarator |
---|
202 | PushValue<FunctionFlag> setHasInitialize(m_functionFlag, |
---|
203 | (node->initializer && node->initializer->initializer_clause && node->initializer->initializer_clause->expression) |
---|
204 | ? AbstractFunction : NoFunctionFlag); |
---|
205 | |
---|
206 | if(currentContext()->type() == DUContext::Other) { |
---|
207 | //Cannot declare a a function within a code-context |
---|
208 | node->declarator->parameter_is_initializer = true; |
---|
209 | }else if(!m_inFunctionDefinition && node->declarator && node->declarator->parameter_declaration_clause && node->declarator->id) { |
---|
210 | //Decide whether the parameter-declaration clause is valid |
---|
211 | DUChainWriteLocker lock(DUChain::lock()); |
---|
212 | CursorInRevision pos = editor()->findPosition(node->start_token, CppEditorIntegrator::FrontEdge); |
---|
213 | |
---|
214 | QualifiedIdentifier id; |
---|
215 | identifierForNode(node->declarator->id, id); |
---|
216 | DUContext* previous = currentContext(); |
---|
217 | |
---|
218 | DUContext* previousLast = lastContext(); |
---|
219 | QVector<KDevelop::DUContext::Import> importedParentContexts = m_importedParentContexts; |
---|
220 | |
---|
221 | openPrefixContext(node, id, pos); //We create a temporary prefix-context to search from within the right scope |
---|
222 | |
---|
223 | DUContext* tempContext = currentContext(); |
---|
224 | if (currentContext()->type() != DUContext::Class) |
---|
225 | node->declarator->parameter_is_initializer = !checkParameterDeclarationClause(node->declarator->parameter_declaration_clause); |
---|
226 | closePrefixContext(id); |
---|
227 | |
---|
228 | |
---|
229 | |
---|
230 | if(tempContext != previous) { |
---|
231 | |
---|
232 | //We remove all of its traces from the AST using ClearDUContextVisitor. |
---|
233 | ClearDUContextVisitor clear; |
---|
234 | clear.visit(node); |
---|
235 | |
---|
236 | ///@todo We don't delete the tempContext, as that may cause crashes. Problem: This leaves garbage in the duchain |
---|
237 | ///@todo Solve the redundancy issue once and for all, properly, using a SimpleDeclarationOrFunctionDeclarationAST or similar. |
---|
238 | |
---|
239 | //Since we don't delete the temporary context, at least collapse its range. |
---|
240 | tempContext->setRange(RangeInRevision(tempContext->range().start, tempContext->range().end)); |
---|
241 | |
---|
242 | setLastContext(previousLast); |
---|
243 | m_importedParentContexts = importedParentContexts; |
---|
244 | } |
---|
245 | Q_ASSERT(currentContext() == previous); |
---|
246 | } |
---|
247 | |
---|
248 | DeclarationBuilderBase::visitInitDeclarator(node); |
---|
249 | } |
---|
250 | |
---|
251 | void DeclarationBuilder::visitQPropertyDeclaration(QPropertyDeclarationAST* node) |
---|
252 | { |
---|
253 | QPropertyDeclaration *decl = openDeclaration<QPropertyDeclaration>(node->name, node->name); |
---|
254 | decl->setIsStored(node->stored); |
---|
255 | decl->setIsUser(node->user); |
---|
256 | decl->setIsConstant(node->constant); |
---|
257 | decl->setIsFinal(node->final); |
---|
258 | |
---|
259 | DeclarationBuilderBase::visitQPropertyDeclaration(node); |
---|
260 | AbstractType::Ptr type = lastType(); |
---|
261 | closeDeclaration(true); |
---|
262 | |
---|
263 | if(type) { |
---|
264 | DUChainWriteLocker lock(DUChain::lock()); |
---|
265 | decl->setAbstractType(type); |
---|
266 | decl->setAccessPolicy(KDevelop::Declaration::Public); |
---|
267 | } |
---|
268 | |
---|
269 | m_pendingPropertyDeclarations.insert(currentContext(), qMakePair(decl, node)); |
---|
270 | } |
---|
271 | |
---|
272 | void DeclarationBuilder::visitForRangeDeclaration(ForRangeDeclarationAst* node) |
---|
273 | { |
---|
274 | AbstractType::Ptr listType = lastType(); |
---|
275 | |
---|
276 | DefaultVisitor::visitForRangeDeclaration(node); |
---|
277 | |
---|
278 | if (lastTypeWasAuto() && listType && m_lastDeclaration) { |
---|
279 | // auto support for range-based for |
---|
280 | AbstractType::Ptr realListType = TypeUtils::realType(listType); |
---|
281 | // step 1: find type of elements in list |
---|
282 | AbstractType::Ptr elementType; |
---|
283 | if (ArrayType::Ptr array = realListType.cast<ArrayType>()) { |
---|
284 | // case a: c-array, i.e. foo bar[5]; -> type is foo |
---|
285 | elementType = array->elementType(); |
---|
286 | } else { |
---|
287 | // case b: look for begin(listType) function using ADL |
---|
288 | DUChainReadLocker lock; |
---|
289 | OverloadResolutionHelper helper = OverloadResolutionHelper( DUContextPointer(currentContext()), TopDUContextPointer(topContext()) ); |
---|
290 | static const QualifiedIdentifier begin("begin"); |
---|
291 | helper.setFunctionNameForADL(begin); |
---|
292 | helper.setKnownParameters(OverloadResolver::ParameterList(listType, false)); |
---|
293 | helper.setFunctions( currentContext()->findDeclarations(begin, CursorInRevision::invalid(), AbstractType::Ptr(), 0, DUContext::OnlyFunctions) ); |
---|
294 | ViableFunction func = helper.resolve(); |
---|
295 | if (func.isValid()) { |
---|
296 | AbstractType::Ptr type = func.declaration()->type<FunctionType>()->returnType(); |
---|
297 | // see spec: for-range-declaration = *__begin; |
---|
298 | elementType = TypeUtils::decreasePointerDepth(type, topContext(), true); |
---|
299 | } |
---|
300 | } |
---|
301 | |
---|
302 | // step 2: set last type, but keep const& |
---|
303 | if (elementType) { |
---|
304 | DUChainWriteLocker lock; |
---|
305 | AbstractType::Ptr type = m_lastDeclaration->abstractType(); |
---|
306 | elementType->setModifiers(type->modifiers()); |
---|
307 | if (ReferenceType::Ptr ref = type.cast<ReferenceType>()) { |
---|
308 | ref->setBaseType(elementType); |
---|
309 | } else { |
---|
310 | type = elementType; |
---|
311 | } |
---|
312 | m_lastDeclaration->setAbstractType(type); |
---|
313 | } |
---|
314 | } |
---|
315 | } |
---|
316 | |
---|
317 | KDevelop::IndexedDeclaration DeclarationBuilder::resolveMethodName(NameAST *node) |
---|
318 | { |
---|
319 | QualifiedIdentifier id; |
---|
320 | identifierForNode(node, id); |
---|
321 | |
---|
322 | DUChainReadLocker lock(DUChain::lock()); |
---|
323 | if(currentDeclaration() && currentDeclaration()->internalContext()) { |
---|
324 | const QList<Declaration*> declarations = currentDeclaration()->internalContext()->findDeclarations(id, CursorInRevision::invalid(), AbstractType::Ptr(), 0, DUContext::OnlyFunctions); |
---|
325 | if(!declarations.isEmpty()) |
---|
326 | return KDevelop::IndexedDeclaration(declarations.first()); |
---|
327 | } |
---|
328 | |
---|
329 | return KDevelop::IndexedDeclaration(); |
---|
330 | } |
---|
331 | |
---|
332 | void DeclarationBuilder::resolvePendingPropertyDeclarations(const QList<PropertyResolvePair> &pairs) |
---|
333 | { |
---|
334 | foreach(const PropertyResolvePair &pair, pairs) { |
---|
335 | if(pair.second->getter){ |
---|
336 | const KDevelop::IndexedDeclaration declaration = resolveMethodName(pair.second->getter); |
---|
337 | if(declaration.isValid()) |
---|
338 | pair.first->setReadMethod(declaration); |
---|
339 | } |
---|
340 | if(pair.second->setter){ |
---|
341 | const KDevelop::IndexedDeclaration declaration = resolveMethodName(pair.second->setter); |
---|
342 | if(declaration.isValid()) |
---|
343 | pair.first->setWriteMethod(declaration); |
---|
344 | } |
---|
345 | if(pair.second->resetter){ |
---|
346 | const KDevelop::IndexedDeclaration declaration = resolveMethodName(pair.second->resetter); |
---|
347 | if(declaration.isValid()) |
---|
348 | pair.first->setResetMethod(declaration); |
---|
349 | } |
---|
350 | if(pair.second->notifier){ |
---|
351 | const KDevelop::IndexedDeclaration declaration = resolveMethodName(pair.second->notifier); |
---|
352 | if(declaration.isValid()) |
---|
353 | pair.first->setNotifyMethod(declaration); |
---|
354 | } |
---|
355 | if(pair.second->designableMethod){ |
---|
356 | const KDevelop::IndexedDeclaration declaration = resolveMethodName(pair.second->designableMethod); |
---|
357 | if(declaration.isValid()) |
---|
358 | pair.first->setDesignableMethod(declaration); |
---|
359 | } |
---|
360 | if(pair.second->scriptableMethod){ |
---|
361 | const KDevelop::IndexedDeclaration declaration = resolveMethodName(pair.second->scriptableMethod); |
---|
362 | if(declaration.isValid()) |
---|
363 | pair.first->setScriptableMethod(declaration); |
---|
364 | } |
---|
365 | } |
---|
366 | } |
---|
367 | |
---|
368 | void DeclarationBuilder::visitSimpleDeclaration(SimpleDeclarationAST* node) |
---|
369 | { |
---|
370 | parseComments(node->comments); |
---|
371 | parseStorageSpecifiers(node->storage_specifiers); |
---|
372 | parseFunctionSpecifiers(node->function_specifiers); |
---|
373 | |
---|
374 | if(m_mapAst) |
---|
375 | m_mappedNodes.push(node); |
---|
376 | |
---|
377 | m_functionDefinedStack.push(0); |
---|
378 | |
---|
379 | DeclarationBuilderBase::visitSimpleDeclaration(node); |
---|
380 | |
---|
381 | m_functionDefinedStack.pop(); |
---|
382 | |
---|
383 | if(m_mapAst) |
---|
384 | m_mappedNodes.pop(); |
---|
385 | |
---|
386 | popSpecifiers(); |
---|
387 | } |
---|
388 | |
---|
389 | void DeclarationBuilder::visitDeclarator (DeclaratorAST* node) |
---|
390 | { |
---|
391 | if(m_ignoreDeclarators) { |
---|
392 | DeclarationBuilderBase::visitDeclarator(node); |
---|
393 | return; |
---|
394 | } |
---|
395 | //need to make backup because we may temporarily change it |
---|
396 | ParameterDeclarationClauseAST* parameter_declaration_clause_backup = node->parameter_declaration_clause; |
---|
397 | |
---|
398 | m_collectQtFunctionSignature = !m_accessPolicyStack.isEmpty() && ((m_accessPolicyStack.top() & FunctionIsSlot) || (m_accessPolicyStack.top() & FunctionIsSignal)); |
---|
399 | m_qtFunctionSignature = QByteArray(); |
---|
400 | |
---|
401 | if (node->parameter_declaration_clause && !node->parameter_is_initializer) { |
---|
402 | |
---|
403 | if(m_collectQtFunctionSignature) //We need to do this just to collect the signature |
---|
404 | checkParameterDeclarationClause(node->parameter_declaration_clause); |
---|
405 | |
---|
406 | Declaration* decl = openFunctionDeclaration(node->id, node); |
---|
407 | |
---|
408 | ///Create mappings iff the AST feature is specified |
---|
409 | if(m_mapAst && !m_mappedNodes.empty()) |
---|
410 | editor()->parseSession()->mapAstDuChain(m_mappedNodes.top(), KDevelop::DeclarationPointer(decl)); |
---|
411 | |
---|
412 | if (m_functionFlag == DeleteFunction) { |
---|
413 | DUChainWriteLocker lock(DUChain::lock()); |
---|
414 | decl->setExplicitlyDeleted(true); |
---|
415 | } |
---|
416 | |
---|
417 | if( !m_functionDefinedStack.isEmpty() ) { |
---|
418 | DUChainWriteLocker lock(DUChain::lock()); |
---|
419 | // don't overwrite isDefinition if that was already set (see openFunctionDeclaration) |
---|
420 | decl->setDeclarationIsDefinition( (bool)m_functionDefinedStack.top() ); |
---|
421 | } |
---|
422 | |
---|
423 | applyFunctionSpecifiers(); |
---|
424 | } else { |
---|
425 | openDefinition(node->id, node, node->id == 0); |
---|
426 | node->parameter_declaration_clause = 0; |
---|
427 | } |
---|
428 | |
---|
429 | m_collectQtFunctionSignature = false; |
---|
430 | |
---|
431 | applyStorageSpecifiers(); |
---|
432 | |
---|
433 | DeclarationBuilderBase::visitDeclarator(node); |
---|
434 | |
---|
435 | if (node->parameter_declaration_clause) { |
---|
436 | if (!m_functionDefinedStack.isEmpty() && m_functionDefinedStack.top() && node->id) { |
---|
437 | |
---|
438 | DUChainWriteLocker lock(DUChain::lock()); |
---|
439 | //We have to search for the fully qualified identifier, so we always get the correct class |
---|
440 | QualifiedIdentifier id = currentContext()->scopeIdentifier(false); |
---|
441 | QualifiedIdentifier id2; |
---|
442 | identifierForNode(node->id, id2); |
---|
443 | id += id2; |
---|
444 | |
---|
445 | id.setExplicitlyGlobal(true); |
---|
446 | |
---|
447 | if (id.count() > 1 || |
---|
448 | (m_inFunctionDefinition && (currentContext()->type() == DUContext::Namespace || currentContext()->type() == DUContext::Global))) { |
---|
449 | CursorInRevision pos = currentDeclaration()->range().start;//editor()->findPosition(m_functionDefinedStack.top(), CppEditorIntegrator::FrontEdge); |
---|
450 | // TODO: potentially excessive locking |
---|
451 | |
---|
452 | QList<Declaration*> declarations = currentContext()->findDeclarations(id, pos, AbstractType::Ptr(), 0, DUContext::OnlyFunctions); |
---|
453 | |
---|
454 | FunctionType::Ptr currentFunction = lastType().cast<FunctionType>(); |
---|
455 | int functionArgumentCount = 0; |
---|
456 | if(currentFunction) |
---|
457 | functionArgumentCount = currentFunction->arguments().count(); |
---|
458 | |
---|
459 | for( int cycle = 0; cycle < 3; cycle++ ) { |
---|
460 | bool found = false; |
---|
461 | ///We do 2 cycles: In the first cycle, we want an exact match. In the second, we accept approximate matches. |
---|
462 | foreach (Declaration* dec, declarations) { |
---|
463 | if (dec->isForwardDeclaration()) |
---|
464 | continue; |
---|
465 | if(dec == currentDeclaration() || dec->isDefinition()) |
---|
466 | continue; |
---|
467 | //Compare signatures of function-declarations: |
---|
468 | if(dec->abstractType()->indexed() == lastType()->indexed()) |
---|
469 | { |
---|
470 | //The declaration-type matches this definition, good. |
---|
471 | }else{ |
---|
472 | if(cycle == 0) { |
---|
473 | //First cycle, only accept exact matches |
---|
474 | continue; |
---|
475 | }else if(cycle == 1){ |
---|
476 | //Second cycle, match by argument-count |
---|
477 | FunctionType::Ptr matchFunction = dec->type<FunctionType>(); |
---|
478 | if(currentFunction && matchFunction && currentFunction->arguments().count() == functionArgumentCount ) { |
---|
479 | //We have a match |
---|
480 | }else{ |
---|
481 | continue; |
---|
482 | } |
---|
483 | }else if(cycle == 2){ |
---|
484 | //Accept any match, so just continue |
---|
485 | } |
---|
486 | if(FunctionDefinition::definition(dec) && wasEncountered(FunctionDefinition::definition(dec))) |
---|
487 | continue; //Do not steal declarations |
---|
488 | } |
---|
489 | |
---|
490 | if(FunctionDefinition* funDef = dynamic_cast<FunctionDefinition*>(currentDeclaration())) { |
---|
491 | funDef->setDeclaration(dec); |
---|
492 | } |
---|
493 | |
---|
494 | found = true; |
---|
495 | break; |
---|
496 | } |
---|
497 | if(found) |
---|
498 | break; |
---|
499 | } |
---|
500 | } |
---|
501 | } |
---|
502 | } |
---|
503 | |
---|
504 | closeDeclaration(); |
---|
505 | |
---|
506 | node->parameter_declaration_clause = parameter_declaration_clause_backup; |
---|
507 | } |
---|
508 | |
---|
509 | ForwardDeclaration * DeclarationBuilder::openForwardDeclaration(NameAST * name, AST * range) |
---|
510 | { |
---|
511 | return openDeclaration<ForwardDeclaration>(name, range); |
---|
512 | } |
---|
513 | |
---|
514 | template<class Type> |
---|
515 | Type hasTemplateContext( const QList<Type>& contexts ) { |
---|
516 | foreach( const Type& context, contexts ) |
---|
517 | if( context && context->type() == KDevelop::DUContext::Template ) |
---|
518 | return context; |
---|
519 | return Type(0); |
---|
520 | } |
---|
521 | |
---|
522 | DUContext::Import hasTemplateContext( const QVector<DUContext::Import>& contexts, TopDUContext* top ) { |
---|
523 | foreach( const DUContext::Import& context, contexts ) |
---|
524 | if( context.context(top) && context.context(top)->type() == KDevelop::DUContext::Template ) |
---|
525 | return context; |
---|
526 | |
---|
527 | return DUContext::Import(); |
---|
528 | } |
---|
529 | |
---|
530 | //Check whether the given context is a template-context by checking whether it imports a template-parameter context |
---|
531 | KDevelop::DUContext* isTemplateContext( KDevelop::DUContext* context ) { |
---|
532 | return hasTemplateContext( context->importedParentContexts(), context->topContext() ).context(context->topContext()); |
---|
533 | } |
---|
534 | |
---|
535 | template<class T> |
---|
536 | T* DeclarationBuilder::openDeclaration(NameAST* name, AST* rangeNode, const Identifier& customName, bool collapseRangeAtStart, bool collapseRangeAtEnd) |
---|
537 | { |
---|
538 | DUChainWriteLocker lock(DUChain::lock()); |
---|
539 | |
---|
540 | KDevelop::DUContext* templateCtx = hasTemplateContext(m_importedParentContexts, topContext()).context(topContext()); |
---|
541 | |
---|
542 | ///We always need to create a template declaration when we're within a template, so the declaration can be accessed |
---|
543 | ///by specialize(..) and its indirect DeclarationId |
---|
544 | if( templateCtx || m_templateDeclarationDepth ) { |
---|
545 | Cpp::SpecialTemplateDeclaration<T>* ret = openDeclarationReal<Cpp::SpecialTemplateDeclaration<T> >( name, rangeNode, customName, collapseRangeAtStart, collapseRangeAtEnd ); |
---|
546 | ret->setTemplateParameterContext(templateCtx); |
---|
547 | return ret; |
---|
548 | } else{ |
---|
549 | return openDeclarationReal<T>( name, rangeNode, customName, collapseRangeAtStart, collapseRangeAtEnd ); |
---|
550 | } |
---|
551 | } |
---|
552 | |
---|
553 | template<class T> |
---|
554 | T* DeclarationBuilder::openDeclarationReal(NameAST* name, AST* rangeNode, const Identifier& customName, bool collapseRangeAtStart, bool collapseRangeAtEnd, const RangeInRevision* customRange) |
---|
555 | { |
---|
556 | RangeInRevision newRange; |
---|
557 | if(name) { |
---|
558 | uint start = name->unqualified_name->start_token; |
---|
559 | uint end = name->unqualified_name->end_token; |
---|
560 | |
---|
561 | //We must exclude the tilde. Else we may get totally messed up ranges when the name of a destructor is renamed in a macro |
---|
562 | if(name->unqualified_name->tilde) |
---|
563 | start = name->unqualified_name->tilde+1; |
---|
564 | |
---|
565 | newRange = editor()->findRange(start, end); |
---|
566 | }else if(rangeNode) { |
---|
567 | newRange = editor()->findRange(rangeNode); |
---|
568 | }else if(customRange) { |
---|
569 | newRange = *customRange; |
---|
570 | } |
---|
571 | |
---|
572 | if(collapseRangeAtStart) |
---|
573 | newRange.end = newRange.start; |
---|
574 | else if(collapseRangeAtEnd) |
---|
575 | newRange.start = newRange.end; |
---|
576 | |
---|
577 | Identifier localId = customName; |
---|
578 | |
---|
579 | if (name) { |
---|
580 | //If this is an operator thing, build the type first. Since it's part of the name, the type-builder doesn't catch it normally |
---|
581 | if(name->unqualified_name && name->unqualified_name->operator_id) |
---|
582 | visit(name->unqualified_name->operator_id); |
---|
583 | |
---|
584 | QualifiedIdentifier id; |
---|
585 | identifierForNode(name, id); |
---|
586 | |
---|
587 | if(localId.isEmpty()) |
---|
588 | localId = id.last(); |
---|
589 | } |
---|
590 | |
---|
591 | T* declaration = 0; |
---|
592 | |
---|
593 | if (recompiling()) { |
---|
594 | // Seek a matching declaration |
---|
595 | |
---|
596 | ///@todo maybe order the declarations within ducontext and change here back to walking the indices, because that's easier to debug and faster |
---|
597 | QList<Declaration*> decls = currentContext()->findLocalDeclarations(localId, CursorInRevision::invalid(), 0, AbstractType::Ptr(), DUContext::NoFiltering); |
---|
598 | foreach( Declaration* dec, decls ) { |
---|
599 | |
---|
600 | if( wasEncountered(dec) ) |
---|
601 | continue; |
---|
602 | |
---|
603 | if (dec->range() == newRange && |
---|
604 | (localId == dec->identifier() || (localId.isUnique() && dec->identifier().isUnique())) && |
---|
605 | typeid(T) == typeid(*dec) |
---|
606 | ) |
---|
607 | { |
---|
608 | // Match |
---|
609 | TemplateDeclaration* templateDecl = dynamic_cast<TemplateDeclaration*>(dec); |
---|
610 | if(templateDecl) |
---|
611 | templateDecl->deleteAllInstantiations(); //Delete all instantiations so we have a fresh start |
---|
612 | |
---|
613 | declaration = dynamic_cast<T*>(dec); |
---|
614 | break; |
---|
615 | } |
---|
616 | } |
---|
617 | |
---|
618 | if(!declaration) { |
---|
619 | ///Second run of the above, this time ignoring the ranges. |
---|
620 | foreach( Declaration* dec, decls ) { |
---|
621 | if( wasEncountered(dec) ) |
---|
622 | continue; |
---|
623 | |
---|
624 | if ((localId == dec->identifier() || (localId.isUnique() && dec->identifier().isUnique())) && |
---|
625 | typeid(*dec) == typeid(T) |
---|
626 | ) |
---|
627 | { |
---|
628 | // Match |
---|
629 | declaration = dynamic_cast<T*>(dec); |
---|
630 | declaration->setRange(newRange); |
---|
631 | break; |
---|
632 | } |
---|
633 | } |
---|
634 | } |
---|
635 | } |
---|
636 | #ifdef DEBUG_UPDATE_MATCHING |
---|
637 | if(declaration) |
---|
638 | kDebug() << "found match for" << localId.toString(); |
---|
639 | else |
---|
640 | kDebug() << "nothing found for" << localId.toString(); |
---|
641 | #endif |
---|
642 | |
---|
643 | if (!declaration) { |
---|
644 | if(currentContext()->inSymbolTable()) |
---|
645 | m_changeWasSignificant = true; //We are adding a declaration that comes into the symbol table, so mark the change significant |
---|
646 | |
---|
647 | declaration = new T(newRange, currentContext()); |
---|
648 | declaration->setIdentifier(localId); |
---|
649 | } |
---|
650 | |
---|
651 | //Clear some settings |
---|
652 | AbstractFunctionDeclaration* funDecl = dynamic_cast<AbstractFunctionDeclaration*>(declaration); |
---|
653 | if(funDecl) |
---|
654 | funDecl->clearDefaultParameters(); |
---|
655 | |
---|
656 | declaration->setDeclarationIsDefinition(false); //May be set later |
---|
657 | |
---|
658 | declaration->setIsTypeAlias(m_inTypedef); |
---|
659 | |
---|
660 | if( localId.templateIdentifiersCount() ) { |
---|
661 | TemplateDeclaration* templateDecl = dynamic_cast<TemplateDeclaration*>(declaration); |
---|
662 | if( declaration && templateDecl ) { |
---|
663 | ///This is a template-specialization. Find the class it is specialized from. |
---|
664 | localId.clearTemplateIdentifiers(); |
---|
665 | |
---|
666 | ///@todo Make sure the searched class is in the same namespace |
---|
667 | QList<Declaration*> decls = currentContext()->findDeclarations(QualifiedIdentifier(localId), editor()->findPosition(name->start_token, CppEditorIntegrator::FrontEdge) ); |
---|
668 | |
---|
669 | if( !decls.isEmpty() ) |
---|
670 | { |
---|
671 | foreach( Declaration* decl, decls ) |
---|
672 | if( TemplateDeclaration* baseTemplateDecl = dynamic_cast<TemplateDeclaration*>(decl) ) { |
---|
673 | templateDecl->setSpecializedFrom(baseTemplateDecl); |
---|
674 | break; |
---|
675 | } |
---|
676 | |
---|
677 | if( !templateDecl->specializedFrom().isValid() ) |
---|
678 | kDebug(9007) << "Could not find valid specialization-base" << localId.toString() << "for" << declaration->toString(); |
---|
679 | } |
---|
680 | } else { |
---|
681 | kDebug(9007) << "Specialization of non-template class" << declaration->toString(); |
---|
682 | } |
---|
683 | |
---|
684 | } |
---|
685 | |
---|
686 | declaration->setComment(comment()); |
---|
687 | clearComment(); |
---|
688 | |
---|
689 | setEncountered(declaration); |
---|
690 | |
---|
691 | m_declarationStack.push(declaration); |
---|
692 | |
---|
693 | return declaration; |
---|
694 | } |
---|
695 | |
---|
696 | ClassDeclaration* DeclarationBuilder::openClassDefinition(NameAST* name, AST* range, bool collapseRange, ClassDeclarationData::ClassType classType) { |
---|
697 | Identifier id; |
---|
698 | |
---|
699 | if(!name) { |
---|
700 | //Unnamed class/struct, use a unique id |
---|
701 | static QAtomicInt& uniqueClassNumber( KDevelop::globalItemRepositoryRegistry().getCustomCounter("Unnamed Class Ids", 1) ); |
---|
702 | id = Identifier::unique( uniqueClassNumber.fetchAndAddRelaxed(1) ); |
---|
703 | } |
---|
704 | |
---|
705 | ClassDeclaration* ret = openDeclaration<ClassDeclaration>(name, range, id, collapseRange); |
---|
706 | DUChainWriteLocker lock(DUChain::lock()); |
---|
707 | ret->setDeclarationIsDefinition(true); |
---|
708 | ret->clearBaseClasses(); |
---|
709 | |
---|
710 | if(m_accessPolicyStack.isEmpty()) |
---|
711 | ret->setAccessPolicy(KDevelop::Declaration::Public); |
---|
712 | else |
---|
713 | ret->setAccessPolicy(currentAccessPolicy()); |
---|
714 | |
---|
715 | ret->setClassType(classType); |
---|
716 | return ret; |
---|
717 | } |
---|
718 | |
---|
719 | Declaration* DeclarationBuilder::openDefinition(NameAST* name, AST* rangeNode, bool collapseRange) |
---|
720 | { |
---|
721 | Declaration* ret = openNormalDeclaration(name, rangeNode, KDevelop::Identifier(), collapseRange); |
---|
722 | |
---|
723 | ///Create mappings iff the AST feature is specified |
---|
724 | if(m_mapAst && !m_mappedNodes.empty()) |
---|
725 | editor()->parseSession()->mapAstDuChain(m_mappedNodes.top(), KDevelop::DeclarationPointer(ret)); |
---|
726 | |
---|
727 | DUChainWriteLocker lock(DUChain::lock()); |
---|
728 | ret->setDeclarationIsDefinition(true); |
---|
729 | return ret; |
---|
730 | } |
---|
731 | |
---|
732 | Declaration* DeclarationBuilder::openNormalDeclaration(NameAST* name, AST* rangeNode, const Identifier& customName, bool collapseRange) { |
---|
733 | if(currentContext()->type() == DUContext::Class) { |
---|
734 | ClassMemberDeclaration* mem = openDeclaration<ClassMemberDeclaration>(name, rangeNode, customName, collapseRange); |
---|
735 | |
---|
736 | DUChainWriteLocker lock(DUChain::lock()); |
---|
737 | mem->setAccessPolicy(currentAccessPolicy()); |
---|
738 | return mem; |
---|
739 | } else if(currentContext()->type() == DUContext::Template) { |
---|
740 | return openDeclaration<TemplateParameterDeclaration>(name, rangeNode, customName, collapseRange); |
---|
741 | } else { |
---|
742 | return openDeclaration<Declaration>(name, rangeNode, customName, collapseRange); |
---|
743 | } |
---|
744 | } |
---|
745 | |
---|
746 | Declaration* DeclarationBuilder::openFunctionDeclaration(NameAST* name, AST* rangeNode) { |
---|
747 | |
---|
748 | QualifiedIdentifier id; |
---|
749 | identifierForNode(name, id); |
---|
750 | Identifier localId = id.last(); //This also copies the template arguments |
---|
751 | if(id.count() > 1) { |
---|
752 | //Merge the scope of the declaration, and put them tog. Add semicolons instead of the ::, so you can see it's not a qualified identifier. |
---|
753 | //Else the declarations could be confused with global functions. |
---|
754 | //This is done before the actual search, so there are no name-clashes while searching the class for a constructor. |
---|
755 | |
---|
756 | QString newId = id.last().identifier().str(); |
---|
757 | for(int a = id.count()-2; a >= 0; --a) |
---|
758 | newId = id.at(a).identifier().str() + "::" + newId; |
---|
759 | |
---|
760 | localId.setIdentifier(newId); |
---|
761 | |
---|
762 | FunctionDefinition* ret = openDeclaration<FunctionDefinition>(name, rangeNode, localId); |
---|
763 | DUChainWriteLocker lock(DUChain::lock()); |
---|
764 | ret->setDeclaration(0); |
---|
765 | return ret; |
---|
766 | } |
---|
767 | |
---|
768 | if(currentContext()->type() == DUContext::Class) { |
---|
769 | DUChainWriteLocker lock; |
---|
770 | ClassFunctionDeclaration* fun = 0; |
---|
771 | if(!m_collectQtFunctionSignature) { |
---|
772 | fun = openDeclaration<ClassFunctionDeclaration>(name, rangeNode, localId); |
---|
773 | }else{ |
---|
774 | QtFunctionDeclaration* qtFun = openDeclaration<QtFunctionDeclaration>(name, rangeNode, localId); |
---|
775 | fun = qtFun; |
---|
776 | qtFun->setIsSlot(m_accessPolicyStack.top() & FunctionIsSlot); |
---|
777 | qtFun->setIsSignal(m_accessPolicyStack.top() & FunctionIsSignal); |
---|
778 | QByteArray temp(QMetaObject::normalizedSignature("(" + m_qtFunctionSignature + ")")); |
---|
779 | IndexedString signature(temp.mid(1, temp.length()-2)); |
---|
780 | // kDebug() << "normalized signature:" << signature.str() << "from:" << QString::fromUtf8(m_qtFunctionSignature); |
---|
781 | qtFun->setNormalizedSignature(signature); |
---|
782 | } |
---|
783 | Q_ASSERT(fun); |
---|
784 | fun->setAccessPolicy(currentAccessPolicy()); |
---|
785 | fun->setIsAbstract(m_functionFlag == AbstractFunction); |
---|
786 | return fun; |
---|
787 | } else if(m_inFunctionDefinition && (currentContext()->type() == DUContext::Namespace || currentContext()->type() == DUContext::Global)) { |
---|
788 | //May be a definition |
---|
789 | FunctionDefinition* ret = openDeclaration<FunctionDefinition>(name, rangeNode, localId); |
---|
790 | DUChainWriteLocker lock(DUChain::lock()); |
---|
791 | ret->setDeclaration(0); |
---|
792 | return ret; |
---|
793 | }else{ |
---|
794 | return openDeclaration<FunctionDeclaration>(name, rangeNode, localId); |
---|
795 | } |
---|
796 | } |
---|
797 | |
---|
798 | void DeclarationBuilder::classTypeOpened(AbstractType::Ptr type) { |
---|
799 | //We override this so we can get the class-declaration into a usable state(with filled type) earlier |
---|
800 | DUChainWriteLocker lock(DUChain::lock()); |
---|
801 | |
---|
802 | IdentifiedType* idType = dynamic_cast<IdentifiedType*>(type.unsafeData()); |
---|
803 | |
---|
804 | if( idType && !idType->declarationId().isValid() ) //When the given type has no declaration yet, assume we are declaring it now |
---|
805 | idType->setDeclaration( currentDeclaration() ); |
---|
806 | |
---|
807 | currentDeclaration()->setType(type); |
---|
808 | } |
---|
809 | |
---|
810 | void DeclarationBuilder::closeDeclaration(bool forceInstance) |
---|
811 | { |
---|
812 | { |
---|
813 | DUChainWriteLocker lock(DUChain::lock()); |
---|
814 | |
---|
815 | if (lastType()) { |
---|
816 | |
---|
817 | AbstractType::Ptr type = typeForCurrentDeclaration(); |
---|
818 | IdentifiedType* idType = dynamic_cast<IdentifiedType*>(type.unsafeData()); |
---|
819 | DelayedType::Ptr delayed = type.cast<DelayedType>(); |
---|
820 | |
---|
821 | //When the given type has no declaration yet, assume we are declaring it now. |
---|
822 | //If the type is a delayed type, it is a searched type, and not a declared one, so don't set the declaration then. |
---|
823 | if( !forceInstance && idType && !idType->declarationId().isValid() && !delayed ) { |
---|
824 | idType->setDeclaration( currentDeclaration() ); |
---|
825 | //Q_ASSERT(idType->declaration() == currentDeclaration()); |
---|
826 | } |
---|
827 | |
---|
828 | if(currentDeclaration()->kind() != Declaration::NamespaceAlias && currentDeclaration()->kind() != Declaration::Alias) { |
---|
829 | //If the type is not identified, it is an instance-declaration too, because those types have no type-declarations. |
---|
830 | if( (((!idType) || (idType && idType->declarationId() != currentDeclaration()->id())) && !currentDeclaration()->isTypeAlias() && !currentDeclaration()->isForwardDeclaration() ) || dynamic_cast<AbstractFunctionDeclaration*>(currentDeclaration()) || forceInstance ) |
---|
831 | currentDeclaration()->setKind(Declaration::Instance); |
---|
832 | else |
---|
833 | currentDeclaration()->setKind(Declaration::Type); |
---|
834 | } |
---|
835 | |
---|
836 | currentDeclaration()->setType(type); |
---|
837 | }else{ |
---|
838 | currentDeclaration()->setAbstractType(AbstractType::Ptr()); |
---|
839 | if(dynamic_cast<ClassDeclaration*>(currentDeclaration())) |
---|
840 | currentDeclaration()->setKind(Declaration::Type); |
---|
841 | } |
---|
842 | if(TemplateDeclaration* templateDecl = dynamic_cast<TemplateDeclaration*>(currentDeclaration())) { |
---|
843 | //The context etc. may have been filled with new items, and the declaration may have been searched unsuccessfully, or wrong instantiations created. |
---|
844 | TemplateDeclaration* deleteInstantiationsOf = 0; |
---|
845 | if(templateDecl->instantiatedFrom()) |
---|
846 | deleteInstantiationsOf = templateDecl->instantiatedFrom(); |
---|
847 | else if(templateDecl->specializedFrom().data()) |
---|
848 | deleteInstantiationsOf = dynamic_cast<TemplateDeclaration*>(templateDecl->specializedFrom().data()); |
---|
849 | else |
---|
850 | deleteInstantiationsOf = templateDecl; |
---|
851 | |
---|
852 | if(deleteInstantiationsOf) { |
---|
853 | CppDUContext<DUContext>* ctx = dynamic_cast<CppDUContext<DUContext>*>(dynamic_cast<Declaration*>(deleteInstantiationsOf)->internalContext()); |
---|
854 | deleteInstantiationsOf->deleteAllInstantiations(); |
---|
855 | if(ctx) |
---|
856 | ctx->deleteAllInstantiations(); |
---|
857 | } |
---|
858 | } |
---|
859 | } |
---|
860 | |
---|
861 | if(lastContext() && (lastContext()->type() != DUContext::Other || currentDeclaration()->isFunctionDeclaration())) |
---|
862 | eventuallyAssignInternalContext(); |
---|
863 | |
---|
864 | ifDebugCurrentFile( DUChainReadLocker lock(DUChain::lock()); kDebug() << "closing declaration" << currentDeclaration()->toString() << "type" << (currentDeclaration()->abstractType() ? currentDeclaration()->abstractType()->toString() : QString("notype")) << "last:" << (lastType() ? lastType()->toString() : QString("(notype)")); ) |
---|
865 | |
---|
866 | m_lastDeclaration = m_declarationStack.pop(); |
---|
867 | } |
---|
868 | |
---|
869 | void DeclarationBuilder::visitTypedef(TypedefAST *def) |
---|
870 | { |
---|
871 | parseComments(def->comments); |
---|
872 | |
---|
873 | DeclarationBuilderBase::visitTypedef(def); |
---|
874 | } |
---|
875 | |
---|
876 | void DeclarationBuilder::visitEnumSpecifier(EnumSpecifierAST* node) |
---|
877 | { |
---|
878 | Declaration * declaration = 0; |
---|
879 | if (!node->isOpaque) { |
---|
880 | declaration = openDefinition(node->name, node, node->name == 0); |
---|
881 | } else { |
---|
882 | // opaque-enum-declaration |
---|
883 | declaration = openForwardDeclaration(node->name, node); |
---|
884 | } |
---|
885 | |
---|
886 | ///Create mappings iff the AST feature is specified |
---|
887 | if(m_mapAst) |
---|
888 | editor()->parseSession()->mapAstDuChain(node, KDevelop::DeclarationPointer(declaration)); |
---|
889 | |
---|
890 | DeclarationBuilderBase::visitEnumSpecifier(node); |
---|
891 | |
---|
892 | closeDeclaration(); |
---|
893 | } |
---|
894 | |
---|
895 | ///Replaces a CppTemplateParameterType with a DelayedType |
---|
896 | struct TemplateTypeExchanger : public KDevelop::TypeExchanger { |
---|
897 | |
---|
898 | TemplateTypeExchanger(TopDUContext* top) : m_top(top) { |
---|
899 | } |
---|
900 | |
---|
901 | virtual AbstractType::Ptr exchange( const AbstractType::Ptr& type ) |
---|
902 | { |
---|
903 | if(CppTemplateParameterType::Ptr templateParamType = type.cast<CppTemplateParameterType>()) { |
---|
904 | Declaration* decl = templateParamType->declaration(m_top); |
---|
905 | if(decl) { |
---|
906 | DelayedType::Ptr newType(new DelayedType()); |
---|
907 | |
---|
908 | IndexedTypeIdentifier id(QualifiedIdentifier(decl->identifier())); |
---|
909 | |
---|
910 | if(type->modifiers() & AbstractType::ConstModifier) |
---|
911 | id.setIsConstant(true); |
---|
912 | |
---|
913 | newType->setIdentifier(id); |
---|
914 | newType->setKind(KDevelop::DelayedType::Delayed); |
---|
915 | |
---|
916 | return newType.cast<AbstractType>(); |
---|
917 | } |
---|
918 | } |
---|
919 | return type; |
---|
920 | } |
---|
921 | private: |
---|
922 | TopDUContext* m_top; |
---|
923 | }; |
---|
924 | |
---|
925 | Cpp::InstantiationInformation DeclarationBuilder::createSpecializationInformation(Cpp::InstantiationInformation base, UnqualifiedNameAST* name, KDevelop::DUContext* templateContext) { |
---|
926 | if(name->template_arguments || base.isValid()) |
---|
927 | { |
---|
928 | //Append a scope part |
---|
929 | InstantiationInformation newCurrent; |
---|
930 | newCurrent.previousInstantiationInformation = base.indexed(); |
---|
931 | if(!name->template_arguments) |
---|
932 | return newCurrent; |
---|
933 | //Process the template arguments if they exist |
---|
934 | const ListNode<TemplateArgumentAST*> * start = name->template_arguments->toFront(); |
---|
935 | const ListNode<TemplateArgumentAST*> * current = start; |
---|
936 | do { |
---|
937 | NameASTVisitor visitor(editor()->parseSession(), 0, templateContext, currentContext()->topContext(), templateContext, templateContext->range().end/*, DUContext::NoUndefinedTemplateParams*/); |
---|
938 | ExpressionEvaluationResult res = visitor.processTemplateArgument(current->element); |
---|
939 | AbstractType::Ptr type = res.type.abstractType(); |
---|
940 | |
---|
941 | TemplateTypeExchanger exchanger(currentContext()->topContext()); |
---|
942 | |
---|
943 | if(type) { |
---|
944 | type = exchanger.exchange(type); |
---|
945 | type->exchangeTypes(&exchanger); |
---|
946 | } |
---|
947 | |
---|
948 | newCurrent.addTemplateParameter(type); |
---|
949 | |
---|
950 | current = current->next; |
---|
951 | }while(current != start); |
---|
952 | return newCurrent; |
---|
953 | }else{ |
---|
954 | return base; |
---|
955 | } |
---|
956 | } |
---|
957 | |
---|
958 | Cpp::IndexedInstantiationInformation DeclarationBuilder::createSpecializationInformation(NameAST* name, DUContext* templateContext) |
---|
959 | { |
---|
960 | InstantiationInformation currentInfo; |
---|
961 | if(name->qualified_names) { |
---|
962 | const ListNode<UnqualifiedNameAST*> * start = name->qualified_names->toFront(); |
---|
963 | const ListNode<UnqualifiedNameAST*> * current = start; |
---|
964 | do { |
---|
965 | currentInfo = createSpecializationInformation(currentInfo, current->element, templateContext); |
---|
966 | current = current->next; |
---|
967 | }while(current != start); |
---|
968 | } |
---|
969 | if(name->unqualified_name) |
---|
970 | currentInfo = createSpecializationInformation(currentInfo, name->unqualified_name, templateContext); |
---|
971 | return currentInfo.indexed(); |
---|
972 | } |
---|
973 | |
---|
974 | void DeclarationBuilder::visitEnumerator(EnumeratorAST* node) |
---|
975 | { |
---|
976 | //Ugly hack: Since we want the identifier only to have the range of the id(not |
---|
977 | //the assigned expression), we change the range of the node temporarily |
---|
978 | uint oldEndToken = node->end_token; |
---|
979 | node->end_token = node->id + 1; |
---|
980 | |
---|
981 | Identifier id(editor()->parseSession()->token_stream->token(node->id).symbol()); |
---|
982 | Declaration* decl = openNormalDeclaration(0, node, id); |
---|
983 | |
---|
984 | node->end_token = oldEndToken; |
---|
985 | |
---|
986 | DeclarationBuilderBase::visitEnumerator(node); |
---|
987 | |
---|
988 | EnumeratorType::Ptr enumeratorType = lastType().cast<EnumeratorType>(); |
---|
989 | |
---|
990 | if(ClassMemberDeclaration* classMember = dynamic_cast<ClassMemberDeclaration*>(currentDeclaration())) { |
---|
991 | DUChainWriteLocker lock(DUChain::lock()); |
---|
992 | classMember->setStatic(true); |
---|
993 | } |
---|
994 | |
---|
995 | closeDeclaration(true); |
---|
996 | |
---|
997 | if(enumeratorType) { ///@todo Move this into closeDeclaration in a logical way |
---|
998 | DUChainWriteLocker lock(DUChain::lock()); |
---|
999 | enumeratorType->setDeclaration(decl); |
---|
1000 | decl->setAbstractType(enumeratorType.cast<AbstractType>()); |
---|
1001 | }else if(!lastType().cast<DelayedType>()){ //If it's in a template, it may be DelayedType |
---|
1002 | AbstractType::Ptr type = lastType(); |
---|
1003 | kWarning() << "not assigned enumerator type:" << typeid(*type.unsafeData()).name() << type->toString(); |
---|
1004 | } |
---|
1005 | } |
---|
1006 | |
---|
1007 | void DeclarationBuilder::classContextOpened(ClassSpecifierAST* /*node*/, DUContext* context) { |
---|
1008 | |
---|
1009 | //We need to set this early, so we can do correct search while building |
---|
1010 | DUChainWriteLocker lock(DUChain::lock()); |
---|
1011 | currentDeclaration()->setInternalContext(context); |
---|
1012 | } |
---|
1013 | |
---|
1014 | void DeclarationBuilder::closeContext() |
---|
1015 | { |
---|
1016 | if (!m_pendingPropertyDeclarations.isEmpty()) { |
---|
1017 | if(m_pendingPropertyDeclarations.contains(currentContext())) |
---|
1018 | resolvePendingPropertyDeclarations(m_pendingPropertyDeclarations.values(currentContext())); |
---|
1019 | } |
---|
1020 | |
---|
1021 | DeclarationBuilderBase::closeContext(); |
---|
1022 | } |
---|
1023 | |
---|
1024 | void DeclarationBuilder::visitNamespace(NamespaceAST* ast) { |
---|
1025 | |
---|
1026 | { |
---|
1027 | RangeInRevision range; |
---|
1028 | Identifier id; |
---|
1029 | |
---|
1030 | if(ast->namespace_name) |
---|
1031 | { |
---|
1032 | id = Identifier(editor()->tokensToStrings(ast->namespace_name, ast->namespace_name+1)); |
---|
1033 | range = editor()->findRange(ast->namespace_name, ast->namespace_name+1); |
---|
1034 | }else |
---|
1035 | { |
---|
1036 | id = unnamedNamespaceIdentifier().identifier(); |
---|
1037 | range.start = editor()->findPosition(ast->linkage_body ? ast->linkage_body->start_token : ast->start_token, CppEditorIntegrator::FrontEdge); |
---|
1038 | range.end = range.start; |
---|
1039 | } |
---|
1040 | |
---|
1041 | DUChainWriteLocker lock(DUChain::lock()); |
---|
1042 | |
---|
1043 | Declaration * declaration = openDeclarationReal<Declaration>(0, 0, id, false, false, &range); |
---|
1044 | |
---|
1045 | ///Create mappings iff the AST feature is specified |
---|
1046 | if(m_mapAst) |
---|
1047 | editor()->parseSession()->mapAstDuChain(ast, KDevelop::DeclarationPointer(declaration)); |
---|
1048 | } |
---|
1049 | |
---|
1050 | DeclarationBuilderBase::visitNamespace(ast); |
---|
1051 | |
---|
1052 | { |
---|
1053 | DUChainWriteLocker lock(DUChain::lock()); |
---|
1054 | currentDeclaration()->setKind(KDevelop::Declaration::Namespace); |
---|
1055 | clearLastType(); |
---|
1056 | closeDeclaration(); |
---|
1057 | } |
---|
1058 | } |
---|
1059 | |
---|
1060 | void DeclarationBuilder::visitClassSpecifier(ClassSpecifierAST *node) |
---|
1061 | { |
---|
1062 | PushValue<bool> setNotInTypedef(m_inTypedef, false); |
---|
1063 | |
---|
1064 | /**Open helper contexts around the class, so the qualified identifier matches. |
---|
1065 | * Example: "class MyClass::RealClass{}" |
---|
1066 | * Will create one helper-context named "MyClass" around RealClass |
---|
1067 | * */ |
---|
1068 | |
---|
1069 | CursorInRevision pos = editor()->findPosition(node->start_token, CppEditorIntegrator::FrontEdge); |
---|
1070 | |
---|
1071 | IndexedInstantiationInformation specializedWith; |
---|
1072 | |
---|
1073 | QualifiedIdentifier id; |
---|
1074 | if( node->name ) { |
---|
1075 | identifierForNode(node->name, id); |
---|
1076 | openPrefixContext(node, id, pos); |
---|
1077 | DUChainReadLocker lock(DUChain::lock()); |
---|
1078 | if(DUContext* templateContext = hasTemplateContext(m_importedParentContexts, topContext()).context(topContext())) { |
---|
1079 | specializedWith = createSpecializationInformation(node->name, templateContext); |
---|
1080 | } |
---|
1081 | } |
---|
1082 | |
---|
1083 | int kind = editor()->parseSession()->token_stream->kind(node->class_key); |
---|
1084 | |
---|
1085 | ClassDeclaration * declaration = openClassDefinition(node->name, node, node->name == 0, classTypeFromTokenKind(kind)); |
---|
1086 | |
---|
1087 | if (kind == Token_struct || kind == Token_union) |
---|
1088 | m_accessPolicyStack.push(Declaration::Public); |
---|
1089 | else |
---|
1090 | m_accessPolicyStack.push(Declaration::Private); |
---|
1091 | |
---|
1092 | DeclarationBuilderBase::visitClassSpecifier(node); |
---|
1093 | |
---|
1094 | eventuallyAssignInternalContext(); |
---|
1095 | |
---|
1096 | if( node->name ) { |
---|
1097 | ///Copy template default-parameters from the forward-declaration to the real declaration if possible |
---|
1098 | DUChainWriteLocker lock(DUChain::lock()); |
---|
1099 | |
---|
1100 | QList<Declaration*> declarations = Cpp::findDeclarationsSameLevel(currentContext(), id.last(), pos); |
---|
1101 | |
---|
1102 | foreach( Declaration* decl, declarations ) { |
---|
1103 | if( decl->abstractType()) { |
---|
1104 | ForwardDeclaration* forward = dynamic_cast<ForwardDeclaration*>(decl); |
---|
1105 | if( forward ) { |
---|
1106 | { |
---|
1107 | KDevelop::DUContext* forwardTemplateContext = forward->internalContext(); |
---|
1108 | if( forwardTemplateContext && forwardTemplateContext->type() == DUContext::Template ) { |
---|
1109 | |
---|
1110 | KDevelop::DUContext* currentTemplateContext = getTemplateContext(currentDeclaration()); |
---|
1111 | if( (bool)forwardTemplateContext != (bool)currentTemplateContext ) { |
---|
1112 | kDebug(9007) << "Template-contexts of forward- and real declaration do not match: " << currentTemplateContext << getTemplateContext(currentDeclaration()) << currentDeclaration()->internalContext() << forwardTemplateContext << currentDeclaration()->internalContext()->importedParentContexts().count(); |
---|
1113 | } else if( forwardTemplateContext && currentTemplateContext ) { |
---|
1114 | if( forwardTemplateContext->localDeclarations().count() != currentTemplateContext->localDeclarations().count() ) { |
---|
1115 | } else { |
---|
1116 | |
---|
1117 | const QVector<Declaration*>& forwardList = forwardTemplateContext->localDeclarations(); |
---|
1118 | const QVector<Declaration*>& realList = currentTemplateContext->localDeclarations(); |
---|
1119 | |
---|
1120 | QVector<Declaration*>::const_iterator forwardIt = forwardList.begin(); |
---|
1121 | QVector<Declaration*>::const_iterator realIt = realList.begin(); |
---|
1122 | |
---|
1123 | for( ; forwardIt != forwardList.end(); ++forwardIt, ++realIt ) { |
---|
1124 | TemplateParameterDeclaration* forwardParamDecl = dynamic_cast<TemplateParameterDeclaration*>(*forwardIt); |
---|
1125 | TemplateParameterDeclaration* realParamDecl = dynamic_cast<TemplateParameterDeclaration*>(*realIt); |
---|
1126 | if( forwardParamDecl && realParamDecl ) { |
---|
1127 | if( !forwardParamDecl->defaultParameter().isEmpty() ) |
---|
1128 | realParamDecl->setDefaultParameter(forwardParamDecl->defaultParameter()); |
---|
1129 | } |
---|
1130 | } |
---|
1131 | } |
---|
1132 | } |
---|
1133 | } |
---|
1134 | } |
---|
1135 | |
---|
1136 | //Update instantiations in case of template forward-declarations |
---|
1137 | // SpecialTemplateDeclaration<ForwardDeclaration>* templateForward = dynamic_cast<SpecialTemplateDeclaration<ForwardDeclaration>* > (decl); |
---|
1138 | // SpecialTemplateDeclaration<Declaration>* currentTemplate = dynamic_cast<SpecialTemplateDeclaration<Declaration>* > (currentDeclaration()); |
---|
1139 | // |
---|
1140 | // if( templateForward && currentTemplate ) |
---|
1141 | // { |
---|
1142 | // //Change the types of all the forward-template instantiations |
---|
1143 | // TemplateDeclaration::InstantiationsHash instantiations = templateForward->instantiations(); |
---|
1144 | // |
---|
1145 | // for( TemplateDeclaration::InstantiationsHash::iterator it = instantiations.begin(); it != instantiations.end(); ++it ) |
---|
1146 | // { |
---|
1147 | // Declaration* realInstance = currentTemplate->instantiate(it.key().args, ImportTrace()); |
---|
1148 | // Declaration* forwardInstance = dynamic_cast<Declaration*>(*it); |
---|
1149 | // //Now change the type of forwardInstance so it matches the type of realInstance |
---|
1150 | // CppClassType::Ptr realClass = realInstance->type<CppClassType>(); |
---|
1151 | // CppClassType::Ptr forwardClass = forwardInstance->type<CppClassType>(); |
---|
1152 | // |
---|
1153 | // if( realClass && forwardClass ) { |
---|
1154 | // //Copy the class from real into the forward-declaration's instance |
---|
1155 | // copyCppClass(realClass.data(), forwardClass.data()); |
---|
1156 | // } else { |
---|
1157 | // kDebug(9007) << "Bad types involved in formward-declaration"; |
---|
1158 | // } |
---|
1159 | // } |
---|
1160 | // }//templateForward && currentTemplate |
---|
1161 | } |
---|
1162 | } |
---|
1163 | }//foreach |
---|
1164 | |
---|
1165 | }//node-name |
---|
1166 | |
---|
1167 | TemplateDeclaration* tempDecl = dynamic_cast<TemplateDeclaration*>(currentDeclaration()); |
---|
1168 | |
---|
1169 | if(tempDecl) { |
---|
1170 | DUChainWriteLocker lock(DUChain::lock()); |
---|
1171 | tempDecl->setSpecializedWith(specializedWith); |
---|
1172 | } |
---|
1173 | closeDeclaration(); |
---|
1174 | |
---|
1175 | ///Create mappings iff the AST feature is specified |
---|
1176 | if(m_mapAst) |
---|
1177 | editor()->parseSession()->mapAstDuChain(node, KDevelop::DeclarationPointer(declaration)); |
---|
1178 | |
---|
1179 | if(node->name) |
---|
1180 | closePrefixContext(id); |
---|
1181 | |
---|
1182 | m_accessPolicyStack.pop(); |
---|
1183 | } |
---|
1184 | |
---|
1185 | void DeclarationBuilder::visitBaseSpecifier(BaseSpecifierAST *node) { |
---|
1186 | DeclarationBuilderBase::visitBaseSpecifier(node); |
---|
1187 | |
---|
1188 | BaseClassInstance instance; |
---|
1189 | { |
---|
1190 | DUChainWriteLocker lock(DUChain::lock()); |
---|
1191 | ClassDeclaration* currentClass = dynamic_cast<ClassDeclaration*>(currentDeclaration()); |
---|
1192 | if(currentClass) { |
---|
1193 | |
---|
1194 | instance.virtualInheritance = (bool)node->virt; |
---|
1195 | |
---|
1196 | //TypeUtils::unAliasedType( |
---|
1197 | instance.baseClass = TypeUtils::unAliasedType(lastType())->indexed(); |
---|
1198 | if(currentClass->classType() == ClassDeclarationData::Struct) |
---|
1199 | instance.access = KDevelop::Declaration::Public; |
---|
1200 | else |
---|
1201 | instance.access = KDevelop::Declaration::Private; |
---|
1202 | |
---|
1203 | if( node->access_specifier ) { |
---|
1204 | int tk = editor()->parseSession()->token_stream->token(node->access_specifier).kind; |
---|
1205 | |
---|
1206 | switch( tk ) { |
---|
1207 | case Token_private: |
---|
1208 | instance.access = KDevelop::Declaration::Private; |
---|
1209 | break; |
---|
1210 | case Token_public: |
---|
1211 | instance.access = KDevelop::Declaration::Public; |
---|
1212 | break; |
---|
1213 | case Token_protected: |
---|
1214 | instance.access = KDevelop::Declaration::Protected; |
---|
1215 | break; |
---|
1216 | } |
---|
1217 | } |
---|
1218 | |
---|
1219 | currentClass->addBaseClass(instance); |
---|
1220 | }else{ |
---|
1221 | kWarning() << "base-specifier without class declaration"; |
---|
1222 | } |
---|
1223 | } |
---|
1224 | addBaseType(instance, node); |
---|
1225 | } |
---|
1226 | |
---|
1227 | QualifiedIdentifier DeclarationBuilder::resolveNamespaceIdentifier(const QualifiedIdentifier& identifier, const CursorInRevision& position) |
---|
1228 | { |
---|
1229 | QList< Declaration* > decls = currentContext()->findDeclarations(identifier, position); |
---|
1230 | |
---|
1231 | QList<DUContext*> contexts; |
---|
1232 | |
---|
1233 | // qlist does not provide convenient stable iterators |
---|
1234 | for (QList<Declaration*>::iterator it = decls.begin(); it != decls.end(); ++it) { |
---|
1235 | Declaration * decl = *it; |
---|
1236 | if(decl->kind() == Declaration::Namespace && decl->internalContext()) { |
---|
1237 | contexts << decl->internalContext(); |
---|
1238 | } else if (decl->kind() == Declaration::NamespaceAlias) { |
---|
1239 | NamespaceAliasDeclaration *aliasDecl = dynamic_cast<NamespaceAliasDeclaration*>(decl); |
---|
1240 | if (aliasDecl) { |
---|
1241 | QList<Declaration*> importedDecls = currentContext()->findDeclarations(aliasDecl->importIdentifier(), position); |
---|
1242 | std::copy(importedDecls.begin(), importedDecls.end(), |
---|
1243 | std::back_inserter(decls)); |
---|
1244 | } |
---|
1245 | } |
---|
1246 | } |
---|
1247 | |
---|
1248 | if( contexts.isEmpty() ) { |
---|
1249 | //Failed to resolve namespace |
---|
1250 | kDebug(9007) << "Failed to resolve namespace \"" << identifier << "\""; |
---|
1251 | QualifiedIdentifier ret = identifier; |
---|
1252 | ret.setExplicitlyGlobal(false); |
---|
1253 | Q_ASSERT(ret.count()); |
---|
1254 | return ret; |
---|
1255 | } else { |
---|
1256 | QualifiedIdentifier ret = contexts.first()->scopeIdentifier(true); |
---|
1257 | ret.setExplicitlyGlobal(false); |
---|
1258 | if(ret.isEmpty()) |
---|
1259 | return ret; |
---|
1260 | Q_ASSERT(ret.count()); |
---|
1261 | return ret; |
---|
1262 | } |
---|
1263 | } |
---|
1264 | |
---|
1265 | void DeclarationBuilder::visitUsing(UsingAST * node) |
---|
1266 | { |
---|
1267 | DeclarationBuilderBase::visitUsing(node); |
---|
1268 | |
---|
1269 | QualifiedIdentifier id; |
---|
1270 | identifierForNode(node->name, id); |
---|
1271 | |
---|
1272 | ///@todo only use the last name component as range |
---|
1273 | AliasDeclaration* decl = openDeclaration<AliasDeclaration>(0, node->name ? (AST*)node->name : (AST*)node, id.last()); |
---|
1274 | { |
---|
1275 | DUChainWriteLocker lock(DUChain::lock()); |
---|
1276 | |
---|
1277 | CursorInRevision pos = editor()->findPosition(node->start_token, CppEditorIntegrator::FrontEdge); |
---|
1278 | QList<Declaration*> declarations = currentContext()->findDeclarations(id, pos); |
---|
1279 | if(!declarations.isEmpty()) { |
---|
1280 | decl->setAliasedDeclaration(declarations[0]); |
---|
1281 | }else{ |
---|
1282 | kDebug(9007) << "Aliased declaration not found:" << id.toString(); |
---|
1283 | } |
---|
1284 | |
---|
1285 | if(m_accessPolicyStack.isEmpty()) |
---|
1286 | decl->setAccessPolicy(KDevelop::Declaration::Public); |
---|
1287 | else |
---|
1288 | decl->setAccessPolicy(currentAccessPolicy()); |
---|
1289 | } |
---|
1290 | |
---|
1291 | closeDeclaration(); |
---|
1292 | } |
---|
1293 | |
---|
1294 | void DeclarationBuilder::visitUsingDirective(UsingDirectiveAST * node) |
---|
1295 | { |
---|
1296 | DeclarationBuilderBase::visitUsingDirective(node); |
---|
1297 | |
---|
1298 | if( compilingContexts() ) { |
---|
1299 | RangeInRevision range = editor()->findRange(node->start_token); |
---|
1300 | DUChainWriteLocker lock(DUChain::lock()); |
---|
1301 | NamespaceAliasDeclaration* decl = openDeclarationReal<NamespaceAliasDeclaration>(0, 0, globalImportIdentifier(), false, false, &range); |
---|
1302 | { |
---|
1303 | QualifiedIdentifier id; |
---|
1304 | identifierForNode(node->name, id); |
---|
1305 | decl->setImportIdentifier( resolveNamespaceIdentifier(id, currentDeclaration()->range().start) ); |
---|
1306 | } |
---|
1307 | closeDeclaration(); |
---|
1308 | } |
---|
1309 | } |
---|
1310 | |
---|
1311 | void DeclarationBuilder::visitAliasDeclaration(AliasDeclarationAST* node) |
---|
1312 | { |
---|
1313 | DeclarationBuilderBase::visitAliasDeclaration(node); |
---|
1314 | |
---|
1315 | if( compilingContexts() ) { |
---|
1316 | PushValue<bool> setTypeDef(m_inTypedef, true); |
---|
1317 | Declaration* decl = openDeclaration<Declaration>(node->name, node->name); |
---|
1318 | closeDeclaration(); |
---|
1319 | } |
---|
1320 | } |
---|
1321 | |
---|
1322 | void DeclarationBuilder::visitTypeId(TypeIdAST * typeId) |
---|
1323 | { |
---|
1324 | //TypeIdAST contains a declarator, but that one does not declare anything |
---|
1325 | PushValue<bool> disableDeclarators(m_ignoreDeclarators, true); |
---|
1326 | |
---|
1327 | DeclarationBuilderBase::visitTypeId(typeId); |
---|
1328 | } |
---|
1329 | |
---|
1330 | void DeclarationBuilder::visitNamespaceAliasDefinition(NamespaceAliasDefinitionAST* node) |
---|
1331 | { |
---|
1332 | DeclarationBuilderBase::visitNamespaceAliasDefinition(node); |
---|
1333 | |
---|
1334 | { |
---|
1335 | DUChainReadLocker lock(DUChain::lock()); |
---|
1336 | if( currentContext()->type() != DUContext::Namespace && currentContext()->type() != DUContext::Global ) { |
---|
1337 | ///@todo report problem |
---|
1338 | kDebug(9007) << "Namespace-alias used in non-global scope"; |
---|
1339 | } |
---|
1340 | } |
---|
1341 | |
---|
1342 | if( compilingContexts() ) { |
---|
1343 | RangeInRevision range = editor()->findRange(node->namespace_name); |
---|
1344 | DUChainWriteLocker lock(DUChain::lock()); |
---|
1345 | NamespaceAliasDeclaration* decl = openDeclarationReal<NamespaceAliasDeclaration>(0, 0, Identifier(editor()->parseSession()->token_stream->token(node->namespace_name).symbol()), false, false, &range); |
---|
1346 | { |
---|
1347 | QualifiedIdentifier id; |
---|
1348 | identifierForNode(node->alias_name, id); |
---|
1349 | decl->setImportIdentifier( resolveNamespaceIdentifier(id, currentDeclaration()->range().start) ); |
---|
1350 | } |
---|
1351 | closeDeclaration(); |
---|
1352 | } |
---|
1353 | } |
---|
1354 | |
---|
1355 | void DeclarationBuilder::visitElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST* node) |
---|
1356 | { |
---|
1357 | PushValue<bool> setNotInTypedef(m_inTypedef, false); |
---|
1358 | |
---|
1359 | int kind = editor()->parseSession()->token_stream->kind(node->type); |
---|
1360 | |
---|
1361 | if( kind == Token_typename ) { |
---|
1362 | //typename is completely handled by the type-builder |
---|
1363 | DeclarationBuilderBase::visitElaboratedTypeSpecifier(node); |
---|
1364 | return; |
---|
1365 | } |
---|
1366 | |
---|
1367 | bool isFriendDeclaration = !m_storageSpecifiers.isEmpty() && (m_storageSpecifiers.top() & ClassMemberDeclaration::FriendSpecifier); |
---|
1368 | |
---|
1369 | bool openedDeclaration = false; |
---|
1370 | |
---|
1371 | if (node->name) { |
---|
1372 | QualifiedIdentifier id; |
---|
1373 | identifierForNode(node->name, id); |
---|
1374 | |
---|
1375 | bool forwardDeclarationGlobal = false; |
---|
1376 | |
---|
1377 | if(m_typeSpecifierWithoutInitDeclarators != node->start_token || isFriendDeclaration) { |
---|
1378 | /**This is an elaborated type-specifier |
---|
1379 | * |
---|
1380 | * See iso c++ draft 3.3.4 for details. |
---|
1381 | * Said shortly it means: |
---|
1382 | * - Search for an existing declaration of the type. If it is found, |
---|
1383 | * it will be used, and we don't need to create a declaration. |
---|
1384 | * - If it is not found, create a forward-declaration in the global/namespace scope. |
---|
1385 | * - @todo While searching for the existing declarations, non-fitting overloaded names should be ignored. |
---|
1386 | * */ |
---|
1387 | |
---|
1388 | ///@todo think how this interacts with re-using duchains. In some cases a forward-declaration should still be created. |
---|
1389 | QList<Declaration*> declarations; |
---|
1390 | CursorInRevision pos = editor()->findPosition(node->start_token, CppEditorIntegrator::FrontEdge); |
---|
1391 | |
---|
1392 | { |
---|
1393 | DUChainReadLocker lock(DUChain::lock()); |
---|
1394 | |
---|
1395 | declarations = currentContext()->findDeclarations( id, pos); |
---|
1396 | |
---|
1397 | forwardDeclarationGlobal = true; |
---|
1398 | |
---|
1399 | //If a good declaration has been found, use its type. Else, create a new forward-declaration. |
---|
1400 | foreach(Declaration* decl, declarations) |
---|
1401 | { |
---|
1402 | if((decl->topContext() != currentContext()->topContext() || wasEncountered(decl)) && decl->abstractType()) |
---|
1403 | { |
---|
1404 | setLastType(declarations.first()->abstractType()); |
---|
1405 | |
---|
1406 | if( isFriendDeclaration ) { |
---|
1407 | lock.unlock(); |
---|
1408 | createFriendDeclaration(node); |
---|
1409 | } |
---|
1410 | return; |
---|
1411 | } |
---|
1412 | } |
---|
1413 | } |
---|
1414 | } |
---|
1415 | |
---|
1416 | node->isDeclaration = true; |
---|
1417 | |
---|
1418 | // Create forward declaration |
---|
1419 | switch (kind) { |
---|
1420 | case Token_class: |
---|
1421 | case Token_struct: |
---|
1422 | case Token_union: |
---|
1423 | case Token_enum: |
---|
1424 | |
---|
1425 | if(forwardDeclarationGlobal) { |
---|
1426 | //Open the global context, so it is currentContext() and we can insert the forward-declaration there |
---|
1427 | DUContext* globalCtx; |
---|
1428 | { |
---|
1429 | DUChainReadLocker lock(DUChain::lock()); |
---|
1430 | globalCtx = currentContext(); |
---|
1431 | while(globalCtx && globalCtx->type() != DUContext::Global && globalCtx->type() != DUContext::Namespace) |
---|
1432 | globalCtx = globalCtx->parentContext(); |
---|
1433 | Q_ASSERT(globalCtx); |
---|
1434 | } |
---|
1435 | |
---|
1436 | //Just temporarily insert the new context |
---|
1437 | injectContext( globalCtx ); |
---|
1438 | } |
---|
1439 | |
---|
1440 | openForwardDeclaration(node->name, node); |
---|
1441 | |
---|
1442 | if(forwardDeclarationGlobal) { |
---|
1443 | closeInjectedContext(); |
---|
1444 | } |
---|
1445 | |
---|
1446 | openedDeclaration = true; |
---|
1447 | break; |
---|
1448 | } |
---|
1449 | } |
---|
1450 | |
---|
1451 | DeclarationBuilderBase::visitElaboratedTypeSpecifier(node); |
---|
1452 | |
---|
1453 | if (openedDeclaration) { |
---|
1454 | /* DUChainWriteLocker lock(DUChain::lock()); |
---|
1455 | //Resolve forward-declarations that are declared after the real type was already declared |
---|
1456 | Q_ASSERT(dynamic_cast<ForwardDeclaration*>(currentDeclaration())); |
---|
1457 | IdentifiedType* idType = dynamic_cast<IdentifiedType*>(lastType().data()); |
---|
1458 | if(idType && idType->declaration()) |
---|
1459 | static_cast<ForwardDeclaration*>(currentDeclaration())->setResolved(idType->declaration());*/ |
---|
1460 | closeDeclaration(); |
---|
1461 | } |
---|
1462 | |
---|
1463 | if( isFriendDeclaration ) |
---|
1464 | createFriendDeclaration(node); |
---|
1465 | } |
---|
1466 | |
---|
1467 | void DeclarationBuilder::createFriendDeclaration(AST* range) { |
---|
1468 | static IndexedIdentifier friendIdentifier(Identifier("friend")); |
---|
1469 | openDeclaration<Declaration>(0, range, friendIdentifier.identifier(), true); |
---|
1470 | closeDeclaration(); |
---|
1471 | } |
---|
1472 | |
---|
1473 | void DeclarationBuilder::visitAccessSpecifier(AccessSpecifierAST* node) |
---|
1474 | { |
---|
1475 | bool isSlot = false; |
---|
1476 | bool isSignal = false; |
---|
1477 | if (node->specs) { |
---|
1478 | const ListNode<uint> *it = node->specs->toFront(); |
---|
1479 | const ListNode<uint> *end = it; |
---|
1480 | do { |
---|
1481 | int kind = editor()->parseSession()->token_stream->kind(it->element); |
---|
1482 | switch (kind) { |
---|
1483 | case Token___qt_slots__: |
---|
1484 | case Token_k_dcop: |
---|
1485 | isSlot = true; |
---|
1486 | break; |
---|
1487 | case Token_public: |
---|
1488 | setAccessPolicy(Declaration::Public); |
---|
1489 | break; |
---|
1490 | case Token_k_dcop_signals: |
---|
1491 | case Token___qt_signals__: |
---|
1492 | isSignal = true; |
---|
1493 | case Token_protected: |
---|
1494 | setAccessPolicy(Declaration::Protected); |
---|
1495 | break; |
---|
1496 | case Token_private: |
---|
1497 | setAccessPolicy(Declaration::Private); |
---|
1498 | break; |
---|
1499 | } |
---|
1500 | |
---|
1501 | it = it->next; |
---|
1502 | } while (it != end); |
---|
1503 | } |
---|
1504 | |
---|
1505 | if(isSignal) |
---|
1506 | setAccessPolicy((KDevelop::Declaration::AccessPolicy)(currentAccessPolicy() | FunctionIsSignal)); |
---|
1507 | |
---|
1508 | if(isSlot) |
---|
1509 | setAccessPolicy((KDevelop::Declaration::AccessPolicy)(currentAccessPolicy() | FunctionIsSlot)); |
---|
1510 | |
---|
1511 | |
---|
1512 | DeclarationBuilderBase::visitAccessSpecifier(node); |
---|
1513 | } |
---|
1514 | |
---|
1515 | void DeclarationBuilder::parseStorageSpecifiers(const ListNode<uint>* storage_specifiers) |
---|
1516 | { |
---|
1517 | ClassMemberDeclaration::StorageSpecifiers specs = 0; |
---|
1518 | |
---|
1519 | if (storage_specifiers) { |
---|
1520 | const ListNode<uint> *it = storage_specifiers->toFront(); |
---|
1521 | const ListNode<uint> *end = it; |
---|
1522 | do { |
---|
1523 | int kind = editor()->parseSession()->token_stream->kind(it->element); |
---|
1524 | switch (kind) { |
---|
1525 | case Token_friend: |
---|
1526 | specs |= ClassMemberDeclaration::FriendSpecifier; |
---|
1527 | break; |
---|
1528 | case Token_auto: |
---|
1529 | specs |= ClassMemberDeclaration::AutoSpecifier; |
---|
1530 | break; |
---|
1531 | case Token_register: |
---|
1532 | specs |= ClassMemberDeclaration::RegisterSpecifier; |
---|
1533 | break; |
---|
1534 | case Token_static: |
---|
1535 | specs |= ClassMemberDeclaration::StaticSpecifier; |
---|
1536 | break; |
---|
1537 | case Token_extern: |
---|
1538 | specs |= ClassMemberDeclaration::ExternSpecifier; |
---|
1539 | break; |
---|
1540 | case Token_mutable: |
---|
1541 | specs |= ClassMemberDeclaration::MutableSpecifier; |
---|
1542 | break; |
---|
1543 | } |
---|
1544 | |
---|
1545 | it = it->next; |
---|
1546 | } while (it != end); |
---|
1547 | } |
---|
1548 | |
---|
1549 | m_storageSpecifiers.push(specs); |
---|
1550 | } |
---|
1551 | |
---|
1552 | void DeclarationBuilder::parseFunctionSpecifiers(const ListNode<uint>* function_specifiers) |
---|
1553 | { |
---|
1554 | AbstractFunctionDeclaration::FunctionSpecifiers specs = 0; |
---|
1555 | |
---|
1556 | if (function_specifiers) { |
---|
1557 | const ListNode<uint> *it = function_specifiers->toFront(); |
---|
1558 | const ListNode<uint> *end = it; |
---|
1559 | do { |
---|
1560 | int kind = editor()->parseSession()->token_stream->kind(it->element); |
---|
1561 | switch (kind) { |
---|
1562 | case Token_inline: |
---|
1563 | specs |= AbstractFunctionDeclaration::InlineSpecifier; |
---|
1564 | break; |
---|
1565 | case Token_virtual: |
---|
1566 | specs |= AbstractFunctionDeclaration::VirtualSpecifier; |
---|
1567 | break; |
---|
1568 | case Token_explicit: |
---|
1569 | specs |= AbstractFunctionDeclaration::ExplicitSpecifier; |
---|
1570 | break; |
---|
1571 | } |
---|
1572 | |
---|
1573 | it = it->next; |
---|
1574 | } while (it != end); |
---|
1575 | } |
---|
1576 | |
---|
1577 | m_functionSpecifiers.push(specs); |
---|
1578 | } |
---|
1579 | |
---|
1580 | void DeclarationBuilder::visitParameterDeclaration(ParameterDeclarationAST* node) |
---|
1581 | { |
---|
1582 | if(m_mapAst) |
---|
1583 | m_mappedNodes.push(node); |
---|
1584 | |
---|
1585 | DeclarationBuilderBase::visitParameterDeclaration(node); |
---|
1586 | |
---|
1587 | AbstractFunctionDeclaration* function = currentDeclaration<AbstractFunctionDeclaration>(); |
---|
1588 | |
---|
1589 | if( function ) { |
---|
1590 | |
---|
1591 | if( node->expression ) { |
---|
1592 | DUChainWriteLocker lock(DUChain::lock()); |
---|
1593 | //Fill default-parameters |
---|
1594 | QString defaultParam = stringFromSessionTokens( editor()->parseSession(), node->expression->start_token, node->expression->end_token ).trimmed(); |
---|
1595 | |
---|
1596 | function->addDefaultParameter(IndexedString(defaultParam)); |
---|
1597 | } |
---|
1598 | if( !node->declarator ) { |
---|
1599 | //If there is no declarator, still create a declaration |
---|
1600 | openDefinition(0, node, true); |
---|
1601 | closeDeclaration(); |
---|
1602 | } |
---|
1603 | } |
---|
1604 | |
---|
1605 | if(m_mapAst) |
---|
1606 | m_mappedNodes.pop(); |
---|
1607 | } |
---|
1608 | |
---|
1609 | void DeclarationBuilder::popSpecifiers() |
---|
1610 | { |
---|
1611 | m_functionSpecifiers.pop(); |
---|
1612 | m_storageSpecifiers.pop(); |
---|
1613 | } |
---|
1614 | |
---|
1615 | void DeclarationBuilder::applyStorageSpecifiers() |
---|
1616 | { |
---|
1617 | if (!m_storageSpecifiers.isEmpty() && m_storageSpecifiers.top() != 0) |
---|
1618 | if (ClassMemberDeclaration* member = dynamic_cast<ClassMemberDeclaration*>(currentDeclaration())) { |
---|
1619 | DUChainWriteLocker lock(DUChain::lock()); |
---|
1620 | |
---|
1621 | member->setStorageSpecifiers(m_storageSpecifiers.top()); |
---|
1622 | } |
---|
1623 | } |
---|
1624 | |
---|
1625 | void DeclarationBuilder::applyFunctionSpecifiers() |
---|
1626 | { |
---|
1627 | DUChainWriteLocker lock(DUChain::lock()); |
---|
1628 | AbstractFunctionDeclaration* function = dynamic_cast<AbstractFunctionDeclaration*>(currentDeclaration()); |
---|
1629 | if(!function) |
---|
1630 | return; |
---|
1631 | |
---|
1632 | if (!m_functionSpecifiers.isEmpty() && m_functionSpecifiers.top() != 0) { |
---|
1633 | |
---|
1634 | function->setFunctionSpecifiers(m_functionSpecifiers.top()); |
---|
1635 | }else{ |
---|
1636 | function->setFunctionSpecifiers((AbstractFunctionDeclaration::FunctionSpecifiers)0); |
---|
1637 | } |
---|
1638 | |
---|
1639 | ///Eventually inherit the "virtual" flag from overridden functions |
---|
1640 | ClassFunctionDeclaration* classFunDecl = dynamic_cast<ClassFunctionDeclaration*>(function); |
---|
1641 | if(classFunDecl && !classFunDecl->isVirtual()) { |
---|
1642 | QList<Declaration*> overridden; |
---|
1643 | foreach(const DUContext::Import &import, currentContext()->importedParentContexts()) { |
---|
1644 | DUContext* iContext = import.context(topContext()); |
---|
1645 | if(iContext) { |
---|
1646 | overridden += iContext->findDeclarations(QualifiedIdentifier(classFunDecl->identifier()), |
---|
1647 | CursorInRevision::invalid(), classFunDecl->abstractType(), classFunDecl->topContext(), DUContext::DontSearchInParent); |
---|
1648 | } |
---|
1649 | } |
---|
1650 | if(!overridden.isEmpty()) { |
---|
1651 | foreach(Declaration* decl, overridden) { |
---|
1652 | if(AbstractFunctionDeclaration* fun = dynamic_cast<AbstractFunctionDeclaration*>(decl)) |
---|
1653 | if(fun->isVirtual()) |
---|
1654 | classFunDecl->setVirtual(true); |
---|
1655 | } |
---|
1656 | } |
---|
1657 | } |
---|
1658 | } |
---|
1659 | |
---|
1660 | bool DeclarationBuilder::checkParameterDeclarationClause(ParameterDeclarationClauseAST* clause) |
---|
1661 | { |
---|
1662 | { |
---|
1663 | DUChainReadLocker lock(DUChain::lock()); |
---|
1664 | if(currentContext()->type() == DUContext::Other) //Cannot declare a function in a code-context |
---|
1665 | return false; ///@todo create warning/error |
---|
1666 | } |
---|
1667 | if(!clause || !clause->parameter_declarations) |
---|
1668 | return true; |
---|
1669 | AbstractType::Ptr oldLastType = lastType(); |
---|
1670 | |
---|
1671 | const ListNode<ParameterDeclarationAST*> *start = clause->parameter_declarations->toFront(); |
---|
1672 | |
---|
1673 | const ListNode<ParameterDeclarationAST*> *it = start; |
---|
1674 | |
---|
1675 | bool ret = false; |
---|
1676 | |
---|
1677 | do { |
---|
1678 | ParameterDeclarationAST* ast = it->element; |
---|
1679 | if(ast) { |
---|
1680 | if(m_collectQtFunctionSignature) { |
---|
1681 | uint endToken = ast->end_token; |
---|
1682 | |
---|
1683 | if(ast->type_specifier) |
---|
1684 | endToken = ast->type_specifier->end_token; |
---|
1685 | if(ast->declarator) { |
---|
1686 | if(ast->declarator->id) |
---|
1687 | endToken = ast->declarator->id->start_token; |
---|
1688 | else |
---|
1689 | endToken = ast->declarator->end_token; |
---|
1690 | } |
---|
1691 | |
---|
1692 | if(!m_qtFunctionSignature.isEmpty()) |
---|
1693 | m_qtFunctionSignature += ", "; |
---|
1694 | |
---|
1695 | m_qtFunctionSignature += editor()->tokensToByteArray(ast->start_token, endToken); |
---|
1696 | ret = true; |
---|
1697 | }else{ |
---|
1698 | if(ast->expression || ast->declarator) { |
---|
1699 | ret = true; //If one parameter has a default argument or a parameter name, it is surely a parameter |
---|
1700 | break; |
---|
1701 | } |
---|
1702 | |
---|
1703 | visit(ast->type_specifier); |
---|
1704 | if( lastType() ) { |
---|
1705 | //Break on the first valid thing found |
---|
1706 | if( lastTypeWasInstance() ) { |
---|
1707 | ret = false; |
---|
1708 | break; |
---|
1709 | }else if(lastType().cast<DelayedType>() && lastType().cast<DelayedType>()->kind() == DelayedType::Unresolved) { |
---|
1710 | //When the searched item was not found, expect it to be a non-type |
---|
1711 | ret = false; |
---|
1712 | }else{ |
---|
1713 | ret = true; |
---|
1714 | break; |
---|
1715 | } |
---|
1716 | } |
---|
1717 | } |
---|
1718 | } |
---|
1719 | it = it->next; |
---|
1720 | } while (it != start); |
---|
1721 | |
---|
1722 | setLastType(oldLastType); |
---|
1723 | |
---|
1724 | return ret; |
---|
1725 | } |
---|
1726 | |
---|
1727 | /// Set the internal context of a declaration; for example, a class declaration's internal context |
---|
1728 | /// is the context inside the brackets: class ClassName { ... } |
---|
1729 | void DeclarationBuilder::eventuallyAssignInternalContext() |
---|
1730 | { |
---|
1731 | if (TypeBuilder::lastContext()) { |
---|
1732 | DUChainWriteLocker lock(DUChain::lock()); |
---|
1733 | |
---|
1734 | if( dynamic_cast<ClassFunctionDeclaration*>(currentDeclaration()) ) |
---|
1735 | Q_ASSERT( !static_cast<ClassFunctionDeclaration*>(currentDeclaration())->isConstructor() || currentDeclaration()->context()->type() == DUContext::Class ); |
---|
1736 | |
---|
1737 | if(TypeBuilder::lastContext() && |
---|
1738 | (TypeBuilder::lastContext()->type() == DUContext::Class || |
---|
1739 | TypeBuilder::lastContext()->type() == DUContext::Other || |
---|
1740 | TypeBuilder::lastContext()->type() == DUContext::Function || |
---|
1741 | TypeBuilder::lastContext()->type() == DUContext::Template || |
---|
1742 | TypeBuilder::lastContext()->type() == DUContext::Enum || |
---|
1743 | (TypeBuilder::lastContext()->type() == DUContext::Namespace && currentDeclaration()->kind() == Declaration::Namespace) |
---|
1744 | ) ) |
---|
1745 | { |
---|
1746 | if( !TypeBuilder::lastContext()->owner() || !TypeBuilder::wasEncountered(TypeBuilder::lastContext()->owner()) ) { //if the context is already internalContext of another declaration, leave it alone |
---|
1747 | currentDeclaration()->setInternalContext(TypeBuilder::lastContext()); |
---|
1748 | |
---|
1749 | TypeBuilder::clearLastContext(); |
---|
1750 | } |
---|
1751 | } |
---|
1752 | } |
---|
1753 | } |
---|