1 /*
2     SPDX-FileCopyrightText: 2008 David Nolden <david.nolden.kdevelop@art-master.de>
3 
4     SPDX-License-Identifier: LGPL-2.0-only
5 */
6 
7 #include "functiondefinition.h"
8 #include "duchainregister.h"
9 #include "definitions.h"
10 
11 namespace KDevelop {
12 REGISTER_DUCHAIN_ITEM(FunctionDefinition);
13 
FunctionDefinition(FunctionDefinitionData & data)14 FunctionDefinition::FunctionDefinition(FunctionDefinitionData& data) : FunctionDeclaration(data)
15 {
16 }
17 
FunctionDefinition(const RangeInRevision & range,DUContext * context)18 FunctionDefinition::FunctionDefinition(const RangeInRevision& range, DUContext* context)
19     : FunctionDeclaration(*new FunctionDefinitionData, range)
20 {
21     d_func_dynamic()->setClassId(this);
22     setDeclarationIsDefinition(true);
23     if (context)
24         setContext(context);
25 }
26 
FunctionDefinition(const FunctionDefinition & rhs)27 FunctionDefinition::FunctionDefinition(const FunctionDefinition& rhs) : FunctionDeclaration(*new FunctionDefinitionData(
28             *rhs.d_func()))
29 {
30 }
31 
~FunctionDefinition()32 FunctionDefinition::~FunctionDefinition()
33 {
34     if (!topContext()->isOnDisk())
35         DUChain::definitions()->removeDefinition(d_func()->m_declaration, this);
36 }
37 
declaration(const TopDUContext * topContext) const38 Declaration* FunctionDefinition::declaration(const TopDUContext* topContext) const
39 {
40     ENSURE_CAN_READ
41 
42     const KDevVarLengthArray<Declaration*> declarations = d_func()->m_declaration.declarations(
43         topContext ? topContext : this->topContext());
44 
45     for (Declaration* decl : declarations) {
46         if (!dynamic_cast<FunctionDefinition*>(decl))
47             return decl;
48     }
49 
50     return nullptr;
51 }
52 
hasDeclaration() const53 bool FunctionDefinition::hasDeclaration() const
54 {
55     return d_func()->m_declaration.isValid();
56 }
57 
setDeclaration(Declaration * declaration)58 void FunctionDefinition::setDeclaration(Declaration* declaration)
59 {
60     ENSURE_CAN_WRITE
61 
62     if (declaration) {
63         DUChain::definitions()->addDefinition(declaration->id(), this);
64         d_func_dynamic()->m_declaration = declaration->id();
65     } else {
66         if (d_func()->m_declaration.isValid()) {
67             DUChain::definitions()->removeDefinition(d_func()->m_declaration, this);
68             d_func_dynamic()->m_declaration = DeclarationId();
69         }
70     }
71 }
72 
definition(const Declaration * decl)73 Declaration* FunctionDefinition::definition(const Declaration* decl)
74 {
75     ENSURE_CHAIN_READ_LOCKED
76     if (!decl) {
77         return nullptr;
78     }
79 
80     if (decl->isFunctionDeclaration() && decl->isDefinition()) {
81         return const_cast<Declaration*>(decl);
82     }
83 
84     const KDevVarLengthArray<IndexedDeclaration> allDefinitions = DUChain::definitions()->definitions(decl->id());
85     for (const IndexedDeclaration decl : allDefinitions) {
86         if (decl.data()) ///@todo Find better ways of deciding which definition to use
87             return decl.data();
88     }
89 
90     return nullptr;
91 }
92 
clonePrivate() const93 Declaration* FunctionDefinition::clonePrivate() const
94 {
95     return new FunctionDefinition(*new FunctionDefinitionData(*d_func()));
96 }
97 }
98