/***************************************************************************
cppcodecompletion . cpp - description
- - - - - - - - - - - - - - - - - - -
begin : Sat Jul 21 2001
copyright : ( C ) 2001 by Victor R <EFBFBD> er
email : victor_roeder @ gmx . de
copyright : ( C ) 2002 , 2003 by Roberto Raggi
email : roberto @ kdevelop . org
copyright : ( C ) 2005 by Adam Treat
email : manyoso @ yahoo . com
copyright : ( C ) 2006 , 2007 by David Nolden
email : david . nolden . kdevelop @ art - master . de
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/***************************************************************************
* *
* This program is free software ; you can redistribute it and / or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation ; either version 2 of the License , or *
* ( at your option ) any later version . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "cppcodecompletion.h"
# include "cppcodecompletionconfig.h"
# include "backgroundparser.h"
# include "ast.h"
# include "ast_utils.h"
# include "codeinformationrepository.h"
# include "parser.h"
# include "lexer.h"
# include "tree_parser.h"
# include "cpp_tags.h"
# include "cppsupport_utils.h"
# include "tag_creator.h"
# include <typeinfo>
# include <vector>
# include <tqpopupmenu.h>
# include <tdeapplication.h>
# include <kdebug.h>
# include <tdelocale.h>
# include <tdemainwindow.h>
# include <tdemessagebox.h>
# include <tdeparts/part.h>
# include <kstatusbar.h>
# include <tdetexteditor/document.h>
# include <tdeaction.h>
# include <tqdatastream.h>
# include <tqfile.h>
# include <tqmap.h>
# include <tqregexp.h>
# include <tqstatusbar.h>
# include <tqstring.h>
# include <tqstringlist.h>
# include <tqpair.h>
# include <tqvaluestack.h>
# include <kdevpartcontroller.h>
# include <kdevmainwindow.h>
# include <kdevproject.h>
# include <kdevcoderepository.h>
# include <codemodel_utils.h>
# include <codemodel.h>
# include <codebrowserfrontend.h>
# include "codecompletionentry.h"
# include "typedesc.h"
# include "computerecoverypoints.h"
# include "completiondebug.h"
# include "bithelpers.h"
# include "stringhelpers.h"
# include "simpletype.h"
# include "simpletypecachebinder.h"
# include "safetycounter.h"
# include "cppevaluation.h"
# include "simplecontext.h"
# include "simpletypefunction.h"
//#define DISABLE_TRACING
CppCodeCompletion * CppCodeCompletion : : m_instance = 0 ;
const bool disableVerboseForCompletionList = false ;
const bool disableVerboseForContextMenu = false ;
const bool contextMenuEntriesAtTop = false ;
bool showNamespaceAppearances = true ;
const char * constructorPrefix = " <constructor> " ;
const char * destructorPrefix = " <destructor> " ;
///This enables-disables the automatic processing of the expression under the mouse-cursor
//#define DISABLETOOLTIPS
/**
- - TODO : Does not yet correctly search for overloaded functions and select the right one
- - TODO : The documentation shown in the calltips looks very bad , a better solution must be found ( maybe an additional tooltip )
*/
void statusBarText ( const TQString & str , int time ) {
CppCodeCompletion * c = CppCodeCompletion : : instance ( ) ;
if ( c )
c - > addStatusText ( str , time ) ;
}
TypePointer CppCodeCompletion : : createGlobalNamespace ( ) {
TDESharedPtr < SimpleTypeCachedNamespace > n = new SimpleTypeCachedNamespace ( TQStringList ( ) , TQStringList ( ) ) ;
n - > addAliases ( m_pSupport - > codeCompletionConfig ( ) - > namespaceAliases ( ) ) ;
return n . data ( ) ;
}
template < class Item >
class ItemLocker {
public :
ItemLocker ( Item & it ) : item ( it ) {
it . lock ( ) ;
}
~ ItemLocker ( ) {
item . unlock ( ) ;
}
private :
Item & item ;
} ;
ParsedFilePointer getParsedFile ( CodeModelItem * i ) {
if ( ! i | | ! i - > file ( ) | | ! i - > file ( ) - > parseResult ( ) ) return 0 ;
return dynamic_cast < ParsedFile * > ( i - > file ( ) - > parseResult ( ) . data ( ) ) ;
}
SafetyCounter safetyCounter ;
CppCodeCompletion * cppCompletionInstance = 0 ;
//file global functions, must be before any "using namespace"
TQString cleanForMenu ( TQString txt ) {
return txt . replace ( " & " , " && " ) . replace ( " " , " " ) ;
}
TQString buildSignature ( TypePointer currType ) {
SimpleTypeFunctionInterface * f = currType - > asFunction ( ) ;
if ( ! f )
return " " ;
TQString ret ;
LocateResult rtt = currType - > locateDecType ( f - > getReturnType ( ) ) ;
if ( rtt - > resolved ( ) | | rtt . resolutionCount ( ) > 1 )
ret = rtt - > fullNameChain ( ) ;
else
ret = f - > getReturnType ( ) . fullNameChain ( ) ;
TypeDesc desc = currType - > desc ( ) ;
desc . decreaseFunctionDepth ( ) ;
TQString sig = ret + " " + desc . fullNameChain ( ) + f - > signature ( ) ;
if ( f - > isConst ( ) )
sig + = " const " ;
return sig ;
}
uint PopupTracker : : pendingPopups = 0 ;
PopupTracker * PopupTracker : : pt = 0 ;
/** Multiple empty lines are reduced to one, too long lines wrapped over, and the beginnings of the lines are normalized
*/
TQStringList maximumLength ( const TQStringList & in , int length ) {
TQStringList ret ;
uint firstNonSpace = 50000 ;
for ( TQStringList : : const_iterator it = in . begin ( ) ; it ! = in . end ( ) ; + + it )
for ( uint a = 0 ; a < ( * it ) . length ( ) ; a + + )
if ( ! ( * it ) [ a ] . isSpace ( ) ) {
if ( firstNonSpace > a )
firstNonSpace = a ;
break ;
}
if ( firstNonSpace = = 50000 )
return TQStringList ( ) ;
bool hadEmptyLine = false ;
for ( TQStringList : : const_iterator it = in . begin ( ) ; it ! = in . end ( ) ; + + it ) {
if ( ( * it ) . length ( ) < = firstNonSpace ) {
if ( ! hadEmptyLine )
ret < < " " ;
hadEmptyLine = true ;
} else {
hadEmptyLine = false ;
TQString str = ( * it ) . mid ( firstNonSpace ) ;
while ( ! str . isEmpty ( ) ) {
if ( ( int ) str . length ( ) < length ) {
ret < < str ;
break ;
} else {
ret < < str . left ( length ) + " \\ " ;
str = str . mid ( length ) ;
}
}
}
}
return ret ;
}
TQStringList prepareTextForMenu ( const TQString & comment , int maxLines , int maxLength ) {
TQStringList in = TQStringList : : split ( " \n " , comment ) ;
TQStringList out ;
for ( TQStringList : : iterator it = in . begin ( ) ; it ! = in . end ( ) ; + + it ) {
out < < cleanForMenu ( * it ) ;
if ( ( int ) out . count ( ) > = maxLines ) {
out < < " [...] " ;
break ;
}
}
return maximumLength ( out , maxLength ) ;
}
TQStringList formatComment ( const TQString & comment , int maxCols = 120 ) {
TQStringList ret ;
SafetyCounter s ( 14 ) ; ///maximum of 14 lines
TQStringList lines = TQStringList : : split ( " \n " , comment ) ;
for ( TQStringList : : iterator it = lines . begin ( ) ; it ! = lines . end ( ) ; + + it ) {
TQStringList words = TQStringList : : split ( " " , * it ) ;
while ( ! words . isEmpty ( ) & & s ) {
TQString line = " ? " ;
int len = 0 ;
while ( ! words . isEmpty ( ) & & len < maxCols ) {
len + = words . front ( ) . length ( ) ;
line + = words . front ( ) + " " ;
words . pop_front ( ) ;
}
ret < < line ;
}
}
if ( ! s )
ret < < " ? comment has too many lines " ;
return ret ;
}
bool operator < ( const CodeCompletionEntry & e1 , const CodeCompletionEntry & e2 ) {
return e1 . text < e2 . text ;
}
template < class ItemType >
static TQValueList < ItemType > unique ( const TQValueList < ItemType > & entryList ) {
TQValueList < ItemType > l ;
TQMap < TQString , bool > map ;
typename TQValueList < ItemType > : : ConstIterator it = entryList . begin ( ) ;
while ( it ! = entryList . end ( ) ) {
CodeCompletionEntry e = * it + + ;
TQString key = ( e . type + " " +
e . prefix + " " +
e . text + " " +
e . postfix + " " ) . simplifyWhiteSpace ( ) . stripWhiteSpace ( ) ;
if ( map . find ( key ) = = map . end ( ) ) {
map [ key ] = TRUE ;
l < < e ;
}
}
return l ;
}
static TQStringList unique ( const TQStringList & entryList ) {
TQStringList l ;
TQMap < TQString , bool > map ;
TQStringList : : ConstIterator it = entryList . begin ( ) ;
while ( it ! = entryList . end ( ) ) {
TQString e = * it + + ;
if ( map . find ( e ) = = map . end ( ) ) {
map [ e ] = TRUE ;
l < < e ;
}
}
return l ;
}
static TQStringList unique ( const TQValueList < TQStringList > & entryList ) {
TQStringList l ;
TQMap < TQString , bool > map ;
TQValueList < TQStringList > : : ConstIterator it = entryList . begin ( ) ;
while ( it ! = entryList . end ( ) ) {
TQStringList li = ( * it + + ) ;
TQString e = li . join ( " \n " ) ;
if ( map . find ( e ) = = map . end ( ) ) {
map [ e ] = TRUE ;
l + = li ;
}
}
return l ;
}
bool tokenAt ( const TQString & text , const TQString & token , int textPos ) {
if ( text . isEmpty ( ) )
return false ;
int tokenPos = token . length ( ) - 1 ;
if ( tokenPos < = 0 | | textPos < = 0 )
return false ;
while ( text [ textPos ] = = token [ tokenPos ] ) {
- - tokenPos ;
- - textPos ;
if ( tokenPos = = 0 | | textPos = = 0 ) {
if ( tokenPos = = 0 ) {
if ( textPos > = 1 & & text [ textPos ] = = token [ tokenPos ] ) {
TQChar c = text [ textPos - 1 ] ;
return c . isSpace ( ) | | c = = ' { ' | | c = = ' } ' | | c = = ' ; ' ;
} else {
return false ;
}
} else {
return false ;
}
}
}
return false ;
}
CppSupportPart * CppCodeCompletion : : cppSupport ( ) const {
return m_pSupport ;
}
using namespace CompletionDebug ;
using namespace StringHelpers ;
using namespace BitHelpers ;
using namespace CppEvaluation ;
struct PopupFillerHelpStruct {
CppCodeCompletion * receiver ;
FileList files ;
CppCodeCompletion : : PopupActions & m_popupActions ;
PopupFillerHelpStruct ( CppCodeCompletion * rec ) : m_popupActions ( rec - > m_popupActions ) {
receiver = rec ;
files = receiver - > cppSupport ( ) - > codeModel ( ) - > fileList ( ) ;
}
bool shouldShowIncludeMenu ( ) const {
return true ;
}
TQMap < TQString , TQPopupMenu * > m_namespacePopupCache ;
void insertItem ( TQPopupMenu * parent , SimpleTypeImpl : : MemberInfo d , TQString prefix ) {
Q_UNUSED ( prefix ) ;
TQString memType = d . memberTypeToString ( ) ;
if ( d . memberType = = SimpleTypeImpl : : MemberInfo : : Typedef & & d . type - > fullName ( ) = = " const int " )
memType = " enum " ;
TQString txt = i18n ( " Jump to %1 %2 " ) . arg ( memType ) . arg ( cleanForMenu ( d . name ) ) ;
int id = parent - > insertItem ( txt , receiver , TQT_SLOT ( popupAction ( int ) ) ) ;
receiver - > m_popupActions . insert ( id , d . decl ) ;
}
void insertItem ( TQPopupMenu * parent , TypeDesc d , TQString prefix ) {
Debug dbg ( " #insert# " , 10 ) ;
TQString txt1 , txt2 ;
if ( d . resolved ( ) & & d . resolved ( ) - > isNamespace ( ) ) {
SimpleTypeCachedNamespace * ns = dynamic_cast < SimpleTypeCachedNamespace * > ( d . resolved ( ) . data ( ) ) ;
if ( ns ) {
SimpleTypeNamespace : : SlaveList slaves = ns - > getSlaves ( receiver - > getIncludeFiles ( ) ) ;
for ( SimpleTypeNamespace : : SlaveList : : iterator it = slaves . begin ( ) ; it ! = slaves . end ( ) ; + + it ) {
SimpleTypeCodeModel * cm = dynamic_cast < SimpleTypeCodeModel * > ( ( * it ) . first . first . resolved ( ) . data ( ) ) ;
if ( cm & & cm - > item ( ) ) {
TQPopupMenu * m = PopupTracker : : createPopup ( parent ) ;
TQString scope = cm - > scope ( ) . join ( " :: " ) ;
TQMap < TQString , TQPopupMenu * > : : iterator it = m_namespacePopupCache . find ( scope ) ;
if ( it ! = m_namespacePopupCache . end ( ) ) {
parent - > insertItem ( " Imported Namespace " + scope , * it ) ;
delete m ;
} else {
parent - > insertItem ( " Imported Namespace " + scope , m ) ;
insertItem ( m , ( new SimpleTypeCachedCodeModel ( cm - > item ( ) ) ) - > desc ( ) , prefix ) ;
m_namespacePopupCache . insert ( scope , m ) ;
}
} else {
SimpleTypeNamespace * cn = dynamic_cast < SimpleTypeNamespace * > ( ( * it ) . first . first . resolved ( ) . data ( ) ) ;
if ( cn ) {
TypePointer t = new SimpleTypeNamespace ( cn ) ; //To avoid endless recursion, this needs to be done(the dynamic-cast above fails)
insertItem ( parent , t - > desc ( ) , prefix ) ;
}
}
}
return ;
}
}
if ( d . resolved ( ) & & receiver - > cppSupport ( ) - > codeCompletionConfig ( ) - > showNamespaceAppearances ( ) ) {
if ( SimpleTypeCachedCodeModel * item = dynamic_cast < SimpleTypeCachedCodeModel * > ( d . resolved ( ) . data ( ) ) ) { ///(1)
if ( item - > item ( ) & & item - > item ( ) - > isNamespace ( ) ) {
NamespaceModel * ns = dynamic_cast < NamespaceModel * > ( item - > item ( ) . data ( ) ) ;
TQStringList wholeScope = ns - > scope ( ) ;
wholeScope < < ns - > name ( ) ;
for ( FileList : : iterator it = files . begin ( ) ; it ! = files . end ( ) ; + + it ) {
// if( !safetyCounter ) break;
NamespaceModel * ns = ( * it ) . data ( ) ;
for ( TQStringList : : iterator it2 = wholeScope . begin ( ) ; it2 ! = wholeScope . end ( ) ; + + it2 ) {
if ( ns - > hasNamespace ( ( * it2 ) ) ) {
ns = ns - > namespaceByName ( * it2 ) ;
if ( ! ns ) break ;
} else {
ns = 0 ;
break ;
}
}
if ( ns ) {
ItemDom i ( ns ) ;
int sLine , sCol , eLine , eCol ;
i - > getStartPosition ( & sLine , & sCol ) ;
i - > getEndPosition ( & eLine , & eCol ) ;
insertItem ( parent , ( new SimpleTypeCodeModel ( i ) ) - > desc ( ) , prefix + " " + ( * it ) - > name ( ) + TQString ( " (%1 Lines): " ) . arg ( eLine - sLine ) ) ; ///SimpleTypeCodeModel is used instead of SimpleTypeCachedNodeModel, so the detection at (1) does not trigger, this avoids endless recursion.
}
}
return ;
}
}
}
if ( d . resolved ( ) ) {
if ( d . resolved ( ) - > asFunction ( ) ) {
txt1 = prefix + i18n ( " Jump to declaration of %1(...) " ) . arg ( d . resolved ( ) - > scope ( ) . join ( " :: " ) ) ;
txt2 = prefix + i18n ( " Jump to definition of %1(...) " ) . arg ( d . resolved ( ) - > scope ( ) . join ( " :: " ) ) ;
} else {
txt1 = prefix + i18n ( " Jump to %1 " ) . arg ( cleanForMenu ( d . resolved ( ) - > scope ( ) . join ( " :: " ) ) ) ;
}
} else {
if ( ! BuiltinTypes : : isBuiltin ( d ) ) {
txt1 = prefix + d . name ( ) + i18n ( " is unresolved " ) ;
} else {
txt1 = prefix + d . name ( ) + i18n ( " (builtin " ) + BuiltinTypes : : comment ( d ) + " ) " ;
}
}
int id = parent - > insertItem ( txt1 , receiver , TQT_SLOT ( popupAction ( int ) ) ) ;
if ( d . resolved ( ) )
receiver - > m_popupActions . insert ( id , d . resolved ( ) - > getDeclarationInfo ( ) ) ;
if ( ! txt2 . isEmpty ( ) ) {
int id2 = parent - > insertItem ( txt2 , receiver , TQT_SLOT ( popupDefinitionAction ( int ) ) ) ;
if ( d . resolved ( ) )
receiver - > m_popupDefinitionActions . insert ( id2 , d . resolved ( ) - > getDeclarationInfo ( ) ) ;
}
}
} ;
ItemDom itemFromScope ( const TQStringList & scope , NamespaceDom startNamespace ) {
if ( scope . isEmpty ( ) )
return ItemDom ( ) ;
NamespaceDom glob = startNamespace ;
if ( ! glob )
return ItemDom ( ) ;
ClassModel * curr = glob ;
TQStringList : : const_iterator mit = scope . begin ( ) ;
while ( curr - > isNamespace ( ) & & mit ! = scope . end ( ) & & ( ( NamespaceModel * ) curr ) - > hasNamespace ( * mit ) ) {
curr = & ( * ( ( ( NamespaceModel * ) curr ) - > namespaceByName ( * mit ) ) ) ;
+ + mit ;
}
while ( ( curr - > isNamespace ( ) | | curr - > isClass ( ) ) & & mit ! = scope . end ( ) & & curr - > hasClass ( * mit ) ) {
ClassList cl = curr - > classByName ( * mit ) ;
curr = & ( * * cl . begin ( ) ) ;
+ + mit ;
}
if ( mit ! = - - scope . end ( ) )
return ItemDom ( ) ;
TypeAliasList l = curr - > typeAliasByName ( * mit ) ;
if ( ! l . isEmpty ( ) )
return model_cast < ItemDom > ( l . front ( ) ) ;
VariableDom v = curr - > variableByName ( * mit ) ;
if ( v )
return model_cast < ItemDom > ( v ) ;
ClassList c = curr - > classByName ( * mit ) ;
if ( ! c . isEmpty ( ) )
return model_cast < ItemDom > ( c . front ( ) ) ;
EnumDom en = curr - > enumByName ( * mit ) ;
if ( en )
return model_cast < ItemDom > ( en ) ;
FunctionList f = curr - > functionByName ( * mit ) ;
if ( ! f . isEmpty ( ) )
return model_cast < ItemDom > ( f . front ( ) ) ;
FunctionDefinitionList fd = curr - > functionDefinitionByName ( * mit ) ;
if ( ! fd . isEmpty ( ) )
return model_cast < ItemDom > ( fd . front ( ) ) ;
return ItemDom ( ) ;
}
struct PopupClassViewFillerHelpStruct {
CppCodeCompletion * receiver ;
CppCodeCompletion : : PopupActions & m_popupActions ;
PopupClassViewFillerHelpStruct ( CppCodeCompletion * rec ) : m_popupActions ( rec - > m_popupActions ) {
receiver = rec ;
}
bool shouldShowIncludeMenu ( ) const {
return false ;
}
void insertItem ( TQPopupMenu * parent , SimpleTypeImpl : : MemberInfo d , TQString prefix ) {
Q_UNUSED ( prefix ) ;
FileDom f = receiver - > m_pSupport - > codeModel ( ) - > fileByName ( d . decl . file ) ;
if ( ! f )
return ;
ItemDom dom = itemFromScope ( TQStringList : : split ( " :: " , d . name ) , model_cast < NamespaceDom > ( f ) ) ;
TQString memType = d . memberTypeToString ( ) ;
if ( d . memberType = = SimpleTypeImpl : : MemberInfo : : Typedef & & d . type - > fullName ( ) = = " const int " )
memType = " enum " ;
TQString txt = i18n ( " Show %1 %2 " ) . arg ( memType ) . arg ( cleanForMenu ( d . name ) ) ;
int id = parent - > insertItem ( txt , receiver , TQT_SLOT ( popupClassViewAction ( int ) ) ) ;
receiver - > m_popupClassViewActions . insert ( id , dom ) ;
}
void insertItem ( TQPopupMenu * parent , TypeDesc d , TQString prefix ) {
Debug dbg ( " #insert# " , 10 ) ;
TQString txt ;
if ( ! d . resolved ( ) )
return ;
ItemDom dom ;
if ( d . resolved ( ) ) {
SimpleTypeCodeModel * cm = dynamic_cast < SimpleTypeCodeModel * > ( d . resolved ( ) . data ( ) ) ;
if ( cm )
dom = cm - > item ( ) ;
}
if ( d . resolved ( ) ) {
if ( ! dom & & d . resolved ( ) - > isNamespace ( ) ) {
SimpleTypeCachedNamespace * ns = dynamic_cast < SimpleTypeCachedNamespace * > ( d . resolved ( ) . data ( ) ) ;
if ( ns ) {
SimpleTypeNamespace : : SlaveList slaves = ns - > getSlaves ( receiver - > getIncludeFiles ( ) ) ;
for ( SimpleTypeNamespace : : SlaveList : : iterator it = slaves . begin ( ) ; it ! = slaves . end ( ) ; + + it ) {
SimpleTypeCodeModel * cm = dynamic_cast < SimpleTypeCodeModel * > ( ( * it ) . first . first . resolved ( ) . data ( ) ) ;
if ( cm & & cm - > item ( ) ) {
insertItem ( parent , ( new SimpleTypeCachedCodeModel ( cm - > item ( ) ) ) - > desc ( ) , prefix ) ;
} else {
SimpleTypeNamespace * cn = dynamic_cast < SimpleTypeNamespace * > ( ( * it ) . first . first . resolved ( ) . data ( ) ) ;
if ( cn ) {
TypePointer t = new SimpleTypeNamespace ( cn ) ; //to avoid endless recursion (caching would be better)
insertItem ( parent , t - > desc ( ) , prefix ) ;
}
}
}
return ;
}
} else {
if ( dom ) {
TQString n = d . resolved ( ) - > scope ( ) . join ( " :: " ) ;
//TQString n = d.fullNameChain();
if ( d . resolved ( ) - > asFunction ( ) ) {
n = buildSignature ( d . resolved ( ) ) ;
}
txt = prefix + i18n ( " Show %1 " ) . arg ( cleanForMenu ( n ) ) ;
} else {
txt = prefix + d . name ( ) + " not in code-model " ;
}
}
} else {
if ( ! BuiltinTypes : : isBuiltin ( d ) ) {
txt = prefix + d . name ( ) + i18n ( " is unresolved " ) ;
} else {
txt = prefix + d . name ( ) + i18n ( " (builtin " ) + BuiltinTypes : : comment ( d ) + " ) " ;
}
}
int id = parent - > insertItem ( txt , receiver , TQT_SLOT ( popupClassViewAction ( int ) ) ) ;
if ( dom )
receiver - > m_popupClassViewActions . insert ( id , dom ) ;
}
} ;
template < class HelpStruct = PopupFillerHelpStruct >
class PopupFiller {
HelpStruct struk ;
TQString depthAdd ;
SafetyCounter s ;
public :
PopupFiller ( HelpStruct str , TQString dAdd , int maxCount = 100 ) : struk ( str ) , depthAdd ( dAdd ) , s ( maxCount ) { }
void fillIncludes ( const DeclarationInfo & decl , TQPopupMenu * parent , bool & needSeparator ) {
if ( ! struk . receiver - > getIncludeFiles ( ) [ HashedString ( decl . file ) ] ) {
TQString file = decl . file ;
//The include-file seems to be missing
if ( needSeparator ) {
needSeparator = false ;
parent - > insertSeparator ( ) ;
}
TQString includeFile = file ;
TQFileInfo info ( file ) ;
Driver * driver = struk . receiver - > cppSupport ( ) - > driver ( ) ;
if ( driver ) {
TQStringList elements = TQStringList : : split ( " / " , file ) ;
includeFile = elements . back ( ) ;
elements . pop_back ( ) ;
Dependence d ;
d . first = includeFile ;
d . second = Dep_Local ;
while ( driver - > findIncludeFile ( d , struk . receiver - > activeFileName ( ) ) ! = file & & ! elements . empty ( ) ) {
//kdDebug( 9007 ) << "could not find include-file \"" << d.first << "\"" << endl;
includeFile = elements . back ( ) + " / " + includeFile ;
d . first = includeFile ;
elements . pop_back ( ) ;
}
if ( elements . empty ( ) )
includeFile = " / " + includeFile ;
//kdDebug( 9007 ) << "found include-file \"" << includeFile << "\"" << endl;
}
int id = parent - > insertItem ( i18n ( " #include \" %1 \" ( defines %2 ) " ) . arg ( includeFile ) . arg ( decl . name ) , struk . receiver , TQT_SLOT ( popupAction ( int ) ) ) ;
DeclarationInfo fakeDec ;
fakeDec . name = decl . name ;
fakeDec . file = includeFile ;
fakeDec . startLine = - 1 ; //Use startline -1 to indicate that instead of jumping to the file, the file should be included.
struk . m_popupActions . insert ( id , fakeDec ) ;
}
}
void fill ( TQPopupMenu * parent , LocateResult d , TQString prefix = " " , const DeclarationInfo & sourceVariable = DeclarationInfo ( ) ) {
Debug dbg ( " #fl# " , 10 )
;
if ( ! s | | ! dbg ) {
//dbgMajor() << "safety-counter triggered while filling \"" << d.fullNameChain() << "\"" << endl;
return ;
}
if ( ! sourceVariable . name . isEmpty ( ) & & sourceVariable . name ! = " this " ) {
SimpleTypeImpl : : MemberInfo f ;
f . decl = sourceVariable ;
f . name = sourceVariable . name ;
f . type = d . desc ( ) ;
f . memberType = SimpleTypeImpl : : MemberInfo : : Variable ;
/*int id = m->insertItem( i18n("jump to variable-declaration \"%1\"").arg( type.sourceVariable.name ) , this, TQT_SLOT( popupAction( int ) ) );
m_popupActions . insert ( id , type . sourceVariable ) ; */
struk . insertItem ( parent , f , prefix ) ;
parent - > insertSeparator ( ) ;
if ( ! sourceVariable . comment . isEmpty ( ) ) {
TQPopupMenu * m = PopupTracker : : createPopup ( parent ) ;
parent - > insertItem ( i18n ( " Comment on %1 " ) . arg ( sourceVariable . name ) , m ) ;
TQStringList ls = prepareTextForMenu ( sourceVariable . comment , 15 , 100 ) ;
for ( TQStringList : : iterator it = ls . begin ( ) ; it ! = ls . end ( ) ; + + it ) {
m - > insertItem ( * it , 0 , TQT_SLOT ( popupClassViewAction ( int ) ) ) ;
}
parent - > insertSeparator ( ) ;
}
}
struk . insertItem ( parent , d , prefix ) ;
if ( d - > resolved ( ) & & ! d - > resolved ( ) - > specialization ( ) . isEmpty ( ) ) {
SimpleType p = d - > resolved ( ) - > parent ( ) ;
LocateResult r = p - > locateDecType ( d - > name ( ) ) ;
if ( r ) {
TQPopupMenu * m = PopupTracker : : createPopup ( parent ) ;
parent - > insertItem ( i18n ( " Specialized from \" %1 \" " ) . arg ( cleanForMenu ( r - > fullNameChain ( ) ) ) , m ) ;
fill ( m , r ) ;
}
}
TypeDesc : : TemplateParams p = d - > templateParams ( ) ;
for ( TypeDesc : : TemplateParams : : iterator it = p . begin ( ) ; it ! = p . end ( ) ; + + it ) {
//if( (*it)->resolved() ) {
TQPopupMenu * m = PopupTracker : : createPopup ( parent ) ;
parent - > insertItem ( i18n ( " Template-param \" %1 \" " ) . arg ( cleanForMenu ( ( * it ) - > fullNameChain ( ) ) ) , m ) ;
fill ( m , * * it ) ;
/*} else {
fill ( parent , * * it , prefix + depthAdd ) ;
} */
}
if ( d - > resolved ( ) ) {
if ( d - > resolved ( ) - > asFunction ( ) ) {
LocateResult rt = d - > resolved ( ) - > locateDecType ( d - > resolved ( ) - > asFunction ( ) - > getReturnType ( ) ) ;
if ( rt ) {
TQPopupMenu * m = PopupTracker : : createPopup ( parent ) ;
parent - > insertItem ( i18n ( " Return-type \" %1 \" " ) . arg ( cleanForMenu ( rt - > fullNameChain ( ) ) ) , m ) ;
fill ( m , rt ) ;
}
TQValueList < TypeDesc > args = d - > resolved ( ) - > asFunction ( ) - > getArgumentTypes ( ) ;
TQStringList argNames = d - > resolved ( ) - > asFunction ( ) - > getArgumentNames ( ) ;
if ( ! args . isEmpty ( ) ) {
TQPopupMenu * m = PopupTracker : : createPopup ( parent ) ;
parent - > insertItem ( i18n ( " Argument-types " ) , m ) ;
TQStringList : : iterator it2 = argNames . begin ( ) ;
for ( TQValueList < TypeDesc > : : iterator it = args . begin ( ) ; it ! = args . end ( ) ; + + it ) {
LocateResult at = d - > resolved ( ) - > locateDecType ( * it ) ;
TQString name = " " ;
if ( it2 ! = argNames . end ( ) ) {
name = * it2 ;
+ + it2 ;
}
TQPopupMenu * mo = PopupTracker : : createPopup ( m ) ;
m - > insertItem ( i18n ( " Argument \" %1 \" " ) . arg ( cleanForMenu ( at - > fullNameChain ( ) + " " + name ) ) , mo ) ;
fill ( mo , at ) ;
}
}
}
}
# ifndef DISABLE_TRACING
if ( d . trace ( ) ) {
TQValueList < TQPair < SimpleTypeImpl : : MemberInfo , TypeDesc > > trace = d . trace ( ) - > trace ( ) ;
if ( ! trace . isEmpty ( ) ) {
TQPopupMenu * m = PopupTracker : : createPopup ( parent ) ;
parent - > insertItem ( i18n ( " Trace " ) , m ) ;
for ( TQValueList < TQPair < SimpleTypeImpl : : MemberInfo , TypeDesc > > : : iterator it = trace . begin ( ) ; it ! = trace . end ( ) ; + + it ) {
TQPopupMenu * mo = PopupTracker : : createPopup ( m ) ;
TQString tail = ( * it ) . second . fullNameChain ( ) ;
if ( ! tail . isEmpty ( ) )
tail = " :: " + tail ;
m - > insertItem ( i18n ( " %1 -> %2 " ) . arg ( cleanForMenu ( ( * it ) . first . name + tail ) ) . arg ( cleanForMenu ( ( * it ) . first . type - > fullNameChain ( ) + tail ) ) , mo ) ;
struk . insertItem ( mo , ( * it ) . first , prefix ) ;
if ( ! ( * it ) . first . decl . comment . isEmpty ( ) ) {
mo - > insertSeparator ( ) ;
TQPopupMenu * m = PopupTracker : : createPopup ( mo ) ;
mo - > insertItem ( i18n ( " Comment " ) , m ) ;
TQStringList ls = prepareTextForMenu ( ( * it ) . first . decl . comment , 15 , 100 ) ;
for ( TQStringList : : iterator it = ls . begin ( ) ; it ! = ls . end ( ) ; + + it ) {
m - > insertItem ( * it , 0 , TQT_SLOT ( popupClassViewAction ( int ) ) ) ;
}
}
/*bool needSeparator = true;
if ( struk . shouldShowIncludeMenu ( ) & & struk . receiver - > cppSupport ( ) - > codeCompletionConfig ( ) - > preProcessAllHeaders ( ) & & ! ( * it ) . first . decl . file . operator TQString ( ) . isEmpty ( ) )
fillIncludes ( ( * it ) . first . decl , mo , needSeparator ) ; */
}
}
}
# endif
if ( d - > resolved ( ) ) {
TQValueList < LocateResult > bases = d - > resolved ( ) - > getBases ( ) ;
for ( TQValueList < LocateResult > : : iterator it = bases . begin ( ) ; it ! = bases . end ( ) ; + + it ) {
TQPopupMenu * m = PopupTracker : : createPopup ( parent ) ;
parent - > insertItem ( i18n ( " Base-class \" %1 \" " ) . arg ( cleanForMenu ( ( * it ) - > fullNameChain ( ) ) ) , m ) ;
fill ( m , * it ) ;
}
if ( d - > resolved ( ) - > parent ( ) & & d - > resolved ( ) - > parent ( ) - > desc ( ) ) {
TQPopupMenu * m = PopupTracker : : createPopup ( parent ) ;
parent - > insertItem ( i18n ( " Nested in \" %1 \" " ) . arg ( cleanForMenu ( d - > resolved ( ) - > parent ( ) - > fullTypeResolved ( ) ) ) , m ) ;
fill ( m , d - > resolved ( ) - > parent ( ) - > desc ( ) ) ;
}
if ( ! d - > resolved ( ) - > comment ( ) . isEmpty ( ) ) {
parent - > insertSeparator ( ) ;
TQPopupMenu * m = PopupTracker : : createPopup ( parent ) ;
parent - > insertItem ( i18n ( " Comment on %1 " ) . arg ( cleanForMenu ( d - > name ( ) ) ) , m ) ;
TQStringList ls = prepareTextForMenu ( d - > resolved ( ) - > comment ( ) , 15 , 100 ) ;
for ( TQStringList : : iterator it = ls . begin ( ) ; it ! = ls . end ( ) ; + + it ) {
m - > insertItem ( * it , 0 , TQT_SLOT ( popupClassViewAction ( int ) ) ) ;
}
}
}
//Add entries for including missing include-files
if ( struk . shouldShowIncludeMenu ( ) & & struk . receiver - > cppSupport ( ) - > codeCompletionConfig ( ) - > preProcessAllHeaders ( ) ) {
bool needSeparator = true ;
//Show the include-files for the whole trace, because usually the first in the trace should be the one to include
if ( d . trace ( ) ) {
TQValueList < TQPair < SimpleTypeImpl : : MemberInfo , TypeDesc > > trace = d . trace ( ) - > trace ( ) ;
if ( ! trace . isEmpty ( ) ) {
for ( TQValueList < TQPair < SimpleTypeImpl : : MemberInfo , TypeDesc > > : : iterator it = trace . begin ( ) ; it ! = trace . end ( ) ; + + it ) {
if ( struk . shouldShowIncludeMenu ( ) & & struk . receiver - > cppSupport ( ) - > codeCompletionConfig ( ) - > preProcessAllHeaders ( ) & & ! ( * it ) . first . decl . file . operator TQString ( ) . isEmpty ( ) )
fillIncludes ( ( * it ) . first . decl , parent , needSeparator ) ;
}
}
}
//Show the include-file for the item itself
if ( d - > resolved ( ) & & ! d - > resolved ( ) - > isNamespace ( ) & & struk . receiver - > cppSupport ( ) ) {
fillIncludes ( d - > resolved ( ) - > getDeclarationInfo ( ) , parent , needSeparator ) ;
}
}
}
} ;
struct CompTypeProcessor : public TypeProcessor {
SimpleType m_scope ;
bool m_processArguments ;
CompTypeProcessor ( SimpleType scope , bool processArguments ) : m_scope ( scope ) , m_processArguments ( processArguments ) { }
virtual TQString parentType ( ) {
return m_scope - > fullType ( ) ;
}
virtual TQString processType ( const TQString & type ) {
if ( ! m_processArguments )
return type ;
LocateResult t = m_scope - > locateDecType ( type ) ;
if ( t )
return t - > fullNameChain ( ) ;
else
return type ;
}
} ;
struct CppCodeCompletionData {
TQPtrList < RecoveryPoint > recoveryPoints ;
//TQStringList classNameList;
CppCodeCompletionData ( ) {
recoveryPoints . setAutoDelete ( true ) ;
}
RecoveryPoint * findRecoveryPoint ( int line , int column ) {
if ( recoveryPoints . count ( ) = = 0 )
return 0 ;
TQPair < int , int > pt = tqMakePair ( line , column ) ;
TQPtrListIterator < RecoveryPoint > it ( recoveryPoints ) ;
RecoveryPoint * recPt = 0 ;
while ( it . current ( ) ) {
TQPair < int , int > startPt = tqMakePair ( it . current ( ) - > startLine , it . current ( ) - > startColumn ) ;
TQPair < int , int > endPt = tqMakePair ( it . current ( ) - > endLine , it . current ( ) - > endColumn ) ;
if ( pt < startPt ) {
break ;
}
if ( startPt < pt & & pt < endPt )
recPt = it . current ( ) ;
+ + it ;
}
return recPt ;
}
} ;
CppCodeCompletion : : CppCodeCompletion ( CppSupportPart * part )
: d ( new CppCodeCompletionData ) ,
//Matches on includes
m_includeRx ( " ^ \\ s*# \\ s*include \\ s+[ \" <] " ) ,
//Matches on C++ and C style comments as well as literal strings
m_cppCodeCommentsRx ( " (//([^ \n ]*)( \n |$)|/ \\ *.* \\ */| \" ([^ \\ \\ ]| \\ \\ .)* \" ) " ) ,
//Matches on alpha chars and '.'
m_codeCompleteChRx ( " ([A-Z])|([a-z])|( \\ .) " ) ,
//Matches on "->" and "::"
m_codeCompleteCh2Rx ( " (->)|( \\ : \\ :) " ) {
m_instance = this ;
cppCompletionInstance = this ;
m_cppCodeCommentsRx . setMinimal ( true ) ;
m_pSupport = part ;
connect ( m_pSupport - > codeCompletionConfig ( ) , TQT_SIGNAL ( stored ( ) ) , this , TQT_SLOT ( emptyCache ( ) ) ) ;
m_activeCursor = 0 ;
m_activeEditor = 0 ;
m_activeCompletion = 0 ;
m_activeHintInterface = 0 ;
m_activeView = 0 ;
m_ccTimer = new TQTimer ( this ) ;
m_showStatusTextTimer = new TQTimer ( this ) ;
m_ccLine = 0 ;
m_ccColumn = 0 ;
connect ( m_ccTimer , TQT_SIGNAL ( timeout ( ) ) , this , TQT_SLOT ( slotTimeout ( ) ) ) ;
connect ( m_showStatusTextTimer , TQT_SIGNAL ( timeout ( ) ) , this , TQT_SLOT ( slotStatusTextTimeout ( ) ) ) ;
computeFileEntryList ( ) ;
CppSupportPart * cppSupport = m_pSupport ;
connect ( cppSupport - > project ( ) , TQT_SIGNAL ( addedFilesToProject ( const TQStringList & ) ) ,
this , TQT_SLOT ( computeFileEntryList ( ) ) ) ;
connect ( cppSupport - > project ( ) , TQT_SIGNAL ( removedFilesFromProject ( const TQStringList & ) ) ,
this , TQT_SLOT ( computeFileEntryList ( ) ) ) ;
connect ( cppSupport , TQT_SIGNAL ( synchronousParseReady ( const TQString & , ParsedFilePointer ) ) , this , TQT_SLOT ( synchronousParseReady ( const TQString & , ParsedFilePointer ) ) ) ;
m_bArgHintShow = false ;
m_bCompletionBoxShow = false ;
m_blockForKeyword = false ;
m_demandCompletion = false ;
m_completionMode = NormalCompletion ;
m_repository = new CodeInformationRepository ( cppSupport - > codeRepository ( ) ) ;
connect ( cppSupport - > codeRepository ( ) , TQT_SIGNAL ( catalogRegistered ( Catalog * ) ) , this , TQT_SLOT ( emptyCache ( ) ) ) ;
connect ( cppSupport - > codeRepository ( ) , TQT_SIGNAL ( catalogUnregistered ( Catalog * ) ) , this , TQT_SLOT ( emptyCache ( ) ) ) ;
connect ( cppSupport - > codeRepository ( ) , TQT_SIGNAL ( catalogChanged ( Catalog * ) ) , this , TQT_SLOT ( emptyCache ( ) ) ) ;
setupCodeInformationRepository ( ) ;
if ( part - > partController ( ) - > parts ( ) ) {
TQPtrListIterator < KParts : : Part > it ( * part - > partController ( ) - > parts ( ) ) ;
while ( KParts : : Part * part = it . current ( ) ) {
integratePart ( part ) ;
+ + it ;
}
}
if ( part - > partController ( ) - > activePart ( ) )
slotActivePartChanged ( part - > partController ( ) - > activePart ( ) ) ;
connect ( part - > partController ( ) , TQT_SIGNAL ( partAdded ( KParts : : Part * ) ) ,
this , TQT_SLOT ( slotPartAdded ( KParts : : Part * ) ) ) ;
connect ( part - > partController ( ) , TQT_SIGNAL ( activePartChanged ( KParts : : Part * ) ) ,
this , TQT_SLOT ( slotActivePartChanged ( KParts : : Part * ) ) ) ;
connect ( part , TQT_SIGNAL ( fileParsed ( const TQString & ) ) ,
this , TQT_SLOT ( slotFileParsed ( const TQString & ) ) ) ;
connect ( part , TQT_SIGNAL ( codeModelUpdated ( const TQString & ) ) ,
this , TQT_SLOT ( slotCodeModelUpdated ( const TQString & ) ) ) ;
TDEAction * action = new TDEAction ( i18n ( " Jump to declaration under cursor " ) , 0 , CTRL + Key_Comma ,
this , TQT_SLOT ( slotJumpToDeclCursorContext ( ) ) , part - > actionCollection ( ) , " jump_to_declaration_cursor_context " ) ;
action - > plug ( & m_DummyActionWidget ) ;
action = new TDEAction ( i18n ( " Jump to definition under cursor " ) , 0 , CTRL + Key_Period ,
this , TQT_SLOT ( slotJumpToDefCursorContext ( ) ) , part - > actionCollection ( ) , " jump_to_defintion_cursor_context " ) ;
action - > plug ( & m_DummyActionWidget ) ;
}
CppCodeCompletion : : ~ CppCodeCompletion ( ) {
delete m_repository ;
delete d ;
}
void CppCodeCompletion : : addStatusText ( TQString text , int timeout ) {
m_statusTextList . append ( TQPair < int , TQString > ( timeout , text ) ) ;
if ( ! m_showStatusTextTimer - > isActive ( ) ) {
slotStatusTextTimeout ( ) ;
}
}
void CppCodeCompletion : : clearStatusText ( ) {
m_statusTextList . clear ( ) ;
m_showStatusTextTimer - > stop ( ) ;
}
void CppCodeCompletion : : slotStatusTextTimeout ( ) {
if ( m_statusTextList . isEmpty ( ) | | ! m_pSupport )
return ;
// m_pSupport->mainWindow() ->statusBar() ->message( m_statusTextList.front().second, m_statusTextList.front().first );
m_showStatusTextTimer - > start ( m_statusTextList . front ( ) . first , true ) ;
m_statusTextList . pop_front ( ) ;
}
void CppCodeCompletion : : slotTimeout ( ) {
if ( ! m_activeCursor | | ! m_activeEditor | | ! m_activeCompletion )
return ;
uint nLine , nCol ;
m_activeCursor - > cursorPositionReal ( & nLine , & nCol ) ;
if ( nLine ! = m_ccLine | | nCol ! = m_ccColumn )
return ;
TQString textLine = m_activeEditor - > textLine ( nLine ) ;
TQChar ch = textLine [ nCol ] ;
if ( ch . isLetterOrNumber ( ) | | ch = = ' _ ' )
return ;
completeText ( ) ;
}
void CppCodeCompletion : : slotArgHintHidden ( ) {
//kdDebug(9007) << "CppCodeCompletion::slotArgHintHidden()" << endl;
m_bArgHintShow = false ;
}
void CppCodeCompletion : : slotCompletionBoxHidden ( ) {
//kdDebug( 9007 ) << "CppCodeCompletion::slotCompletionBoxHidden()" << endl;
m_bCompletionBoxShow = false ;
}
void CppCodeCompletion : : integratePart ( KParts : : Part * part ) {
if ( ! part | | ! part - > widget ( ) )
return ;
KTextEditor : : Document * doc = dynamic_cast < KTextEditor : : Document * > ( part ) ;
if ( doc ) {
kdDebug ( 9007 ) < < k_funcinfo < < " integrate document: " < < doc < < endl ;
if ( m_pSupport ) { //The slot should connected even when automatic completion is disabled, so it can be enabled any time
kdDebug ( 9007 ) < < k_funcinfo < < " enabling code completion " < < endl ;
connect ( part , TQT_SIGNAL ( textChanged ( ) ) , this , TQT_SLOT ( slotTextChanged ( ) ) ) ;
connect ( part - > widget ( ) , TQT_SIGNAL ( completionDone ( ) ) , this ,
TQT_SLOT ( slotCompletionBoxHidden ( ) ) ) ;
connect ( part - > widget ( ) , TQT_SIGNAL ( completionAborted ( ) ) , this ,
TQT_SLOT ( slotCompletionBoxHidden ( ) ) ) ;
connect ( part - > widget ( ) , TQT_SIGNAL ( argHintHidden ( ) ) , this ,
TQT_SLOT ( slotArgHintHidden ( ) ) ) ;
}
}
}
void CppCodeCompletion : : slotPartAdded ( KParts : : Part * part ) {
integratePart ( part ) ;
}
void CppCodeCompletion : : slotActivePartChanged ( KParts : : Part * part ) {
emptyCache ( ) ;
this - > d - > recoveryPoints . clear ( ) ;
if ( m_activeHintInterface & & m_activeView ) {
disconnect ( m_activeView , TQT_SIGNAL ( needTextHint ( int , int , TQString & ) ) , this , TQT_SLOT ( slotTextHint ( int , int , TQString & ) ) ) ;
m_activeHintInterface = 0 ;
}
if ( ! part )
return ;
kdDebug ( 9007 ) < < k_funcinfo < < endl ;
m_activeFileName = TQString ( ) ;
KTextEditor : : Document * doc = dynamic_cast < KTextEditor : : Document * > ( part ) ;
if ( ! doc )
return ;
m_activeFileName = doc - > url ( ) . path ( ) ;
// if the interface stuff fails we should disable codecompletion automatically
m_activeEditor = dynamic_cast < KTextEditor : : EditInterface * > ( part ) ;
if ( ! m_activeEditor ) {
kdDebug ( 9007 ) < < " Editor doesn't support the EditDocumentIface " < < endl ;
return ;
}
m_activeCursor = dynamic_cast < KTextEditor : : ViewCursorInterface * > ( part - > widget ( ) ) ;
if ( ! m_activeCursor ) {
kdDebug ( 9007 ) < < " The editor doesn't support the CursorDocumentIface! " < < endl ;
return ;
}
m_activeCompletion = dynamic_cast < KTextEditor : : CodeCompletionInterface * > ( part - > widget ( ) ) ;
if ( ! m_activeCompletion ) {
kdDebug ( 9007 ) < < " Editor doesn't support the CompletionIface " < < endl ;
return ;
}
m_activeView = part ? dynamic_cast < KTextEditor : : View * > ( part - > widget ( ) ) : 0 ;
if ( m_activeView )
m_activeHintInterface = dynamic_cast < KTextEditor : : TextHintInterface * > ( m_activeView ) ;
char * q = 0 ;
kdDebug ( ) < < q < < endl ;
if ( m_activeHintInterface ) {
# ifndef DISABLETOOLTIPS
m_activeHintInterface - > enableTextHints ( 500 ) ;
connect ( m_activeView , TQT_SIGNAL ( needTextHint ( int , int , TQString & ) ) , this , TQT_SLOT ( slotTextHint ( int , int , TQString & ) ) ) ;
# endif
} else {
kdDebug ( 9007 ) < < " editor has no text-hint-interface " < < endl ;
}
kdDebug ( 9007 ) < < k_funcinfo < < " -- end " < < endl ;
}
void CppCodeCompletion : : slotTextChanged ( ) {
m_ccTimer - > stop ( ) ;
if ( ! m_activeCursor )
return ;
unsigned int nLine , nCol ;
m_activeCursor - > cursorPositionReal ( & nLine , & nCol ) ;
TQString strCurLine = m_activeEditor - > textLine ( nLine ) ;
TQString ch = strCurLine . mid ( nCol - 1 , 1 ) ;
TQString ch2 = strCurLine . mid ( nCol - 2 , 2 ) ;
// Tell the completion box to _go_away_ when the completion char
// becomes empty or whitespace and the box is already showing.
// !!WARNING!! This is very hackish, but KTE doesn't offer a way
// to tell the completion box to _go_away_
if ( ch . simplifyWhiteSpace ( ) . isEmpty ( ) & &
! strCurLine . simplifyWhiteSpace ( ) . contains ( " virtual " ) & &
m_bCompletionBoxShow ) {
TQValueList < KTextEditor : : CompletionEntry > entryList ;
m_bCompletionBoxShow = true ;
m_activeCompletion - > showCompletionBox ( entryList , 0 ) ;
}
m_ccLine = 0 ;
m_ccColumn = 0 ;
bool argsHint = m_pSupport - > codeCompletionConfig ( ) - > automaticArgumentsHint ( ) ;
bool codeComplete = m_pSupport - > codeCompletionConfig ( ) - > automaticCodeCompletion ( ) ;
bool headComplete = codeComplete ; //m_pSupport->codeCompletionConfig() ->automaticHeaderCompletion();
// m_codeCompleteChRx completes on alpha chars and '.'
// m_codeCompleteCh2Rx completes on "->" and "::"
if ( ( argsHint & & ch = = " ( " ) | |
( codeComplete & & strCurLine . simplifyWhiteSpace ( ) . contains ( " virtual " ) ) | |
( codeComplete & & ( m_codeCompleteChRx . search ( ch ) ! = - 1 | |
m_codeCompleteCh2Rx . search ( ch2 ) ! = - 1 ) ) | |
( headComplete & & ( ch = = " \" " | | ch = = " < " ) & & m_includeRx . search ( strCurLine ) ! = - 1 ) ) {
int time ;
m_ccLine = nLine ;
m_ccColumn = nCol ;
if ( ch = = " ( " )
time = m_pSupport - > codeCompletionConfig ( ) - > argumentsHintDelay ( ) ;
else
time = m_pSupport - > codeCompletionConfig ( ) - > codeCompletionDelay ( ) ;
m_ccTimer - > start ( time , true ) ;
}
fitContextItem ( nLine , nCol ) ;
}
void CppCodeCompletion : : fitContextItem ( int nLine , int nCol ) {
if ( ! SimpleType : : globalNamespace ( ) ) {
kdDebug ( 9007 ) < < " no global namespace was set, clearing cache " < < endl ;
emptyCache ( ) ;
}
///Find out whether the cache may be used on, or has to be cleared.
if ( m_cachedFromContext ) {
int sLine , sCol , eLine , eCol ;
m_cachedFromContext - > getStartPosition ( & sLine , & sCol ) ;
m_cachedFromContext - > getEndPosition ( & eLine , & eCol ) ;
if ( ( nLine < sLine | | ( nLine = = sLine & & nCol < sCol ) ) | | ( nLine > eLine | | ( nLine = = eLine & & nCol > = eCol ) ) ) {
///The stored item was left. First check whether the item was expanded.
FileDom file = m_pSupport - > codeModel ( ) - > fileByName ( m_activeFileName ) ;
if ( file ) {
CodeModelUtils : : CodeModelHelper fileModel ( m_pSupport - > codeModel ( ) , file ) ;
if ( m_cachedFromContext - > isClass ( ) ) {
ClassDom klass = fileModel . classAt ( nLine , nCol ) ;
if ( klass ) {
ClassDom oldClass = dynamic_cast < ClassModel * > ( m_cachedFromContext . data ( ) ) ;
if ( oldClass & & oldClass - > name ( ) = = klass - > name ( ) & & oldClass - > scope ( ) = = klass - > scope ( ) ) {
m_cachedFromContext = klass . data ( ) ;
} else {
emptyCache ( ) ;
}
} else {
emptyCache ( ) ;
}
} else if ( m_cachedFromContext - > isFunction ( ) ) {
FunctionDom function = fileModel . functionAt ( nLine , nCol ) ;
if ( function ) {
FunctionDom oldFunction = dynamic_cast < FunctionModel * > ( m_cachedFromContext . data ( ) ) ;
if ( oldFunction & & oldFunction - > name ( ) = = function - > name ( ) & & function - > scope ( ) = = oldFunction - > scope ( ) & & oldFunction - > argumentList ( ) . count ( ) = = function - > argumentList ( ) . count ( ) ) {
ArgumentList l1 = oldFunction - > argumentList ( ) ;
ArgumentList l2 = function - > argumentList ( ) ;
ArgumentList : : iterator it = l1 . begin ( ) ;
ArgumentList : : iterator it2 = l2 . begin ( ) ;
bool match = true ;
while ( it ! = l1 . end ( ) ) {
if ( ( * it ) - > type ( ) ! = ( * it2 ) - > type ( ) ) {
match = false ;
break ;
}
+ + it ;
+ + it2 ;
}
if ( match ) {
m_cachedFromContext = function . data ( ) ;
} else {
emptyCache ( ) ;
}
} else {
emptyCache ( ) ;
}
} else {
emptyCache ( ) ;
}
} else {
emptyCache ( ) ;
}
} else {
emptyCache ( ) ;
}
}
}
}
enum { T_ACCESS , T_PAREN , T_BRACKET , T_IDE , T_UNKNOWN , T_TEMP } ;
TQString CppCodeCompletion : : replaceCppComments ( const TQString & contents ) {
TQString text = contents ;
int pos = 0 ;
while ( ( pos = m_cppCodeCommentsRx . search ( text , pos ) ) ! = - 1 ) {
if ( m_cppCodeCommentsRx . cap ( 1 ) . startsWith ( " // " ) ) {
TQString before = m_cppCodeCommentsRx . cap ( 1 ) ;
TQString after ;
after . fill ( ' ' , before . length ( ) - 5 ) ;
after . prepend ( " /* " ) ;
after . append ( " */ " ) ;
text . replace ( pos , before . length ( ) - 1 , after ) ;
pos + = after . length ( ) ;
} else {
pos + = m_cppCodeCommentsRx . matchedLength ( ) ;
}
}
return text ;
}
int CppCodeCompletion : : expressionAt ( const TQString & contents , int index ) {
kdDebug ( 9007 ) < < k_funcinfo < < endl ;
/* C++ style comments present issues with finding the expr so I'm
matching for them and replacing them with empty C style comments
of the same length for purposes of finding the expr . */
TQString text = clearComments ( contents ) ;
int last = T_UNKNOWN ;
int start = index ;
- - index ;
while ( index > 0 ) {
while ( index > 0 & & text [ index ] . isSpace ( ) ) {
- - index ;
}
TQChar ch = text [ index ] ;
TQString ch2 = text . mid ( index - 1 , 2 ) ;
if ( ( last ! = T_IDE ) & & ( ch . isLetterOrNumber ( ) | | ch = = ' _ ' ) ) {
while ( index > 0 & & ( text [ index ] . isLetterOrNumber ( ) | | text [ index ] = = ' _ ' ) ) {
- - index ;
}
last = T_IDE ;
} else if ( last ! = T_IDE & & ch = = ' ) ' ) {
int count = 0 ;
while ( index > 0 ) {
TQChar ch = text [ index ] ;
if ( ch = = ' ( ' ) {
+ + count ;
} else if ( ch = = ' ) ' ) {
- - count ;
} else if ( count = = 0 ) {
//index;
last = T_PAREN ;
break ;
}
- - index ;
}
} else if ( last ! = T_IDE & & ch = = ' > ' & & ch2 ! = " -> " ) {
int count = 0 ;
while ( index > 0 ) {
TQChar ch = text [ index ] ;
if ( ch = = ' < ' ) {
+ + count ;
} else if ( ch = = ' > ' ) {
- - count ;
} else if ( count = = 0 ) {
//--index;
last = T_TEMP ;
break ;
}
- - index ;
}
} else if ( ch = = ' ] ' ) {
int count = 0 ;
while ( index > 0 ) {
TQChar ch = text [ index ] ;
if ( ch = = ' [ ' ) {
+ + count ;
} else if ( ch = = ' ] ' ) {
- - count ;
} else if ( count = = 0 ) {
//--index;
last = T_BRACKET ;
break ;
}
- - index ;
}
} else if ( ch = = ' . ' ) {
- - index ;
last = T_ACCESS ;
} else if ( ch2 = = " :: " ) {
index - = 2 ;
last = T_ACCESS ;
} else if ( ch2 = = " -> " ) {
index - = 2 ;
last = T_ACCESS ;
} else {
if ( start > index ) {
+ + index ;
}
last = T_UNKNOWN ;
break ;
}
}
///If we're at the first item, the above algorithm cannot be used safely,
///so just determine whether the sign is valid for the beginning of an expression, if it isn't reject it.
if ( index = = 0 & & start > index & & ! ( text [ index ] . isLetterOrNumber ( ) | | text [ index ] = = ' _ ' | | text [ index ] = = ' : ' ) ) {
+ + index ;
}
return index ;
}
TQStringList CppCodeCompletion : : splitExpression ( const TQString & text ) {
# define ADD_CURRENT()\
if ( current . length ( ) ) { l < < current ; /*kdDebug(9007) << "add word " << current << endl;*/ current = " " ; }
TQStringList l ;
uint index = 0 ;
TQString current ;
while ( index < text . length ( ) ) {
TQChar ch = text [ index ] ;
TQString ch2 = text . mid ( index , 2 ) ;
if ( ch = = ' . ' ) {
current + = ch ;
ADD_CURRENT ( ) ;
+ + index ;
} else if ( ch = = ' ( ' ) {
int count = 0 ;
while ( index < text . length ( ) ) {
TQChar ch = text [ index ] ;
if ( ch = = ' ( ' ) {
+ + count ;
} else if ( ch = = ' ) ' ) {
- - count ;
} else if ( count = = 0 ) {
break ;
}
current + = ch ;
+ + index ;
}
} else if ( ch = = ' [ ' ) {
int count = 0 ;
while ( index < text . length ( ) ) {
TQChar ch = text [ index ] ;
if ( ch = = ' [ ' ) {
+ + count ;
} else if ( ch = = ' ] ' ) {
- - count ;
} else if ( count = = 0 ) {
break ;
}
current + = ch ;
+ + index ;
}
} else if ( ch2 = = " -> " ) {
current + = ch2 ;
ADD_CURRENT ( ) ;
index + = 2 ;
} /*else if ( ch2 == "::" )
{
current + = ch2 ;
ADD_CURRENT ( ) ;
index + = 2 ;
} */
else {
current + = text [ index ] ;
+ + index ;
}
}
ADD_CURRENT ( ) ;
return l ;
}
///Before calling this, a SimpleTypeConfiguration-object should be created, so that the ressources will be freed when that object is destroyed
EvaluationResult CppCodeCompletion : : evaluateExpressionAt ( int line , int column , SimpleTypeConfiguration & conf , bool ifUnknownSetType ) {
kdDebug ( 9007 ) < < " CppCodeCompletion::evaluateExpressionAt( " < < line < < " , " < < column < < " ) " < < endl ;
if ( ! m_pSupport | | ! m_activeEditor )
return EvaluationResult ( ) ;
if ( line < 0 | | line > = ( int ) m_activeEditor - > numLines ( ) )
return EvaluationResult ( ) ;
if ( column < 0 | | column > = m_activeEditor - > lineLength ( line ) )
return EvaluationResult ( ) ;
{
TQString curLine = m_activeEditor - > textLine ( line ) ;
///move column to the last letter of the pointed word
while ( column + 1 < ( int ) curLine . length ( ) & & isValidIdentifierSign ( curLine [ column ] ) & & isValidIdentifierSign ( curLine [ column + 1 ] ) )
column + + ;
//if( column > 0 ) column--;
if ( column > = ( int ) curLine . length ( ) | | curLine [ column ] . isSpace ( ) )
return EvaluationResult ( ) ;
TQString expr = curLine . left ( column + 1 ) ;
kdDebug ( 9007 ) < < " evaluating line \" " < < expr . stripWhiteSpace ( ) < < " \" " < < endl ;
if ( curLine [ column ] = = ' - ' | | curLine [ column ] = = ' ; ' )
- - column ;
EvaluationResult type = evaluateExpressionType ( line , column + 1 , conf , ifUnknownSetType ? addFlag ( DefaultEvaluationOptions , DefaultAsTypeExpression ) : DefaultEvaluationOptions ) ;
kdDebug ( 9007 ) < < " type: " < < type - > fullNameChain ( ) < < endl ;
return type ;
}
}
void CppCodeCompletion : : popupAction ( int number ) {
PopupActions : : iterator it = m_popupActions . find ( number ) ;
if ( it ! = m_popupActions . end ( ) ) {
TQString fileName = ( * it ) . file = = " current_file " ? m_activeFileName : ( * it ) . file . operator TQString ( ) ;
if ( ( * it ) . startLine = = - 1 ) {
//startLine -1 indicates that the file should be added to the include-files
m_activeEditor - > insertLine ( 0 , TQString ( " #include \" %1 \" /* defines %2 */ " ) . arg ( fileName ) . arg ( ( * it ) . name ) ) ;
} else {
m_pSupport - > partController ( ) - > editDocument ( fileName , ( * it ) . startLine ) ;
}
} else {
kdDebug ( 9007 ) < < " error " < < endl ;
}
}
void CppCodeCompletion : : popupDefinitionAction ( int number ) {
PopupActions : : iterator it = m_popupDefinitionActions . find ( number ) ;
if ( it ! = m_popupDefinitionActions . end ( ) ) {
TQString fileName = ( * it ) . file = = " current_file " ? m_activeFileName : ( * it ) . file . operator TQString ( ) ;
if ( ! m_pSupport - > switchHeaderImpl ( fileName , ( * it ) . startLine , ( * it ) . startCol ) )
m_pSupport - > partController ( ) - > editDocument ( fileName , ( * it ) . startLine ) ;
} else {
kdDebug ( 9007 ) < < " error " < < endl ;
}
}
void CppCodeCompletion : : selectItem ( ItemDom item ) {
Extensions : : KDevCodeBrowserFrontend * f = m_pSupport - > extension < Extensions : : KDevCodeBrowserFrontend > ( " KDevelop/CodeBrowserFrontend " ) ;
if ( f ! = 0 ) {
ItemDom itemDom ( & ( * item ) ) ;
f - > jumpedToItem ( itemDom ) ;
} else {
kdDebug ( ) < < " could not find the proper extension " < < endl ;
}
}
void CppCodeCompletion : : popupClassViewAction ( int number ) {
PopupClassViewActions : : iterator it = m_popupClassViewActions . find ( number ) ;
if ( it ! = m_popupClassViewActions . end ( ) ) {
if ( ( * it ) )
selectItem ( * it ) ;
} else {
kdDebug ( 9007 ) < < " error " < < endl ;
}
}
void CppCodeCompletion : : contextEvaluationMenus ( TQPopupMenu * popup , const Context * context , int line , int column ) {
clearStatusText ( ) ;
Q_UNUSED ( context ) ;
if ( ! m_pSupport - > codeCompletionConfig ( ) - > showEvaluationContextMenu ( ) )
return ;
kdDebug ( 9007 ) < < " CppCodeCompletion::contextEvaluationMenu() " < < endl ;
PopupTracker : : print ( ) ;
m_popupActions . clear ( ) ;
m_popupDefinitionActions . clear ( ) ;
m_popupClassViewActions . clear ( ) ;
if ( ! m_pSupport | | ! m_activeEditor )
return ;
struct SetDbgState {
DBGStreamType & st ;
bool oldState ;
SetDbgState ( DBGStreamType & targ , bool state ) : st ( targ ) {
oldState = targ . state ( ) ;
targ . setState ( state ) ;
}
~ SetDbgState ( ) {
st . setState ( oldState ) ;
}
} ;
int cpos = 0 ;
SetDbgState stt ( dbgState , disableVerboseForContextMenu ) ;
SimpleTypeConfiguration conf ( m_activeFileName ) ;
EvaluationResult type = evaluateExpressionAt ( line , column , conf ) ;
///Test if it is a macro
if ( type . isMacro ) {
TQPopupMenu * m = PopupTracker : : createPopup ( popup ) ;
int gid ;
if ( contextMenuEntriesAtTop )
gid = popup - > insertItem ( i18n ( " Navigate by Macro \" %1 \" " ) . arg ( cleanForMenu ( type . macro . name ( ) ) ) , m , 5 , cpos + + ) ;
else
gid = popup - > insertItem ( i18n ( " Navigate by Macro \" %1 \" " ) . arg ( cleanForMenu ( type . macro . name ( ) ) ) , m ) ;
int id = m - > insertItem ( i18n ( " Jump to %1 " ) . arg ( cleanForMenu ( type . macro . name ( ) ) ) , this , TQT_SLOT ( popupAction ( int ) ) ) ;
TQPopupMenu * b = PopupTracker : : createPopup ( m ) ;
m - > insertItem ( i18n ( " Body " ) , b ) ;
DeclarationInfo i ;
i . file = type . macro . fileName ( ) ;
i . startCol = type . macro . column ( ) ;
i . startLine = type . macro . line ( ) ;
i . endCol = type . macro . column ( ) ;
i . endLine = type . macro . line ( ) ;
m_popupActions . insert ( id , i ) ;
TQStringList ls = prepareTextForMenu ( type . macro . body ( ) , 20 , 100 ) ;
for ( TQStringList : : iterator it = ls . begin ( ) ; it ! = ls . end ( ) ; + + it ) {
b - > insertItem ( * it , 0 , TQT_SLOT ( popupClassViewAction ( int ) ) ) ;
}
}
///Test if it is an include-directive
TQString includeFileName , includeFilePath ;
bool simpleAlgorithm = false ;
bool isIncludeDirective = getIncludeInfo ( line , includeFileName , includeFilePath , simpleAlgorithm ) ;
if ( isIncludeDirective ) {
///Add menu entry
if ( ! includeFilePath . isEmpty ( ) ) {
int gid ;
TQPopupMenu * m = PopupTracker : : createPopup ( popup ) ;
if ( contextMenuEntriesAtTop )
gid = popup - > insertItem ( i18n ( " Goto Include File: %1 " ) . arg ( cleanForMenu ( includeFileName ) ) , m , 5 , cpos + + ) ;
else
gid = popup - > insertItem ( i18n ( " Goto Include File: %1 " ) . arg ( cleanForMenu ( includeFileName ) ) , m ) ;
int id = m - > insertItem ( i18n ( " Jump to %1 " ) . arg ( cleanForMenu ( includeFilePath ) ) , this , TQT_SLOT ( popupAction ( int ) ) ) ;
DeclarationInfo i ;
i . file = includeFilePath ;
i . startCol = 0 ;
i . startLine = 0 ;
i . endCol = 0 ;
i . endLine = 0 ;
m_popupActions . insert ( id , i ) ;
if ( simpleAlgorithm & & cppSupport ( ) - > codeCompletionConfig ( ) - > resolveIncludePaths ( ) ) {
//Add a notification that the correct algorithm failed in finding the include-file correctly
m - > insertItem ( i18n ( " This include-file could not be located regularly, and was selected from the project file list. " ) ) ;
}
} else {
///Could not find include-file
if ( contextMenuEntriesAtTop )
popup - > insertItem ( i18n ( " Not Found: \" %1 \" " ) . arg ( includeFileName ) , 5 , cpos + + ) ;
else
popup - > insertItem ( i18n ( " Not Found: \" %1 \" " ) . arg ( includeFileName ) ) ;
}
}
///Break if we cannot show additional information
if ( isIncludeDirective | | ( ! type - > resolved ( ) & & ! type . sourceVariable & & ( ! type . resultType . trace ( ) | | type . resultType . trace ( ) - > trace ( ) . isEmpty ( ) ) & & ! BuiltinTypes : : isBuiltin ( type . resultType ) ) )
return ;
TQString name = type - > fullNameChain ( ) ;
if ( type . sourceVariable )
name + = " " + type . sourceVariable . name ;
if ( type . resultType - > resolved ( ) & & type . resultType - > resolved ( ) - > asFunction ( ) )
name = buildSignature ( type . resultType - > resolved ( ) ) ;
///Fill the jump-menu
{
PopupFillerHelpStruct h ( this ) ;
PopupFiller < PopupFillerHelpStruct > filler ( h , " " ) ;
TQPopupMenu * m = PopupTracker : : createPopup ( popup ) ;
int gid ;
if ( contextMenuEntriesAtTop )
gid = popup - > insertItem ( i18n ( " Navigate by \" %1 \" " ) . arg ( cleanForMenu ( name ) ) , m , 5 , cpos + + ) ;
else
gid = popup - > insertItem ( i18n ( " Navigate by \" %1 \" " ) . arg ( cleanForMenu ( name ) ) , m ) ;
popup - > setWhatsThis ( gid , i18n ( " <b>Navigation</b><p>Provides a menu to navigate to positions of items that are involved in this expression " ) ) ;
/*if( type.sourceVariable && type.sourceVariable.name != "this" ) {
int id = m - > insertItem ( i18n ( " jump to variable-declaration \" %1 \" " ) . arg ( type . sourceVariable . name ) , this , TQT_SLOT ( popupAction ( int ) ) ) ;
m_popupActions . insert ( id , type . sourceVariable ) ;
} */
filler . fill ( m , type , " " , type . sourceVariable ) ;
}
if ( type - > resolved ( ) ) {
///Now fill the class-view-browsing-stuff
{
TQPopupMenu * m = PopupTracker : : createPopup ( popup ) ;
int gid ;
if ( contextMenuEntriesAtTop )
gid = popup - > insertItem ( i18n ( " Navigate Class-View by \" %1 \" " ) . arg ( cleanForMenu ( name ) ) , m , 6 , cpos + + ) ;
else
gid = popup - > insertItem ( i18n ( " Navigate Class-View by \" %1 \" " ) . arg ( cleanForMenu ( name ) ) , m ) ;
popup - > setWhatsThis ( gid , i18n ( " <b>Navigation</b><p>Provides a menu to show involved items in the class-view " ) ) ;
PopupClassViewFillerHelpStruct h ( this ) ;
PopupFiller < PopupClassViewFillerHelpStruct > filler ( h , " " ) ;
filler . fill ( m , type ) ;
}
}
if ( contextMenuEntriesAtTop )
popup - > insertSeparator ( cpos ) ;
}
void CppCodeCompletion : : slotTextHint ( int line , int column , TQString & text ) {
if ( ! m_pSupport - > codeCompletionConfig ( ) - > statusBarTypeEvaluation ( ) )
return ;
kdDebug ( 9007 ) < < " CppCodeCompletion::slotTextHint() " < < endl ;
clearStatusText ( ) ;
if ( m_lastHintTime . msecsTo ( TQTime : : currentTime ( ) ) < 300 ) {
kdDebug ( 9007 ) < < " slotNeedTextHint called too often " < < endl ;
return ;
}
m_lastHintTime = TQTime : : currentTime ( ) ;
clearStatusText ( ) ;
text = " " ;
if ( ! m_pSupport | | ! m_activeEditor )
return ;
SimpleTypeConfiguration conf ( m_activeFileName ) ;
EvaluationResult type = evaluateExpressionAt ( line , column , conf ) ;
if ( type . expr . expr ( ) . stripWhiteSpace ( ) . isEmpty ( ) )
return ; ///Expression could not be found
if ( type . sourceVariable ) {
text + = type . sourceVariable . toText ( ) + " \n " ;
}
if ( type - > resolved ( ) ) {
/*SimpleTypeFunctionInterface* f = type->resolved()->asFunction();
if ( f ) {
text + = " function: \" " + buildSignature ( type - > resolved ( ) ) + " \" " ;
} else {
TQValueList < TypeDesc > trace = type . resultType - > trace ( ) ;
if ( ! trace . isEmpty ( ) ) {
for ( TQValueList < TypeDesc > : : iterator it = trace . begin ( ) ; it ! = trace . end ( ) ; + + it ) {
text + = ( * it ) . fullNameChain ( ) + " --> " ;
}
text + = " \n " ;
}
text + = " type: \" " + type . resultType - > fullTypeResolved ( ) + " \" " ;
}
if ( type . resultType - > parent ( ) ) text + = " \n nested in: \" " + type . resultType - > parent ( ) - > fullTypeResolvedWithScope ( ) + " \" " ;
DeclarationInfo i = type . resultType - > getDeclarationInfo ( ) ;
if ( i ) text + = " \n " + i . locationToText ( ) ;
if ( ! type . resultType - > comment ( ) . isEmpty ( ) ) text + = " \n \n " + type . resultType - > comment ( ) + " " ; */
} else { }
kdDebug ( 9007 ) < < " showing: \n " < < text < < endl ;
const int timeout = 2000 ;
if ( type - > resolved ( ) ) {
addStatusText ( i18n ( " Type of \" %1 \" is \" %2 \" " ) . arg ( type . expr . expr ( ) ) . arg ( type - > fullNameChain ( ) ) , timeout ) ;
if ( type . sourceVariable & & ! type . sourceVariable . comment . isEmpty ( ) ) {
addStatusText ( i18n ( " Comment on variable \" %1 \" : \" %2 \" " ) . arg ( type . sourceVariable . name ) . arg ( type . sourceVariable . comment ) , 10000 ) ;
}
if ( ! type - > resolved ( ) - > comment ( ) . isEmpty ( ) ) {
addStatusText ( i18n ( " Comment on \" %1 \" : \" %2 \" " ) . arg ( type - > name ( ) ) . arg ( type - > resolved ( ) - > comment ( ) ) , 10000 ) ;
}
if ( type - > resolved ( ) - > comment ( ) . isEmpty ( ) ) {
addStatusText ( i18n ( " \" %1 \" has no comment " ) . arg ( type - > name ( ) ) , timeout ) ;
}
} else {
if ( type ) {
if ( ! BuiltinTypes : : isBuiltin ( type . resultType ) ) {
addStatusText ( i18n ( " Type of \" %1 \" is unresolved, name: \" %2 \" " ) . arg ( type . expr . expr ( ) ) . arg ( type - > fullNameChain ( ) ) , 2 * timeout ) ;
} else {
addStatusText ( i18n ( " \" %1 \" is of builtin type \" %2 \" , a %3 " ) . arg ( type . expr . expr ( ) ) . arg ( type - > fullNameChain ( ) ) . arg ( BuiltinTypes : : comment ( type . resultType ) ) , 2 * timeout ) ;
}
} else {
addStatusText ( i18n ( " Type of \" %1 \" could not be evaluated: tried to evaluate expression as \" %2 \" " ) . arg ( type . expr . expr ( ) ) . arg ( type . expr . typeAsString ( ) ) , 2 * timeout ) ;
}
}
text = " " ; ///Don't really use tooltips since those are not implemented in katepart, and don't work right in the qt-designer based part
}
///not good..
bool CppCodeCompletion : : isTypeExpression ( const TQString & expr ) {
TypeDesc d ( expr ) ;
if ( ! d . isValidType ( ) )
return false ;
TQString ex = d . fullNameChain ( ) ;
TQStringList lex = TQStringList : : split ( " " , ex ) ;
TQStringList lexpr = TQStringList : : split ( " " , expr ) ;
return lex . join ( " " ) = = lexpr . join ( " " ) ;
}
bool CppCodeCompletion : : mayBeTypeTail ( int line , int column , TQString & append , bool inFunction ) {
TQString tail = clearComments ( m_activeEditor - > text ( line , column + 1 , line + 10 > ( int ) m_activeEditor - > numLines ( ) ? ( int ) m_activeEditor - > numLines ( ) : line + 10 , 0 ) ) ;
tail . replace ( " \n " , " " ) ;
SafetyCounter s ( 100 ) ;
bool hadSpace = false ;
while ( ! tail . isEmpty ( ) & & s ) {
if ( tail [ 0 ] = = ' ; ' ) {
return false ;
} else if ( ( ! inFunction & & tail [ 0 ] = = ' , ' ) | | tail [ 0 ] = = ' & ' | | tail [ 0 ] = = ' * ' | | tail [ 0 ] = = ' { ' | | tail [ 0 ] = = ' : ' ) {
return true ;
} else if ( isTypeOpenParen ( tail [ 0 ] ) ) {
///TODO: use findClose to make the whole expression include template-params
int to = findClose ( tail , 0 ) ;
if ( to ! = - 1 ) {
append = tail . left ( to + 1 ) ;
tail = tail . mid ( to + 1 ) ;
} else {
return false ;
}
} else if ( isTypeCloseParen ( tail [ 0 ] ) ) {
return true ;
} else if ( tail [ 0 ] . isSpace ( ) ) {
tail = tail . mid ( 1 ) ;
hadSpace = true ;
} else if ( tail [ 0 ] . isLetter ( ) ) {
return hadSpace ;
} else {
break ;
}
}
return false ;
}
bool CppCodeCompletion : : canBeTypePrefix ( const TQString & prefix , bool inFunction ) {
for ( int p = prefix . length ( ) - 1 ; p > = 0 ; - - p ) {
if ( prefix [ p ] . isSpace ( ) ) {
continue ;
}
if ( prefix [ p ] = = ' ; ' | | prefix [ p ] = = ' < ' | | prefix [ p ] = = ' : ' | | ( ! inFunction & & ( prefix [ p ] = = ' ( ' | | prefix [ p ] = = ' , ' ) ) | | prefix [ p ] = = ' } ' | | prefix [ p ] = = ' { ' ) {
return true ;
}
///@todo: make this a simple regex
if ( prefix [ p ] . isLetterOrNumber ( ) & & ( tokenAt ( prefix , " class " , p ) | | tokenAt ( prefix , " struct " , p ) | | tokenAt ( prefix , " const " , p ) | | tokenAt ( prefix , " typedef " , p ) | | tokenAt ( prefix , " public " , p ) | | tokenAt ( prefix , " protected " , p ) | | tokenAt ( prefix , " private " , p ) | | tokenAt ( prefix , " virtual " , p ) | | tokenAt ( prefix , " static " , p ) | | tokenAt ( prefix , " virtual " , p ) ) )
return true ;
else {
return false ;
}
}
return true ;
}
///This function is just a litte hack und should be remade, it doesn't work for all cases
ExpressionInfo CppCodeCompletion : : findExpressionAt ( int line , int column , int startLine , int startCol , bool inFunction ) {
ExpressionInfo ret ;
TQString contents = clearComments ( getText ( startLine , startCol , line , column ) ) ;
int start_expr = expressionAt ( contents , contents . length ( ) ) ;
if ( start_expr ! = int ( contents . length ( ) ) ) {
TQString str = contents . mid ( start_expr , contents . length ( ) - start_expr ) . stripWhiteSpace ( ) ;
if ( str . startsWith ( " new " ) ) {
str = str . mid ( 4 ) . stripWhiteSpace ( ) ;
}
ret . setExpr ( str ) ;
if ( ! ret . expr ( ) . isEmpty ( ) )
ret . t = ExpressionInfo : : NormalExpression ;
}
if ( ret ) {
///Check whether it may be a type-expression
bool mayBeType = true ;
TQString append ;
if ( ! mayBeTypeTail ( line , column - 1 , append , inFunction ) )
mayBeType = false ;
if ( mayBeType ) {
if ( ! canBeTypePrefix ( contents . left ( start_expr ) , inFunction ) )
mayBeType = false ;
}
//make this a regexp
TQString e = ret . expr ( ) ;
if ( e . contains ( " . " ) | | e . contains ( " -> " ) | | e . contains ( " ( " ) | | e . contains ( " ) " ) | | e . contains ( " = " ) | | e . contains ( " - " ) )
mayBeType = false ;
if ( mayBeType ) {
ret . setExpr ( ret . expr ( ) + append ) ;
ret . t = ExpressionInfo : : TypeExpression ;
}
}
return ret ;
}
void macrosToDriver ( Driver & d , FileDom file ) {
return ; //Deactivate this for now, because macros can cause inconsistency of line/column-numbers between processed text and the not-processed text of the buffer
ParseResultPointer p ;
if ( file )
p = file - > parseResult ( ) ;
ParsedFile * pf = dynamic_cast < ParsedFile * > ( p . data ( ) ) ;
if ( pf ) {
d . insertMacros ( pf - > usedMacros ( ) ) ; ///Add macros
}
}
SimpleContext * CppCodeCompletion : : computeFunctionContext ( FunctionDom f , int line , int col , SimpleTypeConfiguration & conf ) {
Q_UNUSED ( conf ) ;
if ( ! f )
return 0 ;
int modelStartLine , modelStartColumn ;
int modelEndLine , modelEndColumn ;
f - > getStartPosition ( & modelStartLine , & modelStartColumn ) ;
f - > getEndPosition ( & modelEndLine , & modelEndColumn ) ;
TQString textLine = m_activeEditor - > textLine ( modelStartLine ) ;
kdDebug ( 9007 ) < < " startLine = " < < textLine < < endl ;
TQString contents = getText ( modelStartLine , modelStartColumn , line , col ) ;
Driver d ;
Lexer lexer ( & d ) ;
macrosToDriver ( d , f - > file ( ) ) ;
lexer . setSource ( contents ) ;
Parser parser ( & d , & lexer ) ;
DeclarationAST : : Node recoveredDecl ;
RecoveryPoint * recoveryPoint = this - > d - > findRecoveryPoint ( line , col ) ; ///@todo recovery-points are not needed anymore
parser . parseDeclaration ( recoveredDecl ) ;
if ( recoveredDecl . get ( ) ) {
bool isFunDef = recoveredDecl - > nodeType ( ) = = NodeType_FunctionDefinition ;
kdDebug ( 9007 ) < < " is function definition= " < < isFunDef < < endl ;
int startLine , startColumn ;
int endLine , endColumn ;
recoveredDecl - > getStartPosition ( & startLine , & startColumn ) ;
recoveredDecl - > getEndPosition ( & endLine , & endColumn ) ;
/*if( startLine != modelStartLine || endLine != modelEndLine || startColumn != modelStartColumn || endColumn != modelEndColumn ) {
kdDebug ( 9007 ) < < " code-model and real file are out of sync \n function-bounds in code-model: " < < endl ;
kdDebug ( 9007 ) < < " (l " < < modelStartLine < < " , c " < < modelStartColumn < < " ) - (l " < < modelEndLine < < " , c " < < modelEndColumn < < " ) " < < " parsed function-bounds: " < < endl ;
kdDebug ( 9007 ) < < " (l " < < startLine < < " , c " < < startColumn < < " ) - (l " < < endLine < < " , c " < < endColumn < < " ) " < < endl ;
} */
if ( isFunDef ) {
FunctionDefinitionAST * def = static_cast < FunctionDefinitionAST * > ( recoveredDecl . get ( ) ) ;
SimpleContext * ctx = computeContext ( def , endLine , endColumn , modelStartLine , modelStartColumn ) ;
if ( ! ctx )
return 0 ;
TQStringList scope = f - > scope ( ) ;
if ( ! scope . isEmpty ( ) ) {
SimpleType parentType ;
/* if( !m_cachedFromContext ) {
TypePointer t = SimpleType ( TQStringList ( ) ) - > locateDecType ( scope . join ( " " ) ) . desc ( ) . resolved ( ) ; ;
if ( t )
parentType = SimpleType ( t . data ( ) ) ;
else
parentType = SimpleType ( scope ) ;
} else { */
parentType = SimpleType ( scope , getIncludeFiles ( ) ) ;
//}
parentType - > descForEdit ( ) . setTotalPointerDepth ( 1 ) ;
ctx - > setContainer ( parentType ) ;
}
SimpleType global = ctx - > global ( ) ;
if ( dynamic_cast < SimpleTypeNamespace * > ( & ( * global ) ) ) {
SimpleTypeNamespace * globalNs = static_cast < SimpleTypeNamespace * > ( & ( * global ) ) ;
TQValueList < TQPair < TQString , TQString > > localImports = ctx - > imports ( ) ;
for ( TQValueList < TQPair < TQString , TQString > > : : const_iterator it = localImports . begin ( ) ; it ! = localImports . end ( ) ; + + it )
globalNs - > addAliasMap ( ( * it ) . first , ( * it ) . second ) ;
}
/* //Should not be necessary any more
if ( ! getParsedFile ( f - > file ( ) . data ( ) ) | | getParsedFile ( f - > file ( ) . data ( ) ) - > includeFiles ( ) . size ( ) < = 1 ) {
if ( ! m_cachedFromContext ) {
conf . setGlobalNamespace ( & ( * global ) ) ;
if ( recoveryPoint ) {
recoveryPoint - > registerImports ( global , m_pSupport - > codeCompletionConfig ( ) - > namespaceAliases ( ) ) ;
} else {
kdDebug ( 9007 ) < < " no recovery-point, cannot use imports " < < endl ;
}
}
} */
///Insert the "this"-type(container) and correctly resolve it using imported namespaces
if ( ctx - > container ( ) ) {
if ( ! m_cachedFromContext ) {
TypeDesc td = ctx - > container ( ) - > desc ( ) ;
td . setIncludeFiles ( getIncludeFiles ( ) ) ;
td . makePrivate ( ) ;
td . resetResolved ( ) ;
TypePointer tt = ctx - > container ( ) - > locateDecType ( td , SimpleTypeImpl : : LocateBase ) - > resolved ( ) ;
if ( tt ) {
ctx - > setContainer ( SimpleType ( tt ) ) ;
} else {
kdDebug ( 9007 ) < < " could not resolve local this-type \" " < < td . fullNameChain ( ) < < " \" " < < endl ;
}
}
SimpleType this_type = ctx - > container ( ) ;
this_type - > descForEdit ( ) . setTotalPointerDepth ( 1 ) ;
SimpleVariable var ;
var . type = this_type - > desc ( ) ;
var . name = " this " ;
var . comment = this_type - > comment ( ) ;
ctx - > add
( var ) ;
ctx - > setContainer ( this_type ) ;
}
return ctx ;
} else {
kdDebug ( 9007 ) < < " computeFunctionContext: context is no function-definition " < < endl ;
}
} else {
kdDebug ( 9007 ) < < " computeFunctionContext: could not find a valid declaration to recover " < < endl ;
}
return 0 ;
}
bool CppCodeCompletion : : functionContains ( FunctionDom f , int line , int col ) {
if ( ! f )
return false ;
int sl , sc , el , ec ;
f - > getStartPosition ( & sl , & sc ) ;
f - > getEndPosition ( & el , & ec ) ;
TQString t = clearComments ( getText ( sl , sc , el , ec ) ) ;
if ( t . isEmpty ( ) )
return false ;
//int i = t.find( '{' );
int i = t . find ( ' ( ' ) ; //This now includes the argument-list
if ( i = = - 1 )
return false ;
int lineCols = 0 ;
for ( int a = 0 ; a < i ; a + + ) {
if ( t [ a ] = = ' \n ' ) {
sl + + ;
lineCols = 0 ;
} else {
lineCols + + ;
}
}
sc + = lineCols ;
return ( line > sl | | ( line = = sl & & col > = sc ) ) & & ( line < el | | ( line = = el & & col < ec ) ) ;
}
void CppCodeCompletion : : getFunctionBody ( FunctionDom f , int & line , int & col ) {
if ( ! f )
return ;
int sl , sc , el , ec ;
f - > getStartPosition ( & sl , & sc ) ;
f - > getEndPosition ( & el , & ec ) ;
TQString t = clearComments ( getText ( sl , sc , el , ec ) ) ;
if ( t . isEmpty ( ) )
return ;
int i = t . find ( ' { ' ) ;
if ( i = = - 1 )
return ;
i + + ;
if ( ( uint ) i > = t . length ( ) )
return ;
int lineCols = 0 ;
for ( int a = 0 ; a < i ; a + + ) {
if ( t [ a ] = = ' \n ' ) {
sl + + ;
lineCols = 0 ;
} else {
lineCols + + ;
}
}
sc + = lineCols ;
line = sl ;
col = sc ;
}
void CppCodeCompletion : : emptyCache ( ) {
m_cachedFromContext = 0 ;
SimpleTypeConfiguration c ; ///Will automatically destroy the type-store when the function is closed
kdDebug ( 9007 ) < < " completion-cache emptied " < < endl ;
}
void CppCodeCompletion : : needRecoveryPoints ( ) {
if ( this - > d - > recoveryPoints . isEmpty ( ) ) {
kdDebug ( 9007 ) < < " missing recovery-points for file " < < m_activeFileName < < " they have to be computed now " < < endl ;
m_pSupport - > backgroundParser ( ) - > lock ( )
;
std : : vector < CppCodeCompletion > vec ;
TranslationUnitAST * ast = * m_pSupport - > backgroundParser ( ) - > translationUnit ( m_activeFileName ) ;
m_pSupport - > backgroundParser ( ) - > unlock ( ) ;
if ( ! ast ) {
kdDebug ( 9007 ) < < " background-parser is missing the translation-unit. The file needs to be reparsed. " < < endl ;
m_pSupport - > parseFileAndDependencies ( m_activeFileName , true ) ;
// m_pSupport->mainWindow() ->statusBar() ->message( i18n( "Background-parser is missing the necessary translation-unit. It will be computed, but this completion will fail." ).arg( m_activeFileName ), 2000 );
return ;
} else {
computeRecoveryPointsLocked ( ) ;
}
if ( this - > d - > recoveryPoints . isEmpty ( ) ) {
kdDebug ( 9007 ) < < " Failed to compute recovery-points for " < < m_activeFileName < < endl ;
// m_pSupport->mainWindow() ->statusBar() ->message( i18n( "Failed to compute recovery-points for %1" ).arg( m_activeFileName ), 1000 );
} else {
kdDebug ( 9007 ) < < " successfully computed recovery-points for " < < m_activeFileName < < endl ;
}
}
}
EvaluationResult CppCodeCompletion : : evaluateExpressionType ( int line , int column , SimpleTypeConfiguration & conf , EvaluateExpressionOptions opt ) {
EvaluationResult ret ;
safetyCounter . init ( ) ;
FileDom file = m_pSupport - > codeModel ( ) - > fileByName ( m_activeFileName ) ;
if ( ! file ) {
// m_pSupport->mainWindow() ->statusBar() ->message( i18n( "File %1 does not exist in the code-model" ).arg( m_activeFileName ), 1000 );
kdDebug ( 9007 ) < < " Error: file " < < m_activeFileName < < " could not be located in the code-model, code-completion stopped \n " ;
return SimpleType ( ) ;
}
needRecoveryPoints ( ) ;
CodeModelUtils : : CodeModelHelper fileModel ( m_pSupport - > codeModel ( ) , file ) ;
ItemDom contextItem ;
int nLine = line , nCol = column ;
// emptyCache();
fitContextItem ( line , column ) ;
TQString strCurLine = m_activeEditor - > textLine ( nLine ) ;
TQString ch = strCurLine . mid ( nCol - 1 , 1 ) ;
TQString ch2 = strCurLine . mid ( nCol - 2 , 2 ) ;
while ( ch [ 0 ] . isSpace ( ) & & nCol > = 3 ) {
nCol - = 1 ;
ch = strCurLine . mid ( nCol - 1 , 1 ) ;
ch2 = strCurLine . mid ( nCol - 2 , 2 ) ;
}
if ( ch2 = = " -> " | | ch = = " . " | | ch = = " ( " ) {
int pos = ch2 = = " -> " ? nCol - 3 : nCol - 2 ;
TQChar c = strCurLine [ pos ] ;
while ( pos > 0 & & c . isSpace ( ) )
c = strCurLine [ - - pos ] ;
if ( ! ( c . isLetterOrNumber ( ) | | c = = ' _ ' | | c = = ' ) ' | | c = = ' ] ' | | c = = ' > ' ) ) {
conf . invalidate ( ) ;
return SimpleType ( ) ;
}
}
bool showArguments = false ;
if ( ch = = " ( " ) {
- - nCol ;
while ( nCol > 0 & & strCurLine [ nCol ] . isSpace ( ) )
- - nCol ;
showArguments = true ;
}
TQString word ;
{
ExpressionInfo exp_ = findExpressionAt ( line , column , line , 0 ) ;
if ( file - > parseResult ( ) ) {
ParsedFilePointer p = dynamic_cast < ParsedFile * > ( file - > parseResult ( ) . data ( ) ) ;
if ( p ) {
if ( p - > usedMacros ( ) . hasMacro ( exp_ . expr ( ) ) ) {
//It is a macro, return it
ret . expr = exp_ . expr ( ) ;
ret . isMacro = true ;
ret . macro = p - > usedMacros ( ) . macro ( exp_ . expr ( ) ) ;
return ret ;
}
}
}
}
if ( ! m_cachedFromContext )
conf . setGlobalNamespace ( createGlobalNamespace ( ) ) ;
ItemLocker < BackgroundParser > block ( * m_pSupport - > backgroundParser ( ) ) ;
FunctionDom currentFunction = fileModel . functionAt ( line , column ) ;
bool functionFailed = true ;
if ( opt & SearchInFunctions ) {
//currentFunction = fileModel.functionAt( line, column );
if ( currentFunction & & functionContains ( currentFunction , line , column ) ) {
///Evaluate the context of the function-body if we're in the argument-list
int realLine = line , realColumn = column ;
getFunctionBody ( currentFunction , realLine , realColumn ) ;
if ( realLine < line | | ( realLine = = line & & realColumn < column ) ) {
realLine = line ;
realColumn = column ;
}
SimpleContext * ctx = computeFunctionContext ( currentFunction , realLine , realColumn , conf ) ;
contextItem = currentFunction . data ( ) ;
if ( ctx ) {
opt = remFlag ( opt , SearchInClasses ) ;
int startLine , endLine ;
currentFunction - > getStartPosition ( & startLine , & endLine ) ;
ExpressionInfo exp = findExpressionAt ( line , column , startLine , endLine , true ) ;
if ( ( opt & DefaultAsTypeExpression ) & & ( ! exp . canBeNormalExpression ( ) & & ! exp . canBeTypeExpression ( ) ) & & ! exp . expr ( ) . isEmpty ( ) )
exp . t = ExpressionInfo : : TypeExpression ;
if ( exp . canBeTypeExpression ( ) ) {
{
if ( ! ( opt & IncludeTypeExpression ) ) {
kdDebug ( 9007 ) < < " recognized a type-expression, but another expression-type is desired " < < endl ;
} else {
TypeDesc d ( exp . expr ( ) ) ;
d . setIncludeFiles ( getIncludeFiles ( ) ) ;
ret . resultType = ctx - > container ( ) - > locateDecType ( d ) ;
ret . expr = exp ;
}
}
}
if ( /*exp.canBeNormalExpression() &&*/ ! ret . resultType - > resolved ( ) ) { ///It is not cleary possible to recognize the kind of an expression from the syntax as long as it's not written completely
{
if ( ! ( opt & IncludeStandardExpressions ) ) {
kdDebug ( 9007 ) < < " recognized a standard-expression, but another expression-type is desired " < < endl ;
} else {
///Remove the not completely typed last word while normal completion
if ( ! showArguments & & ( opt & CompletionOption ) ) {
TQString e = exp . expr ( ) ;
int idx = e . length ( ) - 1 ;
while ( e [ idx ] . isLetterOrNumber ( ) | | e [ idx ] = = ' _ ' )
- - idx ;
if ( idx ! = int ( e . length ( ) ) - 1 ) {
+ + idx ;
word = e . mid ( idx ) . stripWhiteSpace ( ) ;
exp . setExpr ( e . left ( idx ) . stripWhiteSpace ( ) ) ;
}
}
functionFailed = false ;
ret = evaluateExpression ( exp , ctx ) ;
}
}
}
} else {
kdDebug ( 9007 ) < < " could not compute context " < < endl ;
}
if ( ctx )
delete ctx ;
} else {
kdDebug ( 9007 ) < < " could not find context-function in code-model " < < endl ;
}
}
if ( ( opt & SearchInClasses ) & & ! ret - > resolved ( ) & & functionFailed ) {
ClassDom currentClass = fileModel . classAt ( line , column ) ;
int startLine = 0 , startCol = 0 ;
RecoveryPoint * recoveryPoint = this - > d - > findRecoveryPoint ( line , column ) ;
TQStringList scope ;
if ( ! currentClass ) {
kdDebug ( 9007 ) < < " no container-class found " < < endl ;
if ( ! recoveryPoint ) {
kdDebug ( 9007 ) < < " no recovery-point found " < < endl ;
} else {
startLine = recoveryPoint - > startLine ;
startCol = recoveryPoint - > startColumn ;
scope = recoveryPoint - > scope ;
}
} else {
contextItem = currentClass . data ( ) ;
scope = currentClass - > scope ( ) ;
scope < < currentClass - > name ( ) ;
currentClass - > getStartPosition ( & startLine , & startCol ) ;
}
SimpleType container ;
if ( m_cachedFromContext ) {
TypeDesc d ( scope . join ( " :: " ) ) ;
d . setIncludeFiles ( getIncludeFiles ( ) ) ;
SimpleTypeImpl * i = SimpleType ( TQStringList ( ) , getIncludeFiles ( ) ) - > locateDecType ( d ) . desc ( ) . resolved ( ) . data ( ) ;
if ( i )
container = i ;
else
container = SimpleType ( scope , getIncludeFiles ( ) ) ;
} else {
container = SimpleType ( scope , getIncludeFiles ( ) ) ;
}
ExpressionInfo exp = findExpressionAt ( line , column , startLine , startCol ) ;
exp . t = ExpressionInfo : : TypeExpression ; ///Outside of functions, we can only handle type-expressions
ret . expr = exp ;
if ( exp & & ( exp . t & ExpressionInfo : : TypeExpression ) ) {
kdDebug ( 9007 ) < < " locating \" " < < exp . expr ( ) < < " \" in " < < container - > fullTypeResolvedWithScope ( ) < < endl ;
TypeDesc d ( exp . expr ( ) ) ;
d . setIncludeFiles ( getIncludeFiles ( ) ) ;
ret . resultType = container - > locateDecType ( d ) ;
} else {
if ( exp ) {
kdDebug ( 9007 ) < < " wrong expression-type recognized " < < endl ;
} else {
kdDebug ( 9007 ) < < " expression could not be recognized " < < endl ;
}
}
}
CppCodeCompletionConfig * cfg = m_pSupport - > codeCompletionConfig ( ) ;
if ( cfg - > usePermanentCaching ( ) & & contextItem ) {
conf . invalidate ( ) ;
m_cachedFromContext = contextItem ;
}
return ret ;
}
bool isAfterKeyword ( const TQString & str , int column ) {
TQStringList keywords ;
keywords < < " new " ;
keywords < < " throw " ;
keywords < < " return " ;
keywords < < " emit " ; ///This could be done even better by only showing signals for completion..
for ( TQStringList : : iterator it = keywords . begin ( ) ; it ! = keywords . end ( ) ; + + it ) {
int len = ( * it ) . length ( ) ;
if ( column > = len & & str . mid ( column - len , len ) = = * it )
return true ;
}
return false ;
}
void CppCodeCompletion : : setMaxComments ( int count ) {
m_maxComments = count ;
}
///TODO: make this use findExpressionAt etc. (like the other expression-evaluation-stuff)
void CppCodeCompletion : : completeText ( bool invokedOnDemand /*= false*/ ) {
kdDebug ( 9007 ) < < " CppCodeCompletion::completeText() " < < endl ;
clearStatusText ( ) ;
if ( ! m_pSupport | | ! m_activeCursor | | ! m_activeEditor | | ! m_activeCompletion )
return ;
setMaxComments ( 1000 ) ;
needRecoveryPoints ( ) ;
CppCodeCompletionConfig * cfg = m_pSupport - > codeCompletionConfig ( ) ;
m_demandCompletion = invokedOnDemand ;
FileDom file = m_pSupport - > codeModel ( ) - > fileByName ( m_activeFileName ) ;
if ( ! file ) {
// m_pSupport->mainWindow() ->statusBar() ->message( i18n( "File %1 does not exist in the code-model" ).arg( m_activeFileName ), 1000 );
kdDebug ( 9007 ) < < " Error: file " < < m_activeFileName < < " could not be located in the code-model, code-completion stopped \n " ;
return ;
}
CodeModelUtils : : CodeModelHelper fileModel ( m_pSupport - > codeModel ( ) , file ) ;
ItemDom contextItem ;
unsigned int line , column ;
m_activeCursor - > cursorPositionReal ( & line , & column ) ;
fitContextItem ( line , column ) ;
///Check whether the cursor is within a comment
int surroundingStartLine = line - 10 , surroundingEndLine = line + 10 ;
if ( surroundingStartLine < 0 )
surroundingStartLine = 0 ;
if ( surroundingEndLine > m_activeEditor - > numLines ( ) - 1 )
surroundingEndLine = m_activeEditor - > numLines ( ) - 1 ;
int surroundingEndCol = m_activeEditor - > lineLength ( surroundingEndLine ) ;
TQString pre = getText ( surroundingStartLine , 0 , line , column ) ;
int pos = pre . length ( ) ;
pre + = getText ( line , column , surroundingEndLine , surroundingEndCol ) ;
TQString cleared = clearComments ( pre ) ;
if ( cleared [ pos ] ! = pre [ pos ] ) {
kdDebug ( 9007 ) < < " stopping completion because we're in a coment " < < endl ;
return ;
}
int nLine = line , nCol = column ;
TQString strCurLine = clearComments ( m_activeEditor - > textLine ( nLine ) ) ;
TQString ch = strCurLine . mid ( nCol - 1 , 1 ) ;
TQString ch2 = strCurLine . mid ( nCol - 2 , 2 ) ;
while ( ch [ 0 ] . isSpace ( ) & & nCol > = 3 ) {
nCol - = 1 ;
ch = strCurLine . mid ( nCol - 1 , 1 ) ;
ch2 = strCurLine . mid ( nCol - 2 , 2 ) ;
}
if ( m_includeRx . search ( strCurLine ) ! = - 1 ) {
if ( ! m_fileEntryList . isEmpty ( ) ) {
m_bCompletionBoxShow = true ;
m_activeCompletion - > showCompletionBox ( m_fileEntryList , column - m_includeRx . matchedLength ( ) ) ;
}
return ;
}
bool showArguments = false ;
bool isInstance = true ;
m_completionMode = NormalCompletion ;
if ( ch2 = = " -> " | | ch = = " . " | | ch = = " ( " ) {
int pos = ch2 = = " -> " ? nCol - 3 : nCol - 2 ;
TQChar c = strCurLine [ pos ] ;
while ( pos > 0 & & c . isSpace ( ) )
c = strCurLine [ - - pos ] ;
if ( ! ( c . isLetterOrNumber ( ) | | c = = ' _ ' | | c = = ' ) ' | | c = = ' ] ' | | c = = ' > ' ) )
return ;
}
if ( ch = = " ( " ) {
- - nCol ;
while ( nCol > 0 & & strCurLine [ nCol - 1 ] . isSpace ( ) )
- - nCol ;
///check whether it is a value-definition using constructor
int column = nCol ;
bool s1 = false , s2 = false ;
while ( column > 0 & & isValidIdentifierSign ( strCurLine [ column - 1 ] ) ) {
column - - ;
s1 = true ;
}
///skip white space
while ( column > 0 & & strCurLine [ column - 1 ] . isSpace ( ) ) {
- - column ;
s2 = true ;
}
if ( s1 & & s2 & & isValidIdentifierSign ( strCurLine [ column - 1 ] ) ) {
if ( isAfterKeyword ( strCurLine , column ) ) {
///Maybe a constructor using "new", or "throw", "return", ...
} else {
///it is a local constructor like "TQString name("David");"
nCol = column ;
}
}
showArguments = TRUE ;
}
EvaluationResult type ;
SimpleType this_type ;
TQString expr , word ;
DeclarationAST : : Node recoveredDecl ;
TypeSpecifierAST : : Node recoveredTypeSpec ;
SimpleContext * ctx = 0 ;
SimpleTypeConfiguration conf ( m_activeFileName ) ;
if ( ! m_cachedFromContext )
conf . setGlobalNamespace ( createGlobalNamespace ( ) ) ;
ItemLocker < BackgroundParser > block ( * m_pSupport - > backgroundParser ( ) ) ;
FunctionDom currentFunction = fileModel . functionAt ( line , column ) ;
RecoveryPoint * recoveryPoint = d - > findRecoveryPoint ( line , column ) ;
if ( recoveryPoint | | currentFunction ) {
contextItem = currentFunction . data ( ) ;
TQStringList scope ;
int startLine , startColumn ;
if ( currentFunction ) { ///maybe change the priority of these
kdDebug ( 9007 ) < < " using code-model for completion " < < endl ;
currentFunction - > getStartPosition ( & startLine , & startColumn ) ;
scope = currentFunction - > scope ( ) ;
} else {
kdDebug ( 9007 ) < < " recovery-point, node-kind = " < < nodeTypeToString ( recoveryPoint - > kind ) < < endl ;
startLine = recoveryPoint - > startLine ;
startColumn = recoveryPoint - > startColumn ;
scope = recoveryPoint - > scope ;
}
TQString textLine = m_activeEditor - > textLine ( startLine ) ;
kdDebug ( 9007 ) < < " startLine = " < < textLine < < endl ;
if ( currentFunction | | recoveryPoint - > kind = = NodeType_FunctionDefinition ) {
TQString textToReparse = clearComments ( getText ( startLine , startColumn , line , showArguments ? nCol : column ) ) ;
kdDebug ( 9007 ) < < " -------------> reparse text " < < endl < < textToReparse < < endl
< < " -------------------------------------------- " < < endl ;
Driver d ;
Lexer lexer ( & d ) ;
macrosToDriver ( d , file ) ;
lexer . setSource ( textToReparse ) ;
Parser parser ( & d , & lexer ) ;
parser . parseDeclaration ( recoveredDecl ) ;
/* kdDebug(9007) << "recoveredDecl = " << recoveredDecl.get() << endl;*/
if ( recoveredDecl . get ( ) ) {
bool isFunDef = recoveredDecl - > nodeType ( ) = = NodeType_FunctionDefinition ;
kdDebug ( 9007 ) < < " is function definition= " < < isFunDef < < endl ;
int endLine , endColumn ;
recoveredDecl - > getEndPosition ( & endLine , & endColumn ) ;
kdDebug ( 9007 ) < < " endLine = " < < endLine < < " , endColumn " < < endColumn < < endl ;
/// @todo check end position
if ( isFunDef ) {
FunctionDefinitionAST * def = static_cast < FunctionDefinitionAST * > ( recoveredDecl . get ( ) ) ;
/// @todo remove code duplication
TQString contents = textToReparse ;
int start_expr = expressionAt ( contents , contents . length ( ) ) ;
// kdDebug(9007) << "start_expr = " << start_expr << endl;
if ( start_expr ! = int ( contents . length ( ) ) )
expr = contents . mid ( start_expr , contents . length ( ) - start_expr ) . stripWhiteSpace ( ) ;
if ( expr . startsWith ( " SIGNAL " ) | | expr . startsWith ( " SLOT " ) ) {
m_completionMode = expr . startsWith ( " SIGNAL " ) ? SignalCompletion : SlotCompletion ;
showArguments = false ;
int end_expr = start_expr - 1 ;
while ( end_expr > 0 & & contents [ end_expr ] . isSpace ( ) )
- - end_expr ;
if ( contents [ end_expr ] ! = ' , ' ) {
expr = TQString ( ) ;
} else {
start_expr = expressionAt ( contents , end_expr ) ;
expr = contents . mid ( start_expr , end_expr - start_expr ) . stripWhiteSpace ( ) ;
}
} else {
if ( ! showArguments ) {
int idx = expr . length ( ) - 1 ;
while ( expr [ idx ] . isLetterOrNumber ( ) | | expr [ idx ] = = ' _ ' )
- - idx ;
if ( idx ! = int ( expr . length ( ) ) - 1 ) {
+ + idx ;
word = expr . mid ( idx ) . stripWhiteSpace ( ) ;
expr = expr . left ( idx ) . stripWhiteSpace ( ) ;
}
}
}
ctx = computeContext ( def , endLine , endColumn , startLine , startColumn ) ;
DeclaratorAST * d = def - > initDeclarator ( ) - > declarator ( ) ;
NameAST * name = d - > declaratorId ( ) ;
TQStringList nested ;
TQPtrList < ClassOrNamespaceNameAST > l ;
if ( name ) {
l = name - > classOrNamespaceNameList ( ) ;
}
// TQPtrList<ClassOrNamespaceNameAST> l = name->classOrNamespaceNameList();
TQPtrListIterator < ClassOrNamespaceNameAST > nameIt ( l ) ;
while ( nameIt . current ( ) ) {
if ( nameIt . current ( ) - > name ( ) ) {
nested < < nameIt . current ( ) - > name ( ) - > text ( ) ;
}
+ + nameIt ;
}
if ( currentFunction ) {
scope = currentFunction - > scope ( ) ;
if ( ! scope . isEmpty ( ) ) {
//scope.pop_back();
} else {
kdDebug ( 9007 ) < < " scope is empty " < < endl ;
}
if ( dynamic_cast < SimpleTypeNamespace * > ( SimpleType : : globalNamespace ( ) . data ( ) ) ) {
SimpleTypeNamespace * globalNs = static_cast < SimpleTypeNamespace * > ( SimpleType : : globalNamespace ( ) . data ( ) ) ;
TQValueList < TQPair < TQString , TQString > > localImports = ctx - > imports ( ) ;
for ( TQValueList < TQPair < TQString , TQString > > : : const_iterator it = localImports . begin ( ) ; it ! = localImports . end ( ) ; + + it )
globalNs - > addAliasMap ( ( * it ) . first , ( * it ) . second ) ;
}
} else {
scope + = nested ;
}
if ( ! scope . isEmpty ( ) ) {
SimpleType parentType ;
/*if( !m_cachedFromContext ) {
TypePointer t = createGlobalNamespace ( ) ;
conf . setGlobalNamespace ( t ) ;
SimpleTypeNamespace * n = dynamic_cast < SimpleTypeNamespace * > ( t . data ( ) ) ;
if ( ! n ) {
TQString str = TQString ( " the global namespace was not resolved correctly , real type: " ) + typeid ( n ) . name ( ) + TQString ( " name: " ) + n - > scope ( ) . join ( " :: " ) + " scope-size: " + n - > scope ( ) . count ( ) ;
kdDebug ( 9007 ) < < str < < endl ;
m_pSupport - > mainWindow ( ) - > statusBar ( ) - > message ( str , 1000 ) ;
} else {
}
this_type = SimpleType ( t ) ;
} */
if ( m_cachedFromContext ) {
TypeDesc d ( scope . join ( " :: " ) ) ;
d . setIncludeFiles ( getIncludeFiles ( ) ) ;
SimpleTypeImpl * i = SimpleType ( TQStringList ( ) , getIncludeFiles ( ) ) - > locateDecType ( d ) . desc ( ) . resolved ( ) . data ( ) ;
if ( i ) {
parentType = i ;
} else {
parentType = SimpleType ( scope , getIncludeFiles ( ) ) ;
}
} else {
parentType = SimpleType ( scope , getIncludeFiles ( ) ) ;
}
this_type = parentType ;
this_type - > descForEdit ( ) . setTotalPointerDepth ( 1 ) ;
ctx - > setContainer ( this_type ) ;
}
///Now locate the local type using the imported namespaces
if ( ! scope . isEmpty ( ) ) {
if ( ! m_cachedFromContext ) {
TypeDesc td = ctx - > container ( ) - > desc ( ) ;
td . makePrivate ( ) ;
td . resetResolved ( ) ;
td . setIncludeFiles ( getIncludeFiles ( ) ) ;
TypePointer tt = ctx - > container ( ) - > locateDecType ( td , SimpleTypeImpl : : LocateBase ) - > resolved ( ) ;
if ( tt ) {
ctx - > setContainer ( SimpleType ( tt ) ) ;
} else {
kdDebug ( 9007 ) < < " could not resolve local this-type \" " < < td . fullNameChain ( ) < < " \" " < < endl ;
}
}
SimpleType this_type = ctx - > container ( ) ;
this_type - > descForEdit ( ) . setTotalPointerDepth ( 1 ) ;
SimpleVariable var ;
var . type = this_type - > desc ( ) ;
var . name = " this " ;
var . comment = this_type - > comment ( ) ;
ctx - > add
( var ) ;
ctx - > setContainer ( this_type ) ;
}
ExpressionInfo exp ( expr ) ;
exp . t = ( ExpressionInfo : : Type ) ( ExpressionInfo : : NormalExpression | ExpressionInfo : : TypeExpression ) ;
type = evaluateExpression ( exp , ctx ) ;
}
} else {
kdDebug ( 9007 ) < < " no valid declaration to recover!!! " < < endl ;
}
} else if ( recoveryPoint - > kind = = NodeType_ClassSpecifier ) {
TQString textToReparse = getText ( recoveryPoint - > startLine , recoveryPoint - > startColumn ,
recoveryPoint - > endLine , recoveryPoint - > endColumn , line ) ;
// kdDebug(9007) << "-------------> please reparse only text" << endl << textToReparse << endl
// << "--------------------------------------------" << endl;
Driver d ;
Lexer lexer ( & d ) ;
macrosToDriver ( d , file ) ;
lexer . setSource ( textToReparse ) ;
Parser parser ( & d , & lexer ) ;
parser . parseClassSpecifier ( recoveredTypeSpec ) ;
/* kdDebug(9007) << "recoveredDecl = " << recoveredTypeSpec.get() << endl;*/
if ( recoveredTypeSpec . get ( ) ) {
//ClassSpecifierAST * clazz = static_cast<ClassSpecifierAST*>( recoveredTypeSpec.get() );
TQString keyword = getText ( line , 0 , line , column ) . simplifyWhiteSpace ( ) ;
kdDebug ( 9007 ) < < " ===========================> keyword is: " < < keyword < < endl ;
if ( keyword = = " virtual " ) { /*
BaseClauseAST * baseClause = clazz - > baseClause ( ) ;
if ( baseClause )
{
TQPtrList < BaseSpecifierAST > baseList = baseClause - > baseSpecifierList ( ) ;
TQPtrList < BaseSpecifierAST > : : iterator it = baseList . begin ( ) ;
for ( ; it ! = baseList . end ( ) ; + + it )
type . append ( ( * it ) - > name ( ) - > text ( ) ) ;
ctx = new SimpleContext ( ) ;
showArguments = false ;
m_completionMode = VirtualDeclCompletion ;
kdDebug ( 9007 ) < < " ------> found virtual keyword for class specifier ' "
< < clazz - > text ( ) < < " ' " < < endl ;
} */
} else if ( TQString ( " virtual " ) . find ( keyword ) ! = - 1 )
m_blockForKeyword = true ;
else
m_blockForKeyword = false ;
}
}
}
///@todo is all this necessary?
if ( ! recoveredDecl . get ( ) & & ! recoveredTypeSpec . get ( ) ) {
TranslationUnitAST * ast = * m_pSupport - > backgroundParser ( ) - > translationUnit ( m_activeFileName ) ;
if ( AST * node = findNodeAt ( ast , line , column ) ) {
kdDebug ( 9007 ) < < " ------------------- AST FOUND -------------------- " < < endl ;
kdDebug ( 9007 ) < < " node-kind = " < < nodeTypeToString ( node - > nodeType ( ) ) < < endl ;
if ( FunctionDefinitionAST * def = functionDefinition ( node ) ) {
kdDebug ( 9007 ) < < " ------> found a function definition " < < endl ;
int startLine , startColumn ;
def - > getStartPosition ( & startLine , & startColumn ) ;
TQString contents = getText ( startLine , startColumn , line , showArguments ? nCol : column ) ;
/// @todo remove code duplication
int start_expr = expressionAt ( contents , contents . length ( ) ) ;
// kdDebug(9007) << "start_expr = " << start_expr << endl;
if ( start_expr ! = int ( contents . length ( ) ) )
expr = contents . mid ( start_expr , contents . length ( ) - start_expr ) . stripWhiteSpace ( ) ;
if ( expr . startsWith ( " SIGNAL " ) | | expr . startsWith ( " SLOT " ) ) {
m_completionMode = expr . startsWith ( " SIGNAL " ) ? SignalCompletion : SlotCompletion ;
showArguments = false ;
int end_expr = start_expr - 1 ;
while ( end_expr > 0 & & contents [ end_expr ] . isSpace ( ) )
- - end_expr ;
if ( contents [ end_expr ] ! = ' , ' ) {
expr = TQString ( ) ;
} else {
start_expr = expressionAt ( contents , end_expr ) ;
expr = contents . mid ( start_expr , end_expr - start_expr ) . stripWhiteSpace ( ) ;
}
} else {
int idx = expr . length ( ) - 1 ;
while ( expr [ idx ] . isLetterOrNumber ( ) | | expr [ idx ] = = ' _ ' )
- - idx ;
if ( idx ! = int ( expr . length ( ) ) - 1 ) {
+ + idx ;
word = expr . mid ( idx ) . stripWhiteSpace ( ) ;
expr = expr . left ( idx ) . stripWhiteSpace ( ) ;
}
}
ctx = computeContext ( def , line , column , startLine , startColumn ) ;
TQStringList scope ;
scopeOfNode ( def , scope ) ;
this_type = SimpleType ( scope , getIncludeFiles ( ) ) ;
if ( scope . size ( ) ) { /*
SimpleVariable var ;
var . type = scope ;
var . name = " this " ;
ctx - > add ( var ) ; */
//kdDebug(9007) << "add variable " << var.name << " with type " << var.type << endl;
}
ExpressionInfo exp ( expr ) ;
exp . t = ( ExpressionInfo : : Type ) ( ExpressionInfo : : NormalExpression | ExpressionInfo : : TypeExpression ) ;
type = evaluateExpression ( exp , ctx ) ;
}
}
}
if ( ! ctx )
return ;
if ( ch2 = = " :: " ) {
TQString str = clearComments ( expr ) ;
if ( ! str . contains ( ' . ' ) & & ! str . contains ( " -> " ) ) ///Necessary, because the expression may also be like user->BaseUser::
isInstance = false ;
}
TQString resolutionType = " (resolved) " ;
if ( ! type - > resolved ( ) ) {
if ( BuiltinTypes : : isBuiltin ( type . resultType ) ) {
resolutionType = " (builtin " + BuiltinTypes : : comment ( type . resultType ) + " ) " ;
} else {
resolutionType = " (unresolved) " ;
}
}
kdDebug ( 9007 ) < < " ===========================> type is: " < < type - > fullNameChain ( ) < < resolutionType < < endl ;
kdDebug ( 9007 ) < < " ===========================> word is: " < < word < < endl ;
if ( ! showArguments ) {
TQValueList < CodeCompletionEntry > entryList ;
if ( ! type & & this_type & & ( expr . isEmpty ( ) | | expr . endsWith ( " ; " ) ) ) {
bool alwaysIncludeNamespaces = cfg - > alwaysIncludeNamespaces ( ) ;
{
SimpleType t = this_type ;
///First, all static data.
bool ready = false ;
SafetyCounter cnt ( 20 ) ;
int depth = 0 ;
while ( ! ready & cnt ) {
if ( t - > scope ( ) . isEmpty ( ) ) {
ready = true ;
}
if ( ! t - > isNamespace ( ) | | invokedOnDemand | | alwaysIncludeNamespaces )
computeCompletionEntryList ( t , entryList , t - > scope ( ) , false , depth ) ;
t = t - > parent ( ) ;
depth + + ;
}
}
{
SimpleType t = this_type ;
///Now find non-static(if we have an instance) and global data
bool ready = false ;
SafetyCounter cnt ( 20 ) ;
int depth = 0 ;
bool first = true ;
while ( ! ready & cnt ) {
if ( t - > scope ( ) . isEmpty ( ) ) {
ready = true ;
}
if ( ( ( t - > isNamespace ( ) & & invokedOnDemand ) | | alwaysIncludeNamespaces ) | | ( first & & isInstance ) )
computeCompletionEntryList ( t , entryList , t - > scope ( ) , t - > isNamespace ( ) ? true : isInstance , depth ) ;
t = t - > parent ( ) ;
depth + + ;
first = false ;
}
}
if ( ctx ) computeCompletionEntryList ( entryList , ctx , isInstance ) ;
} else if ( type - > resolved ( ) & & expr . isEmpty ( ) ) {
if ( ctx ) computeCompletionEntryList ( entryList , ctx , isInstance ) ;
// if ( m_pSupport->codeCompletionConfig() ->includeGlobalFunctions() )
// computeCompletionEntryList( type, entryList, TQStringList(), false );
computeCompletionEntryList ( type , entryList , TQStringList ( ) , false ) ;
if ( this_type . scope ( ) . size ( ) )
computeCompletionEntryList ( this_type , entryList , this_type . scope ( ) , isInstance ) ;
computeCompletionEntryList ( type , entryList , type - > resolved ( ) - > scope ( ) , isInstance ) ;
} else if ( type - > resolved ( ) ) {
if ( type - > resolved ( ) )
computeCompletionEntryList ( type , entryList , type - > resolved ( ) - > scope ( ) , isInstance ) ;
}
TQStringList trueMatches ;
if ( invokedOnDemand ) {
// find matching words
TQValueList < CodeCompletionEntry > : : Iterator it ;
for ( it = entryList . begin ( ) ; it ! = entryList . end ( ) ; + + it ) {
if ( ( * it ) . text . startsWith ( word ) ) {
trueMatches < < ( * it ) . text ;
// if more than one entry matches, abort immediately
if ( trueMatches . size ( ) > 1 )
break ;
}
}
}
if ( invokedOnDemand & & trueMatches . size ( ) = = 1 ) {
// erbsland: get the cursor position now, because m_ccLine and m_ccColumn
// are not set until the first typed char.
unsigned int nLine , nCol ;
m_activeCursor - > cursorPositionReal ( & nLine , & nCol ) ;
// there is only one entry -> complete immediately
m_activeEditor - > insertText ( nLine , nCol ,
trueMatches [ 0 ] . right ( trueMatches [ 0 ] . length ( ) - word . length ( ) ) ) ;
} else if ( entryList . size ( ) ) {
entryList = unique ( entryList ) ;
qHeapSort ( entryList ) ;
m_bCompletionBoxShow = true ;
///Warning: the conversion is only possible because CodeCompletionEntry is binary compatible with KTextEditor::CompletionEntry,
///never change that!
m_activeCompletion - > showCompletionBox ( * ( ( TQValueList < KTextEditor : : CompletionEntry > * ) ( & entryList ) ) , word . length ( ) ) ;
}
} else {
TQValueList < TQStringList > signatureList ;
signatureList = computeSignatureList ( type ) ;
TQString methodName = type - > name ( ) ;
///Search for variables with ()-operator in the context
if ( ctx ) {
SimpleVariable var = ctx - > findVariable ( methodName ) ;
if ( ! var . name . isEmpty ( ) ) {
signatureList + = computeSignatureList ( ctx - > container ( ) - > locateDecType ( var . type ) ) ;
}
}
///search for fitting methods/classes in the current context
SimpleType t = this_type ;
bool ready = false ;
SafetyCounter s ( 20 ) ;
do {
if ( ! t )
ready = true ;
TypeDesc d ( methodName ) ;
d . setIncludeFiles ( getIncludeFiles ( ) ) ;
SimpleType method = t - > typeOf ( d ) ;
if ( method )
signatureList + = computeSignatureList ( method ) ;
if ( t )
t = t - > parent ( ) ;
} while ( ! ready & & s ) ;
if ( ! signatureList . isEmpty ( ) ) {
//signatureList = unique( signatureList );
//qHeapSort( signatureList );
m_bArgHintShow = true ;
m_activeCompletion - > showArgHint ( unique ( signatureList ) , " () " , " , " ) ;
}
}
delete ( ctx ) ;
ctx = 0 ;
if ( cfg - > usePermanentCaching ( ) ) {
conf . invalidate ( ) ;
m_cachedFromContext = contextItem ;
}
}
TQValueList < TQStringList > CppCodeCompletion : : computeSignatureList ( EvaluationResult result ) {
SimpleType type = result ;
if ( result . expr . t = = ExpressionInfo : : TypeExpression ) {
TypeDesc d ( result - > name ( ) ) ;
d . setIncludeFiles ( getIncludeFiles ( ) ) ;
type = type - > typeOf ( d , SimpleTypeImpl : : MemberInfo : : Function ) ; ///Compute the signature of the constructor
}
TQValueList < TQStringList > retList ;
SimpleTypeFunctionInterface * f = type - > asFunction ( ) ;
SimpleType currType = type ;
if ( ! f & & ! type - > isNamespace ( ) ) {
SimpleType t = type - > typeOf ( TypeDesc ( " operator ( ) " ) , SimpleTypeImpl : : MemberInfo : : Function ) ;
if ( t ) {
f = t - > asFunction ( ) ;
currType = t ;
}
}
while ( f ) {
TQStringList lst ;
TQString sig = buildSignature ( currType . get ( ) ) ;
TQString comment = currType - > comment ( ) ;
TQStringList commentList ;
if ( m_pSupport - > codeCompletionConfig ( ) - > showCommentWithArgumentHint ( ) ) {
if ( ! comment . isEmpty ( ) ) {
if ( sig . length ( ) + comment . length ( ) < 130 ) {
sig + = " : \" " + currType - > comment ( ) + " \" " ;
} else {
commentList = formatComment ( comment ) ;
}
}
}
lst < < sig ;
lst + = commentList ;
currType = f - > nextFunction ( ) ;
///Maybe try to apply implicit template-params in this place
retList < < lst ;
f = currType - > asFunction ( ) ;
}
return retList ;
}
void CppCodeCompletion : : synchronousParseReady ( const TQString & file , ParsedFilePointer unit ) {
if ( file = = m_activeFileName ) {
computeRecoveryPoints ( unit ) ;
}
}
void CppCodeCompletion : : slotCodeModelUpdated ( const TQString & fileName ) {
if ( fileName ! = m_activeFileName | | ! m_pSupport | | ! m_activeEditor )
return ;
// m_pSupport->mainWindow() ->statusBar() ->message( i18n( "Current file updated %1" ).arg( m_activeFileName ), 1000 );
computeRecoveryPointsLocked ( ) ;
}
void CppCodeCompletion : : slotFileParsed ( const TQString & fileName ) {
if ( fileName ! = m_activeFileName | | ! m_pSupport | | ! m_activeEditor )
return ;
// m_pSupport->mainWindow() ->statusBar() ->message( i18n( "Current file parsed %1 (cache emptied)" ).arg( m_activeFileName ), 1000 );
emptyCache ( ) ; ///The cache has to be emptied, because the code-model changed. @todo Better: Only refresh the code-model(tell all code-model-types to refresh themselves on demand)
computeRecoveryPointsLocked ( ) ;
}
void CppCodeCompletion : : setupCodeInformationRepository ( ) { }
SimpleContext * CppCodeCompletion : : computeContext ( FunctionDefinitionAST * ast , int line , int col , int lineOffset , int colOffset ) {
kdDebug ( 9007 ) < < " CppCodeCompletion::computeContext() -- main " < < endl ;
SimpleContext * ctx = new SimpleContext ( ) ;
if ( ast & & ast - > initDeclarator ( ) & & ast - > initDeclarator ( ) - > declarator ( ) ) {
DeclaratorAST * d = ast - > initDeclarator ( ) - > declarator ( ) ;
if ( ParameterDeclarationClauseAST * clause = d - > parameterDeclarationClause ( ) ) {
if ( ParameterDeclarationListAST * params = clause - > parameterDeclarationList ( ) ) {
TQPtrList < ParameterDeclarationAST > l ( params - > parameterList ( ) ) ;
TQPtrListIterator < ParameterDeclarationAST > it ( l ) ;
while ( it . current ( ) ) {
ParameterDeclarationAST * param = it . current ( ) ;
+ + it ;
SimpleVariable var ;
TQStringList ptrList ;
TQPtrList < AST > ptrOpList = param - > declarator ( ) - > ptrOpList ( ) ;
TQPtrList < AST > : : iterator it = ptrOpList . begin ( ) ;
for ( ; it ! = ptrOpList . end ( ) ; + + it ) {
ptrList . append ( ( * it ) - > text ( ) ) ;
}
var . ptrList = ptrList ;
var . type = param - > typeSpec ( ) - > text ( ) + ptrList . join ( " " ) ;
var . name = declaratorToString ( param - > declarator ( ) , TQString ( ) , true ) ;
var . comment = param - > comment ( ) ;
param - > getStartPosition ( & var . startLine , & var . startCol ) ;
param - > getEndPosition ( & var . endLine , & var . endCol ) ;
if ( var . type ) {
ctx - > add
( var ) ;
//kdDebug(9007) << "add argument " << var.name << " with type " << var.type << endl;
}
}
}
}
}
if ( ast )
computeContext ( ctx , ast - > functionBody ( ) , line , col ) ;
if ( ctx ) {
ctx - > offset ( lineOffset , colOffset ) ;
}
return ctx ;
}
void CppCodeCompletion : : computeContext ( SimpleContext * & ctx , StatementAST * stmt , int line , int col ) {
if ( ! stmt )
return ;
switch ( stmt - > nodeType ( ) ) {
case NodeType_IfStatement :
computeContext ( ctx , static_cast < IfStatementAST * > ( stmt ) , line , col ) ;
break ;
case NodeType_WhileStatement :
computeContext ( ctx , static_cast < WhileStatementAST * > ( stmt ) , line , col ) ;
break ;
case NodeType_DoStatement :
computeContext ( ctx , static_cast < DoStatementAST * > ( stmt ) , line , col ) ;
break ;
case NodeType_ForStatement :
computeContext ( ctx , static_cast < ForStatementAST * > ( stmt ) , line , col ) ;
break ;
case NodeType_SwitchStatement :
computeContext ( ctx , static_cast < SwitchStatementAST * > ( stmt ) , line , col ) ;
break ;
case NodeType_TryBlockStatement :
computeContext ( ctx , static_cast < TryBlockStatementAST * > ( stmt ) , line , col ) ;
break ;
case NodeType_DeclarationStatement :
computeContext ( ctx , static_cast < DeclarationStatementAST * > ( stmt ) , line , col ) ;
break ;
case NodeType_StatementList :
computeContext ( ctx , static_cast < StatementListAST * > ( stmt ) , line , col ) ;
break ;
case NodeType_ExpressionStatement :
break ;
}
}
void CppCodeCompletion : : computeContext ( SimpleContext * & ctx , StatementListAST * ast , int line , int col ) {
if ( ! inContextScope ( ast , line , col , false , true ) )
return ;
TQPtrList < StatementAST > l ( ast - > statementList ( ) ) ;
TQPtrListIterator < StatementAST > it ( l ) ;
while ( it . current ( ) ) {
StatementAST * stmt = it . current ( ) ;
+ + it ;
computeContext ( ctx , stmt , line , col ) ;
}
}
void CppCodeCompletion : : computeContext ( SimpleContext * & ctx , IfStatementAST * ast , int line , int col ) {
if ( ! inContextScope ( ast , line , col ) )
return ;
computeContext ( ctx , ast - > condition ( ) , line , col ) ;
computeContext ( ctx , ast - > statement ( ) , line , col ) ;
computeContext ( ctx , ast - > elseStatement ( ) , line , col ) ;
}
void CppCodeCompletion : : computeContext ( SimpleContext * & ctx , ForStatementAST * ast , int line , int col ) {
if ( ! inContextScope ( ast , line , col ) )
return ;
computeContext ( ctx , ast - > initStatement ( ) , line , col ) ;
computeContext ( ctx , ast - > condition ( ) , line , col ) ;
computeContext ( ctx , ast - > statement ( ) , line , col ) ;
}
void CppCodeCompletion : : computeContext ( SimpleContext * & ctx , DoStatementAST * ast , int line , int col ) {
if ( ! inContextScope ( ast , line , col ) )
return ;
//computeContext( ctx, ast->condition(), line, col );
computeContext ( ctx , ast - > statement ( ) , line , col ) ;
}
void CppCodeCompletion : : computeContext ( SimpleContext * & ctx , WhileStatementAST * ast , int line , int col ) {
if ( ! inContextScope ( ast , line , col ) )
return ;
computeContext ( ctx , ast - > condition ( ) , line , col ) ;
computeContext ( ctx , ast - > statement ( ) , line , col ) ;
}
void CppCodeCompletion : : computeContext ( SimpleContext * & ctx , SwitchStatementAST * ast , int line , int col ) {
if ( ! inContextScope ( ast , line , col ) )
return ;
computeContext ( ctx , ast - > condition ( ) , line , col ) ;
computeContext ( ctx , ast - > statement ( ) , line , col ) ;
}
void CppCodeCompletion : : computeContext ( SimpleContext * & ctx , TryBlockStatementAST * ast , int line , int col ) {
if ( ! inContextScope ( ast , line , col ) )
return ;
computeContext ( ctx , ast - > statement ( ) , line , col ) ;
computeContext ( ctx , ast - > catchStatementList ( ) , line , col ) ;
}
void CppCodeCompletion : : computeContext ( SimpleContext * & ctx , CatchStatementListAST * ast , int line , int col ) {
/*if ( !inContextScope( ast, line, col, false, true ) )
return ; */
TQPtrList < CatchStatementAST > l ( ast - > statementList ( ) ) ;
TQPtrListIterator < CatchStatementAST > it ( l ) ;
while ( it . current ( ) ) {
CatchStatementAST * stmt = it . current ( ) ;
+ + it ;
computeContext ( ctx , stmt , line , col ) ;
}
}
void CppCodeCompletion : : computeContext ( SimpleContext * & ctx , CatchStatementAST * ast , int line , int col ) {
if ( ! ast - > statement ( ) )
return ;
if ( ! inContextScope ( ast - > statement ( ) , line , col ) )
return ;
computeContext ( ctx , ast - > condition ( ) , line , col ) ;
computeContext ( ctx , ast - > statement ( ) , line , col ) ;
}
void CppCodeCompletion : : computeContext ( SimpleContext * & ctx , DeclarationStatementAST * ast , int line , int col ) {
///@todo respect NodeType_Typedef
if ( ast - > declaration ( ) & & ast - > declaration ( ) - > nodeType ( ) = = NodeType_UsingDirective ) {
UsingDirectiveAST * usingDecl = static_cast < UsingDirectiveAST * > ( ast - > declaration ( ) ) ;
TQString name ;
if ( usingDecl - > name ( ) ) {
name = usingDecl - > name ( ) - > text ( ) ;
if ( ! name . isNull ( ) )
ctx - > addImport ( TQPair < TQString , TQString > ( " " , name ) ) ;
}
}
if ( ast - > declaration ( ) & & ast - > declaration ( ) - > nodeType ( ) = = NodeType_NamespaceAlias ) {
NamespaceAliasAST * namespaceAlias = static_cast < NamespaceAliasAST * > ( ast - > declaration ( ) ) ;
TQString name ;
if ( namespaceAlias - > namespaceName ( ) & & namespaceAlias - > aliasName ( ) ) {
ctx - > addImport ( TQPair < TQString , TQString > ( namespaceAlias - > namespaceName ( ) - > text ( ) , namespaceAlias - > aliasName ( ) - > text ( ) ) ) ;
}
}
if ( ! ast - > declaration ( ) | | ast - > declaration ( ) - > nodeType ( ) ! = NodeType_SimpleDeclaration )
return ;
if ( ! inContextScope ( ast , line , col , true , false ) )
return ;
SimpleDeclarationAST * simpleDecl = static_cast < SimpleDeclarationAST * > ( ast - > declaration ( ) ) ;
TypeSpecifierAST * typeSpec = simpleDecl - > typeSpec ( ) ;
InitDeclaratorListAST * initDeclListAST = simpleDecl - > initDeclaratorList ( ) ;
if ( ! initDeclListAST )
return ;
TQPtrList < InitDeclaratorAST > l = initDeclListAST - > initDeclaratorList ( ) ;
TQPtrListIterator < InitDeclaratorAST > it ( l ) ;
while ( it . current ( ) ) {
DeclaratorAST * d = it . current ( ) - > declarator ( ) ;
+ + it ;
if ( d - > declaratorId ( ) ) {
SimpleVariable var ;
TQStringList ptrList ;
TQPtrList < AST > ptrOpList = d - > ptrOpList ( ) ;
TQPtrList < AST > : : iterator it = ptrOpList . begin ( ) ;
for ( ; it ! = ptrOpList . end ( ) ; + + it ) {
ptrList . append ( ( * it ) - > text ( ) ) ;
}
for ( int a = 0 ; a < d - > arrayDimensionList ( ) . count ( ) ; a + + )
ptrList . append ( " * " ) ;
var . ptrList = ptrList ;
var . type = typeSpec - > text ( ) + ptrList . join ( " " ) ;
var . name = toSimpleName ( d - > declaratorId ( ) ) ;
var . comment = d - > comment ( ) ;
d - > getStartPosition ( & var . startLine , & var . startCol ) ;
d - > getEndPosition ( & var . endLine , & var . endCol ) ;
ctx - > add
( var ) ;
//kdDebug(9007) << "add variable " << var.name << " with type " << var.type << endl;
}
}
}
void CppCodeCompletion : : computeContext ( SimpleContext * & ctx , ConditionAST * ast , int line , int col ) {
if ( ! ast - > typeSpec ( ) | | ! ast - > declarator ( ) | | ! ast - > declarator ( ) - > declaratorId ( ) )
return ;
if ( ! inContextScope ( ast , line , col , true , false ) )
return ;
SimpleVariable var ;
TQStringList ptrList ;
TQPtrList < AST > ptrOpList = ast - > declarator ( ) - > ptrOpList ( ) ;
TQPtrList < AST > : : iterator it = ptrOpList . begin ( ) ;
for ( ; it ! = ptrOpList . end ( ) ; + + it ) {
ptrList . append ( ( * it ) - > text ( ) ) ;
}
var . ptrList = ptrList ;
var . type = ast - > typeSpec ( ) - > text ( ) + ptrList . join ( " " ) ;
var . name = toSimpleName ( ast - > declarator ( ) - > declaratorId ( ) ) ;
var . comment = ast - > comment ( ) ;
ast - > getStartPosition ( & var . startLine , & var . startCol ) ;
ast - > getEndPosition ( & var . endLine , & var . endCol ) ;
ctx - > add
( var ) ;
//kdDebug(9007) << "add variable " << var.name << " with type " << var.type << endl;
}
bool CppCodeCompletion : : inContextScope ( AST * ast , int line , int col , bool checkStart , bool checkEnd ) {
int startLine , startColumn ;
int endLine , endColumn ;
ast - > getStartPosition ( & startLine , & startColumn ) ;
ast - > getEndPosition ( & endLine , & endColumn ) ;
// kdDebug(9007) << k_funcinfo << endl;
// kdDebug(9007) << "current char line: " << line << " col: " << col << endl;
//
// kdDebug(9007) << nodeTypeToString( ast->nodeType() )
// << " start line: " << startLine
// << " col: " << startColumn << endl;
// kdDebug(9007) << nodeTypeToString( ast->nodeType() )
// << " end line: " << endLine
// << " col: " << endColumn << endl;
bool start = line > startLine | | ( line = = startLine & & col > = startColumn ) ;
bool end = line < endLine | | ( line = = endLine & & col < = endColumn ) ;
if ( checkStart & & checkEnd )
return start & & end ;
else if ( checkStart )
return start ;
else if ( checkEnd )
return end ;
return false ;
}
FunctionDefinitionAST * CppCodeCompletion : : functionDefinition ( AST * node ) {
while ( node ) {
if ( node - > nodeType ( ) = = NodeType_FunctionDefinition )
return static_cast < FunctionDefinitionAST * > ( node ) ;
node = node - > parent ( ) ;
}
return 0 ;
}
TQString CppCodeCompletion : : getText ( int startLine , int startColumn , int endLine , int endColumn , int omitLine ) {
if ( startLine = = endLine ) {
TQString textLine = m_activeEditor - > textLine ( startLine ) ;
return textLine . mid ( startColumn , endColumn - startColumn ) ;
}
TQStringList contents ;
for ( int line = startLine ; line < = endLine ; + + line ) {
if ( line = = omitLine )
continue ;
TQString textLine = m_activeEditor - > textLine ( line ) ;
if ( line = = startLine )
textLine = textLine . mid ( startColumn ) ;
if ( line = = endLine )
textLine = textLine . left ( endColumn ) ;
contents < < textLine ;
}
return contents . join ( " \n " ) ;
}
void CppCodeCompletion : : computeRecoveryPointsLocked ( ) {
m_pSupport - > backgroundParser ( ) - > lock ( )
;
ParsedFilePointer unit = m_pSupport - > backgroundParser ( ) - > translationUnit ( m_activeFileName ) ;
computeRecoveryPoints ( unit ) ;
m_pSupport - > backgroundParser ( ) - > unlock ( ) ;
}
void CppCodeCompletion : : computeRecoveryPoints ( ParsedFilePointer unit ) {
if ( m_blockForKeyword )
return ;
kdDebug ( 9007 ) < < " CppCodeCompletion::computeRecoveryPoints " < < endl ;
d - > recoveryPoints . clear ( ) ;
if ( ! unit )
return ;
ComputeRecoveryPoints walker ( d - > recoveryPoints ) ;
walker . parseTranslationUnit ( * unit ) ;
}
TQString codeModelAccessToString ( CodeModelItem : : Access access ) {
switch ( access ) {
case CodeModelItem : : Public :
return " public " ;
case CodeModelItem : : Protected :
return " protected " ;
case CodeModelItem : : Private :
return " private " ;
default :
return " unknown " ;
}
}
# define MAXCOMMENTCOLUMNS 45
TQString CppCodeCompletion : : commentFromItem ( const SimpleType & parent , const ItemDom & item ) {
- - m_maxComments ;
static TQString maxReached = " " ;
if ( m_maxComments < 0 ) {
return maxReached ;
}
TQString ret ;
int line , col ;
item - > getStartPosition ( & line , & col ) ;
if ( ! parent - > scope ( ) . isEmpty ( ) ) {
ret + = " Container: " + parent - > fullTypeResolvedWithScope ( ) ;
}
if ( item - > isEnum ( ) ) {
ret + = " \n Kind: Enum " ;
ret + = " \n Values: " ;
const EnumModel * en = dynamic_cast < const EnumModel * > ( item . data ( ) ) ;
if ( en ) {
EnumeratorList values = en - > enumeratorList ( ) ;
for ( EnumeratorList : : iterator it = values . begin ( ) ; it ! = values . end ( ) ; + + it ) {
ret + = " \n " + ( * it ) - > name ( ) ;
if ( ! ( * it ) - > value ( ) . isEmpty ( ) ) {
ret + " = " + ( * it ) - > value ( ) ;
}
}
ret + = " \n \n Access: " + codeModelAccessToString ( ( CodeModelItem : : Access ) en - > access ( ) ) ;
} else { }
}
if ( item - > isFunction ( ) | | item - > isFunctionDefinition ( ) ) {
const FunctionModel * f = dynamic_cast < const FunctionModel * > ( item . data ( ) ) ;
ret + = " \n Kind: Function " ;
if ( f ) {
TQString state ;
if ( f - > isStatic ( ) )
state + = " static " ;
if ( f - > isVirtual ( ) )
state + = " virtual " ;
if ( f - > isAbstract ( ) )
state + = " abstract " ;
//if( f->isTemplateable() ) state += "template ";
if ( f - > isConstant ( ) )
state + = " const " ;
if ( f - > isSlot ( ) )
state + = " slot " ;
if ( f - > isSignal ( ) )
state + = " signal " ;
if ( ! state . isEmpty ( ) )
ret + = " \n Modifiers: " + state ;
ret + = " \n Access: " + codeModelAccessToString ( ( CodeModelItem : : Access ) f - > access ( ) ) ;
}
}
if ( item - > isEnumerator ( ) ) {
const EnumeratorModel * f = dynamic_cast < const EnumeratorModel * > ( item . data ( ) ) ;
ret + = " \n Kind: Enumerator " ;
if ( f ) {
if ( ! f - > value ( ) . isEmpty ( ) )
ret + = " \n Value: " + f - > value ( ) ;
//ret += "\nAccess: " + codeModelAccessToString( f->() );
}
} else {
if ( item - > isVariable ( ) ) {
const VariableModel * f = dynamic_cast < const VariableModel * > ( item . data ( ) ) ;
if ( f ) {
if ( ! f - > isEnumeratorVariable ( ) ) {
ret + = " \n Kind: Variable " ;
if ( f - > isStatic ( ) )
ret + = " \n Modifiers: static " ;
} else {
ret + = " \n Kind: Enumerator " ;
ret + = " \n Enum: " + f - > type ( ) ;
}
ret + = " \n Access: " + codeModelAccessToString ( ( CodeModelItem : : Access ) f - > access ( ) ) ;
}
}
}
if ( item - > isTypeAlias ( ) ) {
const TypeAliasModel * t = dynamic_cast < const TypeAliasModel * > ( item . data ( ) ) ;
ret + = " \n Kind: Typedef " ;
if ( t ) {
ret + = " \n Type: " + t - > type ( ) ;
LocateResult r = parent - > locateDecType ( t - > type ( ) ) ;
if ( r . desc ( ) . resolved ( ) )
ret + = " \n Resolved type: " + r . desc ( ) . resolved ( ) - > fullTypeResolvedWithScope ( ) ;
else
ret + = " \n Partially resolved type: " + r . desc ( ) . fullNameChain ( ) ;
}
}
if ( item - > isClass ( ) ) {
ret + = " \n Kind: Class " ;
}
ret + = TQString ( " \n File: %1 \n Line: %2 Column: %3 " ) . arg ( prepareTextForMenu ( item - > fileName ( ) , 3 , MAXCOMMENTCOLUMNS ) . join ( " \n " ) ) . arg ( line ) . arg ( col ) ;
if ( ! item - > comment ( ) . isEmpty ( ) )
ret + = " \n \n " + prepareTextForMenu ( item - > comment ( ) , 3 , MAXCOMMENTCOLUMNS ) . join ( " \n " ) ;
return ret ;
}
TQString CppCodeCompletion : : commentFromTag ( const SimpleType & parent , Tag & tag ) {
- - m_maxComments ;
static TQString maxReached = " " ;
if ( m_maxComments < 0 ) {
return maxReached ;
}
int line , col ;
tag . getStartPosition ( & line , & col ) ;
TQString ret ; // = tag.comment();
if ( ! parent - > scope ( ) . isEmpty ( ) ) {
ret + = " Container: " + parent - > fullTypeResolvedWithScope ( ) ;
}
/*
if ( tag . kind ( ) = = Tag : : Kind_Enum ) {
ret + = " \n Kind: Enum " ;
ret + = " \n Values: " ;
EnumModel * en = dynamic_cast < EnumModel * > ( item . data ( ) ) ;
if ( en ) {
EnumeratorList values = en - > enumeratorList ( ) ;
for ( EnumeratorList : : iterator it = values . begin ( ) ; it ! = values . end ( ) ; + + it )
{
ret + = " \n " + ( * it ) - > name ( ) ;
if ( ! ( * it ) - > value ( ) . isEmpty ( ) ) {
ret + " = " + ( * it ) - > value ( ) ;
}
}
ret + = " \n \n Access: " + codeModelAccessToString ( ( CodeModelItem : : Access ) en - > access ( ) ) ;
} else {
}
} */
if ( tag . kind ( ) = = Tag : : Kind_Function | | tag . kind ( ) = = Tag : : Kind_FunctionDeclaration ) {
CppFunction < Tag > function ( tag ) ;
ret + = " \n Kind: Function " ;
TQString state ;
if ( function . isStatic ( ) )
state + = " static " ;
if ( function . isVirtual ( ) )
state + = " virtual " ;
//if( function.isVolatile() ) state += "volatile ";
if ( function . isConst ( ) )
state + = " const " ;
if ( function . isSlot ( ) )
state + = " slot " ;
if ( function . isSignal ( ) )
state + = " signal " ;
if ( ! state . isEmpty ( ) )
ret + = " \n Modifiers: " + state ;
ret + = " \n Access: " + TagUtils : : accessToString ( function . access ( ) ) ;
}
/*if( item->isEnumerator() ) {
EnumeratorModel * f = dynamic_cast < EnumeratorModel * > ( item . data ( ) ) ;
ret + = " \n Kind: Enumerator " ;
if ( f ) {
if ( ! f - > value ( ) . isEmpty ( ) )
ret + = " \n Value: " + f - > value ( ) ;
//ret += "\nAccess: " + codeModelAccessToString( f->() );
}
} else {
if ( item - > isVariable ( ) ) {
VariableModel * f = dynamic_cast < VariableModel * > ( item . data ( ) ) ;
ret + = " \n Kind: Variable " ;
if ( f ) {
ret + = " \n Access: " + codeModelAccessToString ( ( CodeModelItem : : Access ) f - > access ( ) ) ;
}
}
} */
if ( tag . kind ( ) = = Tag : : Kind_Enum ) {
CppVariable < Tag > var ( tag ) ;
ret + = " \n Kind: Enum " ;
}
if ( tag . kind ( ) = = Tag : : Kind_Enumerator ) {
CppVariable < Tag > var ( tag ) ;
ret + = " \n Kind: Enumerator " ;
if ( tag . hasAttribute ( " enum " ) & & tag . attribute ( " enum " ) . asString ( ) ! = " int " )
ret + = " \n Enum: " + tag . attribute ( " enum " ) . asString ( ) ;
}
if ( tag . kind ( ) = = Tag : : Kind_Variable ) {
CppVariable < Tag > var ( tag ) ;
ret + = " \n Kind: Variable " ;
if ( var . isStatic ( ) )
ret + = " \n Modifiers: static " ;
ret + = " \n Access: " + TagUtils : : accessToString ( var . access ( ) ) ;
}
if ( tag . kind ( ) = = Tag : : Kind_Typedef ) {
ret + = " \n Kind: Typedef " ;
ret + = " \n Type: " + tagType ( tag ) ;
LocateResult r = parent - > locateDecType ( tagType ( tag ) ) ;
if ( r . desc ( ) . resolved ( ) )
ret + = " \n Resolved type: " + r . desc ( ) . resolved ( ) - > fullTypeResolvedWithScope ( ) ;
else
ret + = " \n Partially resolved type: " + r . desc ( ) . fullNameChain ( ) ;
}
if ( tag . kind ( ) = = Tag : : Kind_Class ) {
ret + = " \n Kind: Class " ;
}
if ( tag . kind ( ) = = Tag : : Kind_Struct ) {
ret + = " \n Kind: Struct " ;
}
ret + = TQString ( " \n File: %1 \n Line: %2 Column: %3 " ) . arg ( prepareTextForMenu ( tag . fileName ( ) , 3 , MAXCOMMENTCOLUMNS ) . join ( " \n " ) ) . arg ( line ) . arg ( col ) ;
if ( ! tag . comment ( ) . isEmpty ( ) ) {
ret + = " \n \n " + prepareTextForMenu ( tag . comment ( ) , 20 , MAXCOMMENTCOLUMNS ) . join ( " \n " ) ;
}
return ret ;
}
void CppCodeCompletion : : computeCompletionEntryList ( SimpleType typeR , TQValueList < CodeCompletionEntry > & entryList , const TQStringList & type , SimpleTypeNamespace * ns , std : : set < HashedString > & ignore , bool isInstance , int depth ) {
HashedString myName = HashedString ( ns - > scope ( ) . join ( " :: " ) + " % " + typeid ( * ns ) . name ( ) ) ;
if ( ignore . find ( myName ) ! = ignore . end ( ) )
return ;
ignore . insert ( myName ) ;
SimpleTypeNamespace : : SlaveList slaves = ns - > getSlaves ( getIncludeFiles ( ) ) ;
for ( SimpleTypeNamespace : : SlaveList : : iterator it = slaves . begin ( ) ; it ! = slaves . end ( ) ; + + it ) {
SimpleTypeNamespace * nns = dynamic_cast < SimpleTypeNamespace * > ( ( * it ) . first . first . resolved ( ) . data ( ) ) ;
if ( ! nns ) {
if ( ( * it ) . first . first . resolved ( ) ) computeCompletionEntryList ( SimpleType ( ( * it ) . first . first . resolved ( ) ) , entryList , ( * it ) . first . first . resolved ( ) - > scope ( ) , isInstance , depth ) ;
} else {
if ( ( * it ) . first . first . resolved ( ) ) computeCompletionEntryList ( SimpleType ( ( * it ) . first . first . resolved ( ) ) , entryList , ( * it ) . first . first . resolved ( ) - > scope ( ) , nns , ignore , isInstance , depth ) ;
}
}
}
void CppCodeCompletion : : computeCompletionEntryList ( SimpleType typeR , TQValueList < CodeCompletionEntry > & entryList , const TQStringList & type , bool isInstance , int depth ) {
dbgState . setState ( disableVerboseForCompletionList ) ;
Debug d ( " #cel# " ) ;
if ( ! safetyCounter | | ! d )
return ;
SimpleTypeImpl * m = & ( * typeR ) ;
if ( SimpleTypeNamespace * ns = dynamic_cast < SimpleTypeNamespace * > ( m ) ) {
std : : set < HashedString > ignore ;
computeCompletionEntryList ( typeR , entryList , type , ns , ignore , isInstance , depth ) ;
} else if ( dynamic_cast < SimpleTypeCodeModel * > ( m ) ) {
ItemDom item = ( dynamic_cast < SimpleTypeCodeModel * > ( m ) ) - > item ( ) ;
if ( item )
if ( ClassModel * mod = dynamic_cast < ClassModel * > ( & ( * item ) ) )
computeCompletionEntryList ( typeR , entryList , ClassDom ( mod ) , isInstance , depth ) ;
} else {
TQValueList < Catalog : : QueryArgument > args ;
TQValueList < Tag > tags ;
TQStringList ts = type ;
if ( ! ts . isEmpty ( ) ) {
TQString s = ts . back ( ) + typeR - > specialization ( ) ;
ts . pop_back ( ) ;
ts . push_back ( s ) ;
}
args . clear ( ) ;
args < < Catalog : : QueryArgument ( " kind " , Tag : : Kind_FunctionDeclaration )
< < Catalog : : QueryArgument ( " scope " , ts ) ;
tags = m_repository - > query ( args ) ;
computeCompletionEntryList ( typeR , entryList , tags , isInstance , depth ) ;
args . clear ( ) ;
args < < Catalog : : QueryArgument ( " kind " , Tag : : Kind_Variable )
< < Catalog : : QueryArgument ( " scope " , ts ) ;
tags = m_repository - > query ( args ) ;
computeCompletionEntryList ( typeR , entryList , tags , isInstance , depth ) ;
if ( ! isInstance ) {
args . clear ( ) ;
args < < Catalog : : QueryArgument ( " kind " , Tag : : Kind_Enumerator )
< < Catalog : : QueryArgument ( " scope " , ts ) ;
tags = m_repository - > query ( args ) ;
computeCompletionEntryList ( typeR , entryList , tags , isInstance , depth ) ;
args . clear ( ) ;
args < < Catalog : : QueryArgument ( " kind " , Tag : : Kind_Enum )
< < Catalog : : QueryArgument ( " scope " , ts ) ;
tags = m_repository - > query ( args ) ;
computeCompletionEntryList ( typeR , entryList , tags , isInstance , depth ) ;
args . clear ( ) ;
args < < Catalog : : QueryArgument ( " kind " , Tag : : Kind_Typedef )
< < Catalog : : QueryArgument ( " scope " , ts ) ;
tags = m_repository - > query ( args ) ;
computeCompletionEntryList ( typeR , entryList , tags , isInstance , depth ) ;
args . clear ( ) ;
args < < Catalog : : QueryArgument ( " kind " , Tag : : Kind_Class )
< < Catalog : : QueryArgument ( " scope " , ts ) ;
tags = m_repository - > query ( args ) ;
computeCompletionEntryList ( typeR , entryList , tags , isInstance , depth ) ;
args . clear ( ) ;
args < < Catalog : : QueryArgument ( " kind " , Tag : : Kind_Struct )
< < Catalog : : QueryArgument ( " scope " , ts ) ;
tags = m_repository - > query ( args ) ;
computeCompletionEntryList ( typeR , entryList , tags , isInstance , depth ) ;
}
args . clear ( ) ;
args < < Catalog : : QueryArgument ( " kind " , Tag : : Kind_Base_class ) ;
TQString fullname = type . join ( " :: " ) + typeR - > specialization ( ) ;
/* if( fullname.length() >=2 )
args < < Catalog : : QueryArgument ( " prefix " , fullname . left ( 2 ) ) ; */
args < < Catalog : : QueryArgument ( " name " , fullname ) ;
TQValueList < LocateResult > parents = typeR - > getBases ( ) ;
for ( TQValueList < LocateResult > : : Iterator it = parents . begin ( ) ; it ! = parents . end ( ) ; + + it ) {
if ( ! ( * it ) - > resolved ( ) )
continue ;
SimpleType tp = SimpleType ( ( * it ) - > resolved ( ) ) ;
if ( tp )
computeCompletionEntryList ( tp , entryList , tp . scope ( ) , isInstance , depth + 1 ) ;
}
}
dbgState . setState ( true ) ;
}
void CppCodeCompletion : : computeCompletionEntryList ( SimpleType type , TQValueList < CodeCompletionEntry > & entryList , TQValueList < Tag > & tags , bool isInstance , int depth ) {
Debug d ( " #cel# " ) ;
if ( ! safetyCounter | | ! d )
return ;
TQString className = type - > desc ( ) . name ( ) ;
bool isNs = type - > isNamespace ( ) ;
CompTypeProcessor proc ( type , m_pSupport - > codeCompletionConfig ( ) - > processFunctionArguments ( ) & & type - > usingTemplates ( ) ) ;
bool resolve = m_pSupport - > codeCompletionConfig ( ) - > processPrimaryTypes ( ) & & type - > usingTemplates ( ) ;
TQValueList < Tag > : : Iterator it = tags . begin ( ) ;
while ( it ! = tags . end ( ) ) {
Tag & tag = * it ;
+ + it ;
int subSorting = 0 ;
if ( tag . name ( ) . isEmpty ( ) ) {
continue ;
} else if ( m_completionMode ! = NormalCompletion ) {
if ( tag . kind ( ) ! = Tag : : Kind_FunctionDeclaration )
continue ;
}
if ( tag . kind ( ) = = Tag : : Kind_Function | | tag . kind ( ) = = Tag : : Kind_FunctionDeclaration ) {
CppFunction < Tag > info ( tag ) ;
if ( m_completionMode = = SlotCompletion & & ! info . isSlot ( ) )
continue ;
else if ( m_completionMode = = SignalCompletion & & ! info . isSignal ( ) )
continue ;
else if ( m_completionMode = = VirtualDeclCompletion & & ! info . isVirtual ( ) )
continue ;
if ( info . isConst ( ) )
subSorting = 1 ;
if ( info . isSlot ( ) )
subSorting = 2 ;
if ( info . isSignal ( ) )
subSorting = 3 ;
if ( info . isVirtual ( ) )
subSorting = 4 ;
if ( info . isStatic ( ) )
subSorting = 5 ;
}
CodeCompletionEntry e = CodeInformationRepository : : toEntry ( tag , m_completionMode , & proc ) ;
TagFlags fl ;
fl . flags = tag . flags ( ) ;
int num = fl . data . access ;
TQString str = " public " ;
if ( num ! = 0 ) {
str = TagUtils : : accessToString ( num ) ;
} else {
num = 0 ;
}
// 0 = protected, 1 = public, 2 = private
if ( str = = " public " )
num = 0 ;
else if ( str = = " protected " )
num = 1 ;
else if ( str = = " private " )
num = 2 ;
int sortPosition = 0 ;
switch ( tag . kind ( ) ) {
case Tag : : Kind_Enum :
sortPosition = 3 ;
if ( isInstance )
continue ;
break ;
case Tag : : Kind_Enumerator :
sortPosition = 4 ;
if ( isInstance )
continue ;
break ;
case Tag : : Kind_Struct :
case Tag : : Kind_Union :
case Tag : : Kind_Class :
sortPosition = 5 ;
if ( isInstance )
continue ;
break ;
case Tag : : Kind_VariableDeclaration :
case Tag : : Kind_Variable :
sortPosition = 2 ;
if ( ! isInstance & & ! CppVariable < Tag > ( tag ) . isStatic ( ) & & ! isNs )
continue ;
break ;
case Tag : : Kind_FunctionDeclaration :
case Tag : : Kind_Function :
sortPosition = 1 ;
if ( ! isInstance & & ! CppFunction < Tag > ( tag ) . isStatic ( ) & & ! isNs )
continue ;
break ;
case Tag : : Kind_Typedef :
sortPosition = 6 ;
if ( isInstance )
continue ;
break ;
}
e . userdata = TQString ( " %1%2%3%4%5 " ) . arg ( num ) . arg ( depth ) . arg ( className ) . arg ( sortPosition ) . arg ( subSorting ) ;
if ( m_completionMode ! = SignalCompletion ) {
if ( ! type - > isNamespace ( ) ) {
if ( num = = 1 )
e . postfix + = " ; (protected) " ; // in " + proc.parentType() + ")";
if ( num = = 2 )
e . postfix + = " ; (private) " ; // in " + proc.parentType() + ")";
}
}
TQString prefix = tagType ( tag ) . stripWhiteSpace ( ) ;
if ( tag . kind ( ) = = Tag : : Kind_Enumerator & & tag . hasAttribute ( " enum " ) ) {
prefix = tag . attribute ( " enum " ) . asString ( ) ;
e . userdata + = prefix ; ///Sort enumerators together
} else if ( tag . kind ( ) = = Tag : : Kind_Enum ) {
prefix = " enum " ;
} else {
if ( tag . kind ( ) = = Tag : : Kind_FunctionDeclaration | | tag . kind ( ) = = Tag : : Kind_Function | | tag . kind ( ) = = Tag : : Kind_Variable | | tag . kind ( ) = = Tag : : Kind_Typedef ) {
if ( ! prefix . isEmpty ( ) & & resolve ) {
LocateResult et = type - > locateDecType ( prefix ) ;
if ( et )
prefix = et - > fullNameChain ( ) ;
}
}
if ( tag . kind ( ) = = Tag : : Kind_FunctionDeclaration | | tag . kind ( ) = = Tag : : Kind_Function ) {
if ( prefix . isEmpty ( ) ) {
if ( tag . name ( ) = = className )
prefix = constructorPrefix ;
else if ( tag . name ( ) . startsWith ( " ~ " ) )
prefix = destructorPrefix ;
}
}
if ( tag . kind ( ) = = Tag : : Kind_Class | | tag . kind ( ) = = Tag : : Kind_Function )
prefix = " " ;
}
e . comment = commentFromTag ( type , tag ) ;
if ( e . prefix . isEmpty ( ) )
e . prefix = prefix ;
else
e . prefix + = " " + prefix ;
e . prefix = e . prefix . stripWhiteSpace ( ) ;
e . prefix = stringMult ( depth , " " ) + e . prefix . stripWhiteSpace ( ) ;
e . text = e . text . stripWhiteSpace ( ) ;
if ( str ! = " private " )
entryList < < e ;
}
}
void CppCodeCompletion : : computeCompletionEntryList ( SimpleType type , TQValueList < CodeCompletionEntry > & entryList , ClassDom klass , bool isInstance , int depth ) {
Debug d ( " #cel# " ) ;
if ( ! safetyCounter | | ! d )
return ;
computeCompletionEntryList ( type , entryList , klass - > functionList ( ) , isInstance , depth ) ;
///Find all function-definitions that have no functions. Those may be inlined functions and need to be treated too.
FunctionDefinitionList definitions = klass - > functionDefinitionList ( ) ;
FunctionList l ;
TQStringList classScope = klass - > scope ( ) ;
classScope < < klass - > name ( ) ;
for ( FunctionDefinitionList : : iterator it = definitions . begin ( ) ; it ! = definitions . end ( ) ; + + it ) {
FunctionList fl = klass - > functionByName ( ( * it ) - > name ( ) ) ;
ArgumentList args = ( * it ) - > argumentList ( ) ;
if ( ! l . isEmpty ( ) ) {
bool matched = false ;
for ( FunctionList : : iterator it = fl . begin ( ) ; it ! = fl . end ( ) ; + + it ) {
ArgumentList fArgs = ( * it ) - > argumentList ( ) ;
if ( fArgs . count ( ) ! = args . count ( ) )
continue ;
ArgumentList : : iterator it3 = args . begin ( ) ;
ArgumentList : : iterator it2 = fArgs . begin ( ) ;
bool hit = true ;
while ( it3 ! = args . end ( ) ) {
if ( ( * it3 ) - > type ( ) ! = ( * it2 ) - > type ( ) ) {
hit = false ;
break ;
}
+ + it3 ;
+ + it2 ;
}
if ( hit ) {
matched = true ;
break ;
}
}
if ( matched )
continue ;
}
///The function-definition belongs to some sub-class
if ( ( * it ) - > scope ( ) ! = classScope & & ! ( * it ) - > scope ( ) . isEmpty ( ) ) continue ;
l < < ( FunctionModel * ) ( * it ) . data ( ) ;
}
if ( ! l . isEmpty ( ) )
computeCompletionEntryList ( type , entryList , l , isInstance , depth ) ;
if ( m_completionMode = = NormalCompletion )
computeCompletionEntryList ( type , entryList , klass - > variableList ( ) , isInstance , depth ) ;
if ( ! isInstance ) {
computeCompletionEntryList ( klass - > name ( ) , type , entryList , klass - > classList ( ) , isInstance , depth ) ;
computeCompletionEntryList ( klass - > name ( ) , type , entryList , klass - > typeAliasList ( ) , isInstance , depth ) ;
}
TQValueList < LocateResult > parents = type - > getBases ( ) ;
for ( TQValueList < LocateResult > : : Iterator it = parents . begin ( ) ; it ! = parents . end ( ) ; + + it ) {
if ( ! ( * it ) - > resolved ( ) )
continue ;
SimpleTypeImpl * i = ( * it ) - > resolved ( ) ;
computeCompletionEntryList ( i , entryList , i - > scope ( ) , isInstance , depth + 1 ) ;
/*
SimpleTypeCodeModel * m = dynamic_cast < SimpleTypeCodeModel * > ( i ) ;
if ( m ) {
ItemDom item = m - > item ( ) ;
ClassModel * kl = dynamic_cast < ClassModel * > ( & ( * item ) ) ;
if ( kl ) {
computeCompletionEntryList ( SimpleType ( ( * it ) - > resolved ( ) ) , entryList , ClassDom ( kl ) , isInstance , depth + 1 ) ;
}
} */
}
}
void CppCodeCompletion : : computeCompletionEntryList ( SimpleType type , TQValueList < CodeCompletionEntry > & entryList , NamespaceDom scope , bool isInstance , int depth ) {
Debug d ( " #cel# " ) ;
if ( ! safetyCounter | | ! d )
return ;
CppCodeCompletionConfig * cfg = m_pSupport - > codeCompletionConfig ( ) ;
computeCompletionEntryList ( type , entryList , ClassDom ( scope . data ( ) ) , isInstance , depth ) ;
if ( ! isInstance )
computeCompletionEntryList ( type , entryList , scope - > namespaceList ( ) , isInstance , depth ) ;
}
void CppCodeCompletion : : computeCompletionEntryList ( TQString parent , SimpleType type , TQValueList < CodeCompletionEntry > & entryList , const ClassList & lst , bool isInstance , int depth ) {
Debug d ( " #cel# " ) ;
if ( ! safetyCounter | | ! d )
return ;
ClassList : : ConstIterator it = lst . begin ( ) ;
while ( it ! = lst . end ( ) ) {
ClassDom klass = * it ;
+ + it ;
CodeCompletionEntry entry ;
entry . prefix = " class " ;
entry . prefix = stringMult ( depth , " " ) + entry . prefix . stripWhiteSpace ( ) ;
entry . text = klass - > name ( ) ;
entry . comment = commentFromItem ( type , klass . data ( ) ) ;
if ( isInstance )
continue ;
entry . userdata = TQString ( " %1%2%3%4%5 " ) . arg ( CodeModelItem : : Public ) . arg ( depth ) . arg ( parent ) . arg ( 6 ) ;
entryList < < entry ;
// if ( cfg->includeTypes() )
/*{
computeCompletionEntryList ( type , entryList , klass - > classList ( ) , isInstance , depth ) ;
} */
}
}
void CppCodeCompletion : : computeCompletionEntryList ( TQString parent , SimpleType type , TQValueList < CodeCompletionEntry > & entryList , const TypeAliasList & lst , bool isInstance , int depth ) {
Debug d ( " #cel# " ) ;
if ( ! safetyCounter | | ! d )
return ;
TypeAliasList : : ConstIterator it = lst . begin ( ) ;
while ( it ! = lst . end ( ) ) {
TypeAliasDom klass = * it ;
+ + it ;
CodeCompletionEntry entry ;
LocateResult et = type - > locateDecType ( klass - > type ( ) ) ;
if ( et )
entry . prefix = " typedef " + et - > fullNameChain ( ) ;
else
entry . prefix = " typedef " + klass - > type ( ) ;
entry . prefix = stringMult ( depth , " " ) + entry . prefix . stripWhiteSpace ( ) ;
entry . text = klass - > name ( ) ;
entry . comment = commentFromItem ( type , klass . data ( ) ) ;
entry . userdata = TQString ( " %1%2%3%4%5 " ) . arg ( CodeModelItem : : Public ) . arg ( depth ) . arg ( parent ) . arg ( 5 ) ;
entryList < < entry ;
}
}
void CppCodeCompletion : : computeCompletionEntryList ( SimpleType type , TQValueList < CodeCompletionEntry > & entryList , const NamespaceList & lst , bool /*isInstance*/ , int depth ) {
Debug d ( " #cel# " ) ;
if ( ! safetyCounter | | ! d )
return ;
NamespaceList : : ConstIterator it = lst . begin ( ) ;
while ( it ! = lst . end ( ) ) {
NamespaceDom scope = * it ;
+ + it ;
CodeCompletionEntry entry ;
entry . prefix = " namespace " ;
entry . prefix = stringMult ( depth , " " ) + entry . prefix . stripWhiteSpace ( ) ;
entry . text = scope - > name ( ) ;
entry . comment = commentFromItem ( type , scope . data ( ) ) ;
entryList < < entry ;
}
}
void CppCodeCompletion : : computeCompletionEntryList ( SimpleType type , TQValueList < CodeCompletionEntry > & entryList , const FunctionList & methods , bool isInstance , int depth ) {
Debug d ( " #cel# " ) ;
if ( ! safetyCounter | | ! d )
return ;
TQString className = type - > desc ( ) . name ( ) ;
bool isNs = type - > isNamespace ( ) ;
bool resolve = type - > usingTemplates ( ) & & m_pSupport - > codeCompletionConfig ( ) - > processPrimaryTypes ( ) ;
CompTypeProcessor proc ( type , m_pSupport - > codeCompletionConfig ( ) - > processFunctionArguments ( ) & & type - > usingTemplates ( ) ) ;
FunctionList : : ConstIterator it = methods . begin ( ) ;
while ( it ! = methods . end ( ) ) {
FunctionDom meth = * it ;
+ + it ;
if ( isInstance & & meth - > isStatic ( ) )
continue ;
else if ( m_completionMode = = SignalCompletion & & ! meth - > isSignal ( ) )
continue ;
else if ( m_completionMode = = SlotCompletion & & ! meth - > isSlot ( ) )
continue ;
else if ( m_completionMode = = VirtualDeclCompletion & & ! meth - > isVirtual ( ) )
continue ;
if ( ! isInstance & & ! meth - > isStatic ( ) & & ! isNs )
continue ;
CodeCompletionEntry entry ;
entry . comment = commentFromItem ( type , model_cast < ItemDom > ( meth ) ) ;
if ( ! resolve ) {
entry . prefix = meth - > resultType ( ) ;
} else {
TQString tt = meth - > resultType ( ) ;
LocateResult t = type - > locateDecType ( tt ) ;
if ( t ) {
entry . prefix = t - > fullNameChain ( ) ;
} else
entry . prefix = meth - > resultType ( ) ;
}
if ( entry . prefix . isEmpty ( ) & & meth - > name ( ) = = className )
entry . prefix = constructorPrefix ;
if ( entry . prefix . isEmpty ( ) & & meth - > name ( ) . startsWith ( " ~ " ) )
entry . prefix = destructorPrefix ;
entry . prefix = stringMult ( depth , " " ) + entry . prefix . stripWhiteSpace ( ) ;
TQString text ;
ArgumentList args = meth - > argumentList ( ) ;
ArgumentList : : Iterator argIt = args . begin ( ) ;
/*
if ( m_completionMode = = VirtualDeclCompletion )
{
//Ideally the type info would be a entry.prefix, but we need them to be
//inserted upon completion so they have to be part of entry.text
entry . text = meth - > resultType ( ) ;
entry . text + = " " ;
entry . text + = meth - > name ( ) ;
}
else */
entry . text = meth - > name ( ) ;
entry . text + = formattedOpeningParenthesis ( args . size ( ) = = 0 ) ;
while ( argIt ! = args . end ( ) ) {
ArgumentDom arg = * argIt ;
+ + argIt ;
text + = proc . processType ( arg - > type ( ) ) ;
if ( m_completionMode = = NormalCompletion | |
m_completionMode = = VirtualDeclCompletion )
text + = TQString ( " " ) + arg - > name ( ) ;
if ( argIt ! = args . end ( ) )
text + = " , " ;
}
if ( args . size ( ) = = 0 ) {
entry . text + = formattedClosingParenthesis ( true ) ;
} else {
text + = formattedClosingParenthesis ( false ) ;
}
int subSorting = 0 ;
if ( meth - > isConstant ( ) )
subSorting = 1 ;
if ( meth - > isSlot ( ) )
subSorting = 2 ;
if ( meth - > isSignal ( ) )
subSorting = 3 ;
if ( meth - > isVirtual ( ) )
subSorting = 4 ;
if ( meth - > isStatic ( ) )
subSorting = 5 ;
entry . userdata + = TQString ( " %1%2%3%4%5 " ) . arg ( meth - > access ( ) ) . arg ( depth ) . arg ( className ) . arg ( 1 ) . arg ( subSorting ) ;
if ( m_completionMode = = VirtualDeclCompletion )
entry . text + = text + " ; " ;
if ( m_completionMode ! = NormalCompletion )
entry . text + = text ;
else
entry . postfix = text ;
if ( meth - > isConstant ( ) )
entry . postfix + = " const " ;
if ( m_completionMode ! = SignalCompletion ) {
if ( ! type - > isNamespace ( ) ) {
if ( meth - > access ( ) = = CodeModelItem : : Protected )
entry . postfix + = " ; (protected) " ; // in " + type->fullType() + ")";
if ( meth - > access ( ) = = CodeModelItem : : Private )
entry . postfix + = " ; (private) " ; // in " + type->fullType() + ")";
}
}
entry . text = entry . text . stripWhiteSpace ( ) ;
entryList < < entry ;
}
}
void CppCodeCompletion : : computeCompletionEntryList ( SimpleType type , TQValueList < CodeCompletionEntry > & entryList , const VariableList & attributes , bool isInstance , int depth ) {
Debug d ( " #cel# " ) ;
TQString className = type - > desc ( ) . name ( ) ;
bool isNs = type - > isNamespace ( ) ;
if ( ! safetyCounter | | ! d )
return ;
if ( m_completionMode ! = NormalCompletion )
return ;
bool resolve = type - > usingTemplates ( ) & & m_pSupport - > codeCompletionConfig ( ) - > processPrimaryTypes ( ) ;
VariableList : : ConstIterator it = attributes . begin ( ) ;
while ( it ! = attributes . end ( ) ) {
VariableDom attr = * it ;
+ + it ;
if ( isInstance & & attr - > isStatic ( ) )
continue ;
if ( ! isInstance & & ! attr - > isStatic ( ) & & ! isNs )
continue ;
CodeCompletionEntry entry ;
entry . text = attr - > name ( ) ;
entry . comment = commentFromItem ( type , model_cast < ItemDom > ( attr ) ) ;
entry . userdata + = TQString ( " %1%2%3%4 " ) . arg ( attr - > access ( ) ) . arg ( depth ) . arg ( className ) . arg ( 2 ) ;
if ( ! attr - > isEnumeratorVariable ( ) ) {
if ( ! resolve ) {
entry . prefix = attr - > type ( ) ;
} else {
TQString tt = attr - > type ( ) ;
LocateResult t = type - > locateDecType ( tt ) ;
//SimpleType t = type->typeOf( attr->name() );
if ( t )
entry . prefix = t - > fullNameChain ( ) ;
else
entry . prefix = attr - > type ( ) ;
}
} else {
entry . prefix = attr - > type ( ) ;
entry . userdata + = attr - > type ( ) ; ///Sort enumerators by their enum
}
if ( attr - > access ( ) = = CodeModelItem : : Protected )
entry . postfix + = " ; (protected) " ; // in " + type->fullType() + ")";
if ( attr - > access ( ) = = CodeModelItem : : Private )
entry . postfix + = " ; (private) " ; // in " + type->fullType() + ")";
entry . prefix = stringMult ( depth , " " ) + entry . prefix . stripWhiteSpace ( ) ;
entryList < < entry ;
}
}
void CppCodeCompletion : : computeCompletionEntryList ( TQValueList < CodeCompletionEntry > & entryList , SimpleContext * ctx , bool /*isInstance*/ , int depth ) {
Debug d ( " #cel# " ) ;
if ( ! safetyCounter | | ! d )
return ;
while ( ctx ) {
TQValueList < SimpleVariable > vars = ctx - > vars ( ) ;
TQValueList < SimpleVariable > : : ConstIterator it = vars . begin ( ) ;
while ( it ! = vars . end ( ) ) {
const SimpleVariable & var = * it ;
+ + it ;
CodeCompletionEntry entry ;
entry . prefix = var . type . fullNameChain ( ) ;
entry . text = var . name ;
entry . userdata = " 000 " ;
entry . comment = " Local variable " ;
entryList < < entry ;
}
ctx = ctx - > prev ( ) ;
}
}
EvaluationResult CppCodeCompletion : : evaluateExpression ( ExpressionInfo expr , SimpleContext * ctx ) {
safetyCounter . init ( ) ;
//d->classNameList = typeNameList( m_pSupport->codeModel() );
CppEvaluation : : ExpressionEvaluation obj ( this , expr , AllOperators , getIncludeFiles ( ) , ctx ) ;
EvaluationResult res ;
res = obj . evaluate ( ) ;
TQString resolutionType = " (resolved) " ;
if ( ! res - > resolved ( ) ) {
if ( BuiltinTypes : : isBuiltin ( res . resultType ) ) {
resolutionType = " (builtin " + BuiltinTypes : : comment ( res . resultType ) + " ) " ;
} else {
resolutionType = " (unresolved) " ;
}
}
addStatusText ( i18n ( " Type of \" %1 \" is \" %2 \" , %3 " ) . arg ( expr . expr ( ) ) . arg ( res - > fullNameChain ( ) ) . arg ( resolutionType ) , 5000 ) ;
return res ;
}
void CppCodeCompletion : : computeFileEntryList ( ) {
m_fileEntryList . clear ( ) ;
TQStringList fileList = m_pSupport - > project ( ) - > allFiles ( ) ;
for ( TQStringList : : Iterator it = fileList . begin ( ) ; it ! = fileList . end ( ) ; + + it ) {
if ( ! m_pSupport - > isHeader ( * it ) )
continue ;
CodeCompletionEntry entry ;
entry . text = TQFileInfo ( * it ) . fileName ( ) ;
m_fileEntryList . push_back ( entry ) ;
}
m_fileEntryList = unique ( m_fileEntryList ) ;
}
HashedStringSet CppCodeCompletion : : getIncludeFiles ( const TQString & fi ) {
TQString file = fi ;
if ( file . isEmpty ( ) )
file = m_activeFileName ;
FileDom f = m_pSupport - > codeModel ( ) - > fileByName ( file ) ;
if ( f ) {
ParseResultPointer p = f - > parseResult ( ) ;
if ( p ) {
ParsedFilePointer pp = dynamic_cast < ParsedFile * > ( p . data ( ) ) ;
if ( pp ) {
return pp - > includeFiles ( ) ;
}
}
}
return HashedStringSet ( ) ;
}
void CppCodeCompletion : : slotJumpToDeclCursorContext ( )
{
kdDebug ( 9007 ) < < k_funcinfo < < endl ;
jumpCursorContext ( Declaration ) ;
}
void CppCodeCompletion : : slotJumpToDefCursorContext ( )
{
kdDebug ( 9007 ) < < k_funcinfo < < endl ;
jumpCursorContext ( Definition ) ;
}
void CppCodeCompletion : : jumpCursorContext ( FunctionType f )
{
if ( ! m_activeCursor ) return ;
SimpleTypeConfiguration conf ( m_activeFileName ) ;
unsigned int line ;
unsigned int column ;
m_activeCursor - > cursorPositionReal ( & line , & column ) ;
EvaluationResult result = evaluateExpressionAt ( line , column , conf ) ;
// Determine the declaration info based on the type of item we are dealing with.
DeclarationInfo d ;
TQString includeFileName , includeFilePath ;
bool unused ;
if ( result . isMacro ) {
d . name = result . macro . name ( ) ;
d . file = result . macro . fileName ( ) ;
d . startLine = d . endLine = result . macro . line ( ) ;
d . startCol = d . endCol = result . macro . column ( ) ;
} else if ( getIncludeInfo ( line , includeFileName , includeFilePath , unused ) ) {
d . name = includeFileName ;
d . file = includeFilePath ;
} else {
d = result . sourceVariable ;
}
if ( ! d ) {
LocateResult type = result . resultType ;
if ( type & & type - > resolved ( ) ) {
// Is it a namespace?
if ( type - > resolved ( ) - > isNamespace ( ) ) {
SimpleTypeCachedNamespace * ns = dynamic_cast < SimpleTypeCachedNamespace * > ( type - > resolved ( ) . data ( ) ) ;
if ( ns ) {
SimpleTypeNamespace : : SlaveList slaves = ns - > getSlaves ( getIncludeFiles ( ) ) ;
if ( slaves . begin ( ) ! = slaves . end ( ) ) {
SimpleTypeCachedCodeModel * item = dynamic_cast < SimpleTypeCachedCodeModel * > ( ( * slaves . begin ( ) ) . first . first . resolved ( ) . data ( ) ) ;
if ( item & & item - > item ( ) & & item - > item ( ) - > isNamespace ( ) ) {
NamespaceModel * ns = dynamic_cast < NamespaceModel * > ( item - > item ( ) . data ( ) ) ;
TQStringList wholeScope = ns - > scope ( ) ;
wholeScope < < ns - > name ( ) ;
FileList files = cppSupport ( ) - > codeModel ( ) - > fileList ( ) ;
for ( FileList : : iterator it = files . begin ( ) ; it ! = files . end ( ) ; + + it ) {
NamespaceModel * ns = ( * it ) . data ( ) ;
for ( TQStringList : : iterator it2 = wholeScope . begin ( ) ; it2 ! = wholeScope . end ( ) ; + + it2 ) {
if ( ns - > hasNamespace ( ( * it2 ) ) ) {
ns = ns - > namespaceByName ( * it2 ) ;
if ( ! ns ) break ;
} else {
ns = 0 ;
break ;
}
}
if ( ns ) {
d . name = ns - > name ( ) ;
ns - > getStartPosition ( & d . startLine , & d . startCol ) ;
ns - > getEndPosition ( & d . endLine , & d . endCol ) ;
d . file = ns - > fileName ( ) ;
break ;
}
}
}
}
}
} else {
// Not a namespace, we can get the declaration info straight from the type description.
d = type - > resolved ( ) - > getDeclarationInfo ( ) ;
}
}
// Unresolved, maybe its a named enumeration?
else if ( type & & type . trace ( ) ) {
TQValueList < TQPair < SimpleTypeImpl : : MemberInfo , TypeDesc > > trace = type . trace ( ) - > trace ( ) ;
if ( ! trace . isEmpty ( ) ) {
if ( trace . begin ( ) ! = trace . end ( ) ) {
d = ( * trace . begin ( ) ) . first . decl ;
}
}
}
}
if ( d ) {
TQString fileName = d . file = = " current_file " ? m_activeFileName : d . file . operator TQString ( ) ;
if ( f = = Definition & & cppSupport ( ) - > switchHeaderImpl ( fileName , d . startLine , d . startCol ) )
return ;
cppSupport ( ) - > partController ( ) - > editDocument ( fileName , d . startLine ) ;
}
}
TQString CppCodeCompletion : : createTypeInfoString ( int line , int column )
{
TQString typeInfoString ;
SimpleTypeConfiguration conf ( m_activeFileName ) ;
EvaluationResult type = evaluateExpressionAt ( line , column , conf ) ;
if ( type . expr . expr ( ) . stripWhiteSpace ( ) . isEmpty ( ) )
return typeInfoString ;
typeInfoString + = type . expr . expr ( ) + TQString ( " : " ) ;
if ( type - > resolved ( ) )
{
TQString scope = type - > resolved ( ) - > scope ( ) . join ( " :: " ) ;
int pos = scope . findRev ( " :: " ) ;
if ( scope . isEmpty ( ) | | pos = = - 1 )
{
scope = " :: " ;
}
else
{
scope . truncate ( pos + 2 ) ;
}
typeInfoString + = scope + type - > fullNameChain ( ) + TQString ( i18n ( " (resolved) " ) ) ;
}
else
{
if ( type )
{
if ( ! BuiltinTypes : : isBuiltin ( type . resultType ) )
{
typeInfoString + = type - > fullNameChain ( ) + TQString ( i18n ( " (unresolved) " ) ) ;
}
else
{
typeInfoString + = type - > fullNameChain ( ) + " , " + BuiltinTypes : : comment ( type . resultType ) + TQString ( i18n ( " (builtin type) " ) ) ;
}
}
else
{
typeInfoString + = TQString ( i18n ( " (unresolved) " ) ) ;
}
}
if ( cppSupport ( ) & & type - > resolved ( ) & & cppSupport ( ) - > codeCompletionConfig ( ) - > preProcessAllHeaders ( ) ) {
DeclarationInfo decl = type - > resolved ( ) - > getDeclarationInfo ( ) ;
if ( ! getIncludeFiles ( ) [ HashedString ( decl . file ) ] ) {
typeInfoString + = " [header not included] " ;
}
}
return typeInfoString ;
}
bool CppCodeCompletion : : getIncludeInfo ( int line , TQString & includeFileName , TQString & includeFilePath , bool & usedProjectFiles )
{
bool isIncludeDirective = false ;
TQString lineText = getText ( line , 0 , line + 1 , 0 ) ;
TQRegExp includeRx ( " (?:#include[ \\ s]*(?: \\ \" | \\ <) ) ( [ ^ \ \ n ] * ) ( \ \ \ " | \\ >) " ) ;
if ( includeRx . search ( lineText ) ! = - 1 ) {
//It is an include-directive. The regular expression captures the string, and the closing sign('"' or '>').
isIncludeDirective = true ;
usedProjectFiles = false ;
TQStringList captured = includeRx . capturedTexts ( ) ;
if ( captured . size ( ) = = 3 ) {
Dependence d ;
d . first = captured [ 1 ] ;
d . second = captured [ 2 ] = = " \" " ? Dep_Local : Dep_Global ;
includeFilePath = cppSupport ( ) - > driver ( ) - > findIncludeFile ( d , activeFileName ( ) ) ;
if ( includeFilePath . isEmpty ( ) ) {
//A simple backup-algorithm that can only find files within the same project
includeFilePath = cppSupport ( ) - > findHeaderSimple ( d . first ) ;
usedProjectFiles = true ;
}
includeFileName = d . first ;
} else {
kdDebug ( 9007 ) < < " wrong count of captured items " < < endl ;
}
}
return isIncludeDirective ;
}
# include "cppcodecompletion.moc"