2 Copyright 2007 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 "abstractdeclarationnavigationcontext.h"
21 #include <QtGui/QTextDocument>
25 #include "../functiondeclaration.h"
26 #include "../functiondefinition.h"
27 #include "../classfunctiondeclaration.h"
28 #include "../namespacealiasdeclaration.h"
29 #include "../forwarddeclaration.h"
30 #include "../types/enumeratortype.h"
31 #include "../types/enumerationtype.h"
32 #include "../types/functiontype.h"
33 #include "../duchainutils.h"
34 #include "../types/pointertype.h"
35 #include "../types/referencetype.h"
36 #include "../types/typeutils.h"
39 AbstractDeclarationNavigationContext::AbstractDeclarationNavigationContext( DeclarationPointer decl
, KDevelop::TopDUContextPointer topContext
, AbstractNavigationContext
* previousContext
)
40 : AbstractNavigationContext(topContext
, previousContext
), m_declaration(decl
)
42 //Jump from definition to declaration if possible
43 FunctionDefinition
* definition
= dynamic_cast<FunctionDefinition
*>(m_declaration
.data());
44 if(definition
&& definition
->declaration())
45 m_declaration
= DeclarationPointer(definition
->declaration());
48 QString
AbstractDeclarationNavigationContext::name() const
50 return declarationName(m_declaration
);
53 QString
AbstractDeclarationNavigationContext::html(bool shorten
)
56 m_currentText
= "<html><body><p><small><small>";
58 addExternalHtml(m_prefix
);
60 if( shorten
&& !m_declaration
->comment().isEmpty() ) {
61 QString comment
= m_declaration
->comment();
62 if( comment
.length() > 60 ) {
66 comment
.replace('\n', ' ');
67 comment
.replace("<br />", " ");
68 comment
.replace("<br/>", " ");
69 m_currentText
+= commentHighlight(Qt::escape(comment
)) + " ";
71 if( m_previousContext
) {
72 m_currentText
+= navigationHighlight("Back to ");
73 makeLink( m_previousContext
->name(), m_previousContext
->name(), NavigationAction(m_previousContext
) );
74 m_currentText
+= "<br>";
77 const AbstractFunctionDeclaration
* function
= dynamic_cast<const AbstractFunctionDeclaration
*>(m_declaration
.data());
78 if( function
&& !shorten
) {
80 qDebug() << "yyy" << m_declaration
;
83 } else if( !shorten
) {
85 if( m_declaration
->isTypeAlias() || m_declaration
->kind() == Declaration::Instance
) {
86 if( m_declaration
->isTypeAlias() )
87 m_currentText
+= importantHighlight("typedef ");
89 if(m_declaration
->type
<EnumeratorType
>())
90 m_currentText
+= i18n("enumerator") + " ";
92 eventuallyMakeTypeLinks( m_declaration
->abstractType() );
94 m_currentText
+= " " + nameHighlight(Qt::escape(declarationName(m_declaration
))) + "<br>";
96 if( m_declaration
->kind() == Declaration::Type
&& m_declaration
->abstractType().cast
<StructureType
>() ) {
97 qDebug() << "xxx" << m_declaration
;
98 qDebug() << "xxx" << m_declaration
->abstractType().cast
<StructureType
>();
102 if(m_declaration
->type
<EnumerationType
>()) {
103 EnumerationType::Ptr enumeration
= m_declaration
->type
<EnumerationType
>();
104 m_currentText
+= i18n("enumeration") + " " + Qt::escape(m_declaration
->identifier().toString()) + "<br>";
107 if(m_declaration
->isForwardDeclaration()) {
108 ForwardDeclaration
* forwardDec
= static_cast<ForwardDeclaration
*>(m_declaration
.data());
109 Declaration
* resolved
= forwardDec
->resolve(m_topContext
.data());
111 m_currentText
+= "(" + i18n("resolved forward-declaration") + ": ";
112 makeLink(resolved
->identifier().toString(), KDevelop::DeclarationPointer(resolved
), NavigationAction::NavigateDeclaration
);
113 m_currentText
+= ") ";
115 m_currentText
+= i18n("(unresolved forward-declaration)") + " ";
120 QualifiedIdentifier identifier
= m_declaration
->qualifiedIdentifier();
121 if( identifier
.count() > 1 ) {
122 if( m_declaration
->context() && m_declaration
->context()->owner() )
124 Declaration
* decl
= m_declaration
->context()->owner();
126 FunctionDefinition
* definition
= dynamic_cast<FunctionDefinition
*>(decl
);
127 if(definition
&& definition
->declaration())
128 decl
= definition
->declaration();
130 if(decl
->abstractType().cast
<EnumerationType
>())
131 m_currentText
+= labelHighlight(i18n("Enum: "));
133 m_currentText
+= labelHighlight(i18n("Container: "));
135 makeLink( declarationName(DeclarationPointer(decl
)), DeclarationPointer(decl
), NavigationAction::NavigateDeclaration
);
136 m_currentText
+= " ";
138 QualifiedIdentifier parent
= identifier
;
140 m_currentText
+= labelHighlight(i18n("Scope: ")) + Qt::escape(parent
.toString()) + " ";
144 QString access
= stringFromAccess(m_declaration
);
145 if( !access
.isEmpty() )
146 m_currentText
+= labelHighlight(i18n("Access: ")) + propertyHighlight(Qt::escape(access
)) + " ";
149 ///@todo Enumerations
152 QStringList details
= declarationDetails(m_declaration
);
153 if( !details
.isEmpty() ) {
155 foreach( QString str
, details
) {
159 detailsHtml
+= propertyHighlight(str
);
163 QString kind
= declarationKind(m_declaration
);
164 if( !kind
.isEmpty() ) {
165 if( !detailsHtml
.isEmpty() )
166 m_currentText
+= labelHighlight(i18n("Kind: ")) + importantHighlight(Qt::escape(kind
)) + " " + detailsHtml
+ " ";
168 m_currentText
+= labelHighlight(i18n("Kind: ")) + importantHighlight(Qt::escape(kind
)) + " ";
169 } else if( !detailsHtml
.isEmpty() ) {
170 m_currentText
+= labelHighlight(i18n("Modifiers: ")) + importantHighlight(Qt::escape(kind
)) + " ";
173 m_currentText
+= "<br />";
175 if( !shorten
&& !m_declaration
->comment().isEmpty() ) {
176 QString comment
= m_declaration
->comment();
177 comment
.replace("<br />", "\n"); //do not escape html newlines within the comment
178 comment
.replace("<br/>", "\n");
179 comment
= Qt::escape(comment
);
180 comment
.replace("\n", "<br />"); //Replicate newlines in html
181 m_currentText
+= commentHighlight(comment
);
182 m_currentText
+= "<br />";
186 if(dynamic_cast<FunctionDefinition
*>(m_declaration
.data()))
187 m_currentText
+= labelHighlight(i18n( "Def.: " ));
189 m_currentText
+= labelHighlight(i18n( "Decl.: " ));
191 makeLink( QString("%1 :%2").arg( KUrl(m_declaration
->url().str()).fileName() ).arg( m_declaration
->range().textRange().start().line()+1 ), m_declaration
, NavigationAction::JumpToSource
);
192 m_currentText
+= " ";
193 //m_currentText += "<br />";
194 if(!dynamic_cast<FunctionDefinition
*>(m_declaration
.data())) {
195 if( FunctionDefinition
* definition
= FunctionDefinition::definition(m_declaration
.data()) ) {
196 m_currentText
+= labelHighlight(i18n( " Def.: " ));
197 makeLink( QString("%1 :%2").arg( KUrl(definition
->url().str()).fileName() ).arg( definition
->range().textRange().start().line()+1 ), DeclarationPointer(definition
), NavigationAction::JumpToSource
);
201 if( FunctionDefinition
* definition
= dynamic_cast<FunctionDefinition
*>(m_declaration
.data()) ) {
202 if(definition
->declaration()) {
203 m_currentText
+= labelHighlight(i18n( " Decl.: " ));
204 makeLink( QString("%1 :%2").arg( KUrl(definition
->declaration()->url().str()).fileName() ).arg( definition
->declaration()->range().textRange().start().line()+1 ), DeclarationPointer(definition
->declaration()), NavigationAction::JumpToSource
);
208 //m_currentText += "<br />";
211 addExternalHtml(m_suffix
);
213 m_currentText
+= "</small></small></p></body></html>";
215 return m_currentText
;
218 void AbstractDeclarationNavigationContext::htmlFunction()
220 const AbstractFunctionDeclaration
* function
= dynamic_cast<const AbstractFunctionDeclaration
*>(m_declaration
.data());
223 const ClassFunctionDeclaration
* classFunDecl
= dynamic_cast<const ClassFunctionDeclaration
*>(m_declaration
.data());
224 const FunctionType::Ptr type
= m_declaration
->abstractType().cast
<FunctionType
>();
226 m_currentText
+= errorHighlight("Invalid type<br>");
229 if( !classFunDecl
|| !classFunDecl
->isConstructor() || !classFunDecl
->isDestructor() ) {
230 eventuallyMakeTypeLinks( type
->returnType() );
231 m_currentText
+= ' ' + nameHighlight(Qt::escape(m_declaration
->identifier().toString()));
234 if( type
->arguments().count() == 0 )
236 m_currentText
+= "()";
238 m_currentText
+= "( ";
241 KDevelop::DUContext
* argumentContext
= DUChainUtils::getArgumentContext(m_declaration
.data());
243 if(argumentContext
) {
244 int firstDefaultParam
= argumentContext
->localDeclarations().count() - function
->defaultParametersSize();
245 int currentArgNum
= 0;
247 foreach(Declaration
* argument
, argumentContext
->localDeclarations()) {
249 m_currentText
+= ", ";
252 AbstractType::Ptr argType
= argument
->abstractType();
254 eventuallyMakeTypeLinks( argType
);
255 m_currentText
+= " " + nameHighlight(Qt::escape(argument
->identifier().toString()));
257 if( currentArgNum
>= firstDefaultParam
)
258 m_currentText
+= " = " + Qt::escape(function
->defaultParameters()[ currentArgNum
- firstDefaultParam
].str());
264 m_currentText
+= " )";
266 m_currentText
+= "<br>";
269 void AbstractDeclarationNavigationContext::htmlClass()
271 StructureType::Ptr klass
= m_declaration
->abstractType().cast
<StructureType
>();
274 m_currentText
+= "class ";
275 eventuallyMakeTypeLinks( klass
.cast
<AbstractType
>() );
278 void AbstractDeclarationNavigationContext::htmlIdentifiedType(AbstractType::Ptr type
, const IdentifiedType
* idType
)
283 if( idType
->declaration(m_topContext
.data()) ) {
285 //Remove the last template-identifiers, because we create those directly
286 QualifiedIdentifier id
= idType
->qualifiedIdentifier();
287 Identifier lastId
= id
.last();
289 lastId
.clearTemplateIdentifiers();
292 //We leave out the * and & reference and pointer signs, those are added to the end
293 makeLink(id
.toString() , DeclarationPointer(idType
->declaration(m_topContext
.data())), NavigationAction::NavigateDeclaration
);
295 m_currentText
+= Qt::escape(type
->toString());
299 void AbstractDeclarationNavigationContext::eventuallyMakeTypeLinks( AbstractType::Ptr type
)
302 m_currentText
+= Qt::escape("<no type>");
305 AbstractType::Ptr target
= TypeUtils::targetType( type
, m_topContext
.data() );
306 const IdentifiedType
* idType
= dynamic_cast<const IdentifiedType
*>( target
.unsafeData() );
308 ///@todo handle const etc. correctly
309 PointerType::Ptr pointer
= type
.cast
<PointerType
>();
310 ReferenceType::Ptr ref
= type
.cast
<ReferenceType
>();
312 if(pointer
&& pointer
->modifiers() & AbstractType::ConstModifier
)
313 m_currentText
+= "const ";
314 if(ref
&& ref
->modifiers() & AbstractType::ConstModifier
)
315 m_currentText
+= "const ";
319 htmlIdentifiedType(type
, idType
);
321 //Add reference and pointer
322 ///@todo correct const handling
323 while(pointer
|| ref
) {
325 m_currentText
+= Qt::escape("*");
326 ref
= pointer
->baseType().cast
<ReferenceType
>();
327 pointer
= pointer
->baseType().cast
<PointerType
>();
330 m_currentText
+= Qt::escape("&");
331 pointer
= ref
->baseType().cast
<PointerType
>();
332 ref
= ref
->baseType().cast
<ReferenceType
>();
337 m_currentText
+= Qt::escape(type
->toString());
341 DeclarationPointer
AbstractDeclarationNavigationContext::declaration() const
343 return m_declaration
;
346 QString
AbstractDeclarationNavigationContext::stringFromAccess(Declaration::AccessPolicy access
)
349 case Declaration::Private
:
351 case Declaration::Protected
:
353 case Declaration::Public
:
359 QString
AbstractDeclarationNavigationContext::stringFromAccess(DeclarationPointer decl
)
361 const ClassMemberDeclaration
* memberDecl
= dynamic_cast<const ClassMemberDeclaration
*>(decl
.data());
363 return stringFromAccess(memberDecl
->accessPolicy());
368 QString
AbstractDeclarationNavigationContext::declarationName( DeclarationPointer decl
)
370 if( NamespaceAliasDeclaration
* alias
= dynamic_cast<NamespaceAliasDeclaration
*>(decl
.data()) ) {
371 if( alias
->identifier().isEmpty() )
372 return "using namespace " + alias
->importIdentifier().toString();
374 return "namespace " + alias
->identifier().toString() + " = " + alias
->importIdentifier().toString();
378 return i18nc("An unknown declaration that is unknown", "Unknown");
380 return decl
->identifier().toString();
383 QStringList
AbstractDeclarationNavigationContext::declarationDetails(DeclarationPointer decl
)
386 const AbstractFunctionDeclaration
* function
= dynamic_cast<const AbstractFunctionDeclaration
*>(decl
.data());
387 const ClassMemberDeclaration
* memberDecl
= dynamic_cast<const ClassMemberDeclaration
*>(decl
.data());
389 if( memberDecl
->isMutable() )
390 details
<< "mutable";
391 if( memberDecl
->isRegister() )
392 details
<< "register";
393 if( memberDecl
->isStatic() )
395 if( memberDecl
->isAuto() )
397 if( memberDecl
->isExtern() )
399 if( memberDecl
->isFriend() )
403 if( decl
->isDefinition() )
404 details
<< "definition";
406 if( memberDecl
&& memberDecl
->isForwardDeclaration() )
407 details
<< "forward";
409 AbstractType::Ptr
t(decl
->abstractType());
411 if( t
->modifiers() & AbstractType::ConstModifier
)
412 details
<< "constant";
413 if( t
->modifiers() & AbstractType::VolatileModifier
)
414 details
<< "volatile";
418 if( function
->isInline() )
421 if( function
->isExplicit() )
422 details
<< "explicit";
424 if( function
->isVirtual() )
425 details
<< "virtual";
427 const ClassFunctionDeclaration
* classFunDecl
= dynamic_cast<const ClassFunctionDeclaration
*>(decl
.data());
430 if( classFunDecl
->functionType() == ClassFunctionDeclaration::Signal
)
432 if( classFunDecl
->functionType() == ClassFunctionDeclaration::Slot
)
434 if( classFunDecl
->isConstructor() )
435 details
<< "constructor";
436 if( classFunDecl
->isDestructor() )
437 details
<< "destructor";
438 if( classFunDecl
->isConversionFunction() )
439 details
<< "conversion-function";